Hi

I've spotted you use a local transport. Yes, it is a test setup issue.
Specifically, you use 'piped' local transport which as far as I recall assumes a payload is available and in case of GET/DELETE it is not so you have the code hanging.
Add this property to your proxy (in jaxrs:client/jaxrs:properties):
"org.apache.cxf.transport.local.LocalConduit.directDispatch" : true

I can see that LocalTransport handler uses Boolean.TRUE to compare, so that property value needs to be a proper boolean.
Will do a minor update so that users can use String "true"...

Or you can set that property directly from the code,

WebClient.getConfig(myServiceInterface).getRequestContext().put(LocalConduit.DIRECT_DISPATCH, Boolean.TRUE);

I'll update the docs re the need to use this property with requests having no payloads when Local transport is used.

Cheers, Sergey

On 30/07/13 00:30, Tom Hartwell wrote:
I'm using CXF 2.6.6 and have not found an open issue regarding the problem
I'm seeing so I'm thinking it may be misconfiguration on my part.

I'm trying to use a CXF client in my application where I have my app wired
via Spring in XML:

test-context.xml

<beans xmlns="http://www.springframework.org/schema/beans";
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; xmlns:jaxrs="
http://cxf.apache.org/jaxrs";
     xsi:schemaLocation="
          http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
          http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
">


     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
         destroy-method="close">
         <property />
         .....
     </bean>

     <bean id="myService" class="com.MyService">
         <property name="dataSource" ref="dataSource" />
         <property name="queries">
             <map>
                 <entry key="SAVE">
                     <value>INSERT INTO ....</value>
                 </entry>
                 <entry key="UPDATE">
                     <value>UPDATE ...</value>
                 </entry>
                 <entry key="GET">
                     <value>SELECT ...</value>
                 </entry>
                 <entry key="DELETE">
                     <value>DELETE from ...</value>
                 </entry>
             </map>
         </property>
     </bean>

     <import resource="classpath:META-INF/cxf/cxf.xml" />
     <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

     <bean id="jacksonMapper"
class="com.fasterxml.jackson.databind.ObjectMapper" />

     <jaxrs:server id="myServer" address="local://localservice/">
         <jaxrs:serviceBeans>
             <ref bean="myService" />
         </jaxrs:serviceBeans>
         <jaxrs:providers>
             <bean
class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider">
                 <property name="mapper" ref="jacksonMapper" />
             </bean>
         </jaxrs:providers>
     </jaxrs:server>


     <jaxrs:client id="myClient" address="local://localservice/"
         serviceClass="com.MyServiceInterface"
         inheritHeaders="true">
         <jaxrs:headers>
             <entry key="Accept" value="application/json" />
             <entry key="ContentType" value="application/json" />
         </jaxrs:headers>
         <jaxrs:providers>
             <bean
class="com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider">
                 <property name="mapper" ref="jacksonMapper" />
             </bean>
         </jaxrs:providers>
     </jaxrs:client>
</beans>

And my Jax-RS interface is as follows:

@Path("/")
public interface MyServiceInterface {

     @GET
     @Path("/{id}")
     @Produces("application/json")
     MyObject retreiveMyObject(@PathParam("id") int id);

     @POST
     @Path("/")
     @Consumes("application/json")
     @Produces("application/json")
     Integer saveMyObject(MyObject myObject);

     @PUT
     @Path("/{id}")
     @Consumes("application/json")
     @Produces("application/json")
     Integer updateMyObject(@PathParam("id") int id, MyObject myObject);

     @DELETE
     @Path("/{id}")
     @Produces("application/json")
     Integer deleteMyObject(@PathParam("id") int id);
}

public class MyService implements MyServiceInterface {
...
}

And the test

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"test-context.xml"})
public class MyServiceTest extends Assert implements
ApplicationContextAware {

     private final Logger logger = LoggerFactory.getLogger(MyServiceTest
.class);

     ApplicationContext ctx;
     @Override
     public void setApplicationContext(ApplicationContext context) throws
BeansException {
         this.ctx = context;
     }

     @Autowired
     @Qualifier("myClient")
     public MyServiceInterface myServiceInterface;

     @Test
     public void testCrud() {
         MyObject myObject = new
MyObject().setAttr1("127.0.0.1").setAttr2(new Date());

         // THIS WORKS THROUGH THE CLIENT
         myObject.setId(myServiceInterface.saveMyObject(myObject));

         // THIS WORKS THROUGH THE CLIENT TOO
         myServiceInterface.updateMyObject(myObject.getId(), myObject
.setX(1.23f).setY(4.56f));

         // THIS DOES NOT HANG!!
         ((MyServiceInterface)ctx.getBean("myService")).deleteMyObject(1);


         // THIS HANGS
         logger.debug("BEGIN THE RETRIEVAL");
         MyObject persistedMyObject = myServiceInterface.retrieveMyObject(
myObject.getId());
         assertEquals(1.23f, persistedMyObject.getX(), 0.05);
         assertEquals(4.56f, persistedMyObject.getY(), 0.05);

         // THIS HANGS TOO??
         myServiceInterface.deleteMyObject(roomAlarm.getId());
         MyObject deletedMyObject = myServiceInterface.retrieveMyObject(
persistedMyObject.getId());

         assertNull(deletedMyObject);
     }
}

The log reads:
1728 [main] DEBUG com.MyObjectTest  - *BEGIN THE RETRIEVAL*
1728 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain  - Adding
interceptor org.apache.cxf.ws.policy.PolicyOutInterceptor@55e29b99 to phase
setup
1728 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain  - Adding
interceptor org.apache.cxf.interceptor.MessageSenderInterceptor@105585dc to
phase prepare-send
1728 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain  - Adding
interceptor org.apache.cxf.interceptor.MessageSenderInterceptor@105585dc to
phase prepare-send
1728 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain  - Chain
org.apache.cxf.phase.PhaseInterceptorChain@7691a4fb was created. Current
flow:
   setup [PolicyOutInterceptor]
   prepare-send [MessageSenderInterceptor]

1728 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain  - Invoking
handleMessage on interceptor
org.apache.cxf.ws.policy.PolicyOutInterceptor@55e29b99
1729 [main] DEBUG org.apache.cxf.ws.policy.PolicyOutInterceptor  - No
binding operation info.
1729 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain  - Invoking
handleMessage on interceptor
org.apache.cxf.interceptor.MessageSenderInterceptor@105585dc
1729 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain  - Adding
interceptor
org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor@68d36ff3to
phase prepare-send-ending
1729 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain  - Chain
org.apache.cxf.phase.PhaseInterceptorChain@7691a4fb was modified. Current
flow:
   setup [PolicyOutInterceptor]
   prepare-send [MessageSenderInterceptor]
   prepare-send-ending [MessageSenderEndingInterceptor]

1729 [main] DEBUG org.apache.cxf.phase.PhaseInterceptorChain  - Invoking
handleMessage on interceptor
org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor@68d36ff3

The save and update work just fine, and the retrieve and delete don't. If I
call the service class directly I can retrieve and delete just fine, so I
have a feeling it has to do with my configuration, but I've tried a ton of
different things to no avail.

Thanks in advance,
Tom



--
Sergey Beryozkin

Talend Community Coders
http://coders.talend.com/

Blog: http://sberyozkin.blogspot.com

Reply via email to