Thanks so much Sergey, that did the trick. While I'm happy that my test now
works, I feel like this violates the Principle of Least Surprise in setting
up a Client in this way. Is there any compelling reason to not set this
property normally?

Thanks again for identifying my problem!

-Tom


On Tue, Jul 30, 2013 at 3:40 AM, Sergey Beryozkin <[email protected]>wrote:

> Actually the wiki mentions that property so I won't update it.
> But, at the moment, you can't set that property in jaxrs:client because
> LocalConduit does not check for message contextual properties, I've just
> got it fixed but in meantime please set the property from the code
>
> Cheers, Sergey
>
> On 30/07/13 10:52, Sergey Beryozkin wrote:
>
>> 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<http://www.springframework.org/schema/beans>
>>> "
>>>      
>>> xmlns:xsi="http://www.w3.org/**2001/XMLSchema-instance<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>
>>> http://www.springframework.**org/schema/beans/spring-beans-**2.0.xsd<http://www.springframework.org/schema/beans/spring-beans-2.0.xsd>
>>>           http://cxf.apache.org/jaxrs
>>> http://cxf.apache.org/schemas/**jaxrs.xsd<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