You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Sergey Beryozkin <sb...@gmail.com> on 2013/08/02 14:02:03 UTC
Re: CXF Jax-RS Client sends POST/PUT fine, GET/DELETE hang
On 30/07/13 17:01, Sergey Beryozkin wrote:
> On 30/07/13 16:51, Tom Hartwell wrote:
>> 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?
> Hmm, good point. Local transport module has been created long before we
> started supporting RS communications and with WS a request payload is
> available in most cases so I guess I worked just fine with the
> piped-style approach.
> I'll start a dev thread, seems like using a direct dispatch style by
> default can simplify things a bit so I'll update the code unless there
> are known reasons for not doing it
FYI, Dan has fixed it such that requests with empty payloads will work
with or without this property being set up.
Cheers, Sergey
>
>>
>> Thanks again for identifying my problem!
>>
>> -Tom
>>
>>
>> On Tue, Jul 30, 2013 at 3:40 AM, Sergey Beryozkin <sberyozkin@gmail.com
>> <ma...@gmail.com>> 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
>>
>>
>