Invoking JAX-WS Web service from Camel - apache-camel

I need to invoke a JAX-WS Web service available on WildFly 8. I've started with a simple example to get started. Here is my Web service:
import javax.jws.WebService;
#WebService
public class HelloWorld implements Hello{
#Override
public String greet(String s) {
return "Hello "+s;
}
}
The WSDL is available at: http://localhost:8080/DemoWS/HelloWorld?wsdl
Taking a look at the Tomcat-CXF example, I have coded the following route:
public class CamelRoute extends RouteBuilder {
private String uri = "cxf:http://localhost:8080/helloWorld?serviceClass=com.sample.HelloWorld";
#Override
public void configure() throws Exception {
from(uri)
.to("log:input")
.recipientList(simple("direct:${header.operationName}"));
from("direct:greet")
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
String id = exchange.getIn().getBody(String.class);
exchange.getOut().setBody(id);
}
})
.to("log:output");
}
}
By running the above code in a Camel Context, the following error is returned:
Exception in thread "main" org.apache.camel.FailedToCreateRouteException: Failed to create route route1: Route[[From[cxf:http://localhost:8080/helloWorld?serviceClas... because of Failed to resolve endpoint: cxf://http://localhost:8080/helloWorld?serviceClass=com.sample.HelloWorld due to: No component found with scheme: cxf
at org.apache.camel.model.RouteDefinition.addRoutes(RouteDefinition.java:177)
at org.apache.camel.impl.DefaultCamelContext.startRoute(DefaultCamelContext.java:731)
at org.apache.camel.impl.DefaultCamelContext.startRouteDefinitions(DefaultCamelContext.java:1803)
at org.apache.camel.impl.DefaultCamelContext.doStartCamel(DefaultCamelContext.java:1589)
at org.apache.camel.impl.DefaultCamelContext.doStart(DefaultCamelContext.java:1453)
at org.apache.camel.support.ServiceSupport.start(ServiceSupport.java:60)
at org.apache.camel.impl.DefaultCamelContext.start(DefaultCamelContext.java:1421)
at com.sample.Main.main(Main.java:15)
Caused by: org.apache.camel.ResolveEndpointFailedException: Failed to resolve endpoint: cxf://http://localhost:8080/helloWorld?
serviceClass=com.sample.HelloWorld due to: No component found with scheme: cxf
It seems I'm not even able to invoke it. Any help ?
Thannks

<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-cxf</artifactId>
</dependency>

Related

Apache-camel corda component connection error: Failed to create route route1

I am trying the connect to Corda using that component and sending data to Apache ActiveMQ again using Apache Camel's Corda component.
Corda is running properly. Particularly, cardapp-example is running, and Notary- PartyA - PartyB and PartyC are alive. I can query using their terminal.
ActiveMQ is working properly, I test it with another input source.
I've also tried to connect difeerent localhost ports of all four nodes, and also the example one showed in the Camel's corda component webpage.
public class CordaConnector {
public void ConnectToCorda() throws Exception {
CamelContext context = new DefaultCamelContext();
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory();
context.addComponent("jms", JmsComponent.jmsComponentAutoAcknowledge(connectionFactory));
context.addRoutes(new RouteBuilder() {
#Override
public void configure() throws Exception {
from("corda://localhost:10004?username=user1&password=test&operation=VAULT_TRACK&contractStateClass=#contractStateClass").
}
});
while(true) {
context.start();
}
}
}
I got the following error message:
Exception in thread "main" org.apache.camel.FailedToCreateRouteException: Failed to create route route1: Route(route1)[From[corda://localhost:10004?username=user1&pa... because of Failed to resolve endpoint: corda://localhost:10004?contractStateClass=%23contractStateClass&operation=VAULT_TRACK&password=test&username=user1 due to: Error binding property (contractStateClass=#contractStateClass) with name: contractStateClass on bean: org.apache.camel.component.corda.CordaConfiguration#1de76cc7 with value: #contractStateClass
...
So when tested seperately, corda works properly, ActiveMQ works properly (with different output), and I ave tried different ports to query information. I have alos tried different commands to query, such as:
from("corda://localhost:10000?username=user1&password=test&operation=NETWORK_MAP_FEED").
to("activemq:queue:try");
I've checked this question Failed to create route route1, but was no help.
I would appreciate any help on what might be the reason.
In your route from uri, you are setting the contractStateClass property using value #contractStateClass : this references a bean named contractStateClass in the Camel registry. But since you did not bind any bean with this name in the context registry, Camel fail to resolve this value: Error binding property (contractStateClass=#contractStateClass) with name: contractStateClass on bean: org.apache.camel.component.corda.CordaConfiguration#1de76cc7 with value: #contractStateClass
You simply need to configure a bean of type Class and provide it to the camel registry. Something like that should work ( camel version 2.24.x )
import net.corda.core.contracts.OwnableState;
import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.camel.impl.SimpleRegistry;
public class CordaConnector {
public static void main(String[] args) {
try {
SimpleRegistry registry = new SimpleRegistry();
registry.put("contractStateClass", OwnableState.class);
CamelContext camelContext = new DefaultCamelContext(registry);
camelContext.addRoutes(new RouteBuilder() {
#Override
public void configure() {
from("corda://localhost:10004?username=user1&password=test&operation=VAULT_TRACK&contractStateClass=#contractStateClass")
.log("got message");
}
});
camelContext.start();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
EDIT for Camel v3.x :
import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.camel.support.SimpleRegistry;
public class CordaConnector {
public static void main(String[] args) {
try {
SimpleRegistry registry = new SimpleRegistry();
registry.bind("contractStateClass", MyContractClass.class);
CamelContext camelContext = new DefaultCamelContext(registry);
camelContext.addRoutes(new RouteBuilder() {
#Override
public void configure() {
from("corda://localhost:10004?username=user1&password=test&operation=VAULT_TRACK&contractStateClass=#contractStateClass")
.log("got message");
}
});
camelContext.start();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}

Simple Camel test fails with no messages recieved

Am using Spring Boot and I have just added camel to it.
I have a simple camel route setup :
import org.apache.camel.builder.RouteBuilder;
import org.springframework.stereotype.Component;
#Component
public class MyRoute extends RouteBuilder {
#Override
public void configure() throws Exception {
from("file://in").to("file://out");
}
}
When I try to create simple test for this route with :
#RunWith(CamelSpringBootRunner.class)
#SpringBootTest
#DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class MyRouteTest extends CamelTestSupport {
#Autowired
private CamelContext camelContext;
#Produce(uri = "file://in")
private ProducerTemplate producerTemplate;
#EndpointInject(uri = "mock:file://out")
private MockEndpoint mockEndpoint;
#Test
public void routeTest() throws Exception {
mockEndpoint.expectedMessageCount(1);
producerTemplate.sendBody("Test");
mockEndpoint.assertIsSatisfied();
}
}
It fails with
mock://file://out Received message count. Expected: <1> but was: <0>
Not sure what could be a problem here. I have producer template that has uri as my route from point and am mocking to endpoint with EndpointInject and the the mock uri?
Fixed but not 100%
If I change route from real one
from("file://in").to("file://out");
to
from("file://in").to("mock:out");
And in my test override
#Override
protected RoutesBuilder createRouteBuilder() throws Exception {
return new MyRoute();
}
to create specific route
and strangest of all ! Had to remove :
#SpringBootTest
and after that
private CamelContext camelContext;
And then it started working !
But unfortunately not what I need, still there are things that need to be fixed, I would like to use my real prod route !
from("file://in").to("file://out");
And if possible not use advise on route , but just mock it , tried with
mock:file://out in test, but it didnt work :(
and also , it does not work with #SpringBootTest ??? very strange ?!
You need to add
#Override
public String isMockEndpoints() {
return "*";
}
This should mock all the enpoints and then you can use mock:file:out for example
If I am not misstaken you are mocking your output endpoint yet your endpoint endpoint is a file endpoint. When you send a message you need to drop a message to whereever the file endpoint is polling. Otherwise you need to mock that as well.

How to mock cxfbean call in Apache Camel?

I've got route that calls cxfbean:
.to("cxfbean:reservationService")
Tried mock this in my test with
#EndpointInject(uri = "mock:reservationService")
MockEndpoint reservationSystemMock;
#BeforeMethod
private void setUpContext() throws Exception
{
context.getRouteDefinition( "send.to.res.svc.endpoint" ).adviceWith(
context, new AdviceWithRouteBuilder() {
#Override
public void configure() throws Exception
{
interceptSendToEndpoint("cxfbean:reservationService")
.skipSendToOriginalEndpoint()
.to("mock:reservationService");
}
});
}
Also tried mock with weaveByToString( "**reservationService" ).replace().to( "mock:reservationService" );. In both cases I get:
Caused by: org.apache.camel.NoSuchBeanException: No bean could be found in the registry for: reservationService
I'd like to test my route without cxf bean instantiation. I'm using CamelTestSupport class as parent.
Managed to mock cxfbean endpoint with weaveByToString( "To[cxfbean:reservationService]" ):
#EndpointInject(uri = "mock:reservationService")
protected MockEndpoint reservationSystemMock;
#BeforeMethod
private void setUpContext() throws Exception
{
context.getRouteDefinition( "send.to.res.svc.endpoint" ).adviceWith(
context, new AdviceWithRouteBuilder() {
#Override
public void configure() throws Exception {
weaveByToString( "To[cxfbean:reservationService]" )
.replace().to( "mock:reservationService" );
}
});
}
Also seems that we can peek necessary expression for weaveByToString using context.getRouteDefinitions().get(0).toString() in debug watcher
Remember to turn on advice-with on your test class. If you use those annotations, then add #UseAdviceWith to the class.
And then start the camel context after you have advised, which
http://camel.apache.org/spring-testing.html
http://camel.apache.org/advicewith.html

Bootstrap camel in spring web application

I'm creating a application with Spring-jersey-camel. I wanted to expose my jersey layer and internally invoke camel routes to invoke resources.
web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
applicationContext.xml
<camelContext id="camelContext" xmlns="http://camel.apache.org/schema/spring">
<packageScan>
<package>com.company.myapp.camel</package>
<excludes>**.*</excludes>
<includes>*Routes.java</includes>
</packageScan>
</camelContext>
MyRoutes.java
#Component
public final class MyRoutes extends RouteBuilder {
#Override
public void configure() throws Exception {
from("direct:getOrdersData").validate(body().isNotNull())
.log("Camel to get orders")
.to("restlet:http://localhost:8081/ordersapp/rest/order/123");
}
}
OrderResourceImpl.java
#Component
#Path("/orderLookup")
public class ReservationResources {
#org.apache.camel.produce
ProducerTemplate producer;
public void setProducer(ProducerTemplate producer) throws Exception {
this.producer = producer;
}
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("{orderId}")
public Response orderLookup(#PathParam("orderId") final long orderrId){
Response r = Response.noContent().build();
//Producer is null. throws nullPointerException
String order= producer.requestBody("direct:getOrdersData", orderId, String.class);
r = Response.ok().entity(reservation).build();
return r;
}
}
Any idea what I'm doing wrong? or how to inject myRoute/ProducerTemplate im my orderResourceImpl.java. Thanks in advance
Two Options,
If ReservationResources is a spring bean then, Inject the Camel Context into it and create a ProducerTemplate from that
ProducerTemplate template = camelContext.createProducerTemplate();
If ReservationResources is not a spring bean then get the Camel Context via a static method https://stackoverflow.com/a/13633109/3696510 and then create the ProducerTemplate.
ProducerTemplate template = StaticSpringApplicationContext.getBean("camelContext").createProducerTemplate()
Also if you do use that StaticSpringApplicationContext mentioned in the link, I would add this method to it.
public static <T> T getBean(String beanName, Class<T> clazz) {
return (T) CONTEXT.getBean(beanName,clazz);
}

Camel Proxy and Replacing Exchange body

I have created a proxy for service.
There is a processor in between proxy (request is of type TypeA) and real service (request is of type TypeB).
The Exchange body which comes into the process(Exchange exchange) method is of TypeA.
I am able to access the data using following line of code
TypeA typeA = exchange.getIn().getBody(TypeA.class);
Now, I wanted to change this information to TypeB.
I am adding the body using following line.
exchange.getIn().setBody(typeA);
I got the java.lang.IllegalArgumentException: argument type mismatch
Now, I wanted to call the real service using the Exchange which come out of the Processor.
I tried and got in Processor the following exception
java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.cxf.databinding.AbstractWrapperHelper.createWrapperObject(AbstractWrapperHelpe
The real web service is not getting invoked.
How to fix this.
I am using POJO mode in proxy.
This works without any problems:
private static class ResetBodyRouteBuilder extends RouteBuilder {
#Override
public void configure() {
from("direct:start")
.process(new Processor() {
#Override
public void process(final Exchange exchange) throws Exception {
final ClassA a = exchange.getIn().getBody(ClassA.class);
LOG.info("body = " + a);
exchange.getIn().setBody(new ClassB()); // reset the body
}
})
.log("body = ${body}");
}
}
public class ClassA {
#Override
public String toString() {
return "I'm A";
}
};
public class ClassB {
#Override
public String toString() {
return "I'm B";
}
};
This prints:
[ main] ResetBody INFO body = I'm A
[ main] route1 INFO body = I'm B

Resources