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