Method with name: sayHi not found on bean - Using apache Camel - apache-camel

I am using apache camel to communicate to a remote EJB which is deployed in Weblogic Server 12c. when i invoke remote EJB it throws me the below exception
org.apache.camel.component.bean.MethodNotFoundException: Method with name: sayHi not found on bean: ClusterableRemoteRef(3961905123449960886S:192.168.1.98:[7001,7001,-1,-1,-1,-1,-1]:weblogic:AdminServer [3961905123449960886S:192.168.1.98:[7001,7001,-1,-1,-1,-1,-1]:weblogic:AdminServer/394])/394 of type: com.iexceed.study.HelloRemoteEJBImpl_6zix6y_IHelloRemoteEJBImpl_12120_WLStub. Exchange[Message: [Body is null]]
My Came-context.xml file is as below
<bean id="ejb" class="org.apache.camel.component.ejb.EjbComponent">
<property name="properties" ref="jndiProperties" />
</bean>
<util:properties id="jndiProperties">
<prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
<prop key="java.naming.provider.url">t3://IPADDRESS:PORT</prop>
<prop key="java.naming.security.principal">weblogic</prop>
<prop key="java.naming.security.credentials">Weblogic#01</prop>
</util:properties>
<camelContext id="camelclient" xmlns="http://camel.apache.org/schema/spring">
<template id="template" />
<endpoint id="camelejb" uri="ejb:EJBRemoteModule-1_0-SNAPSHOTEJBRemoteModule-1_0-SNAPSHOT_jarHelloRemoteEJBImpl_IHelloRemoteEJB?method=sayHi"/>
<route>
<from uri="direct:start_0" />
<to uri="camelejb" />
</route>
</camelContext>
and the java client class which i am using is
public void postRequest(){
try {
String camelID = "camelejb";
Exchange exchange = null;
Message msg = null;
getCamelContext();
springCamelContext.start();
System.out.println("Starting camel context.....");
getUriMap();
ProducerTemplate template = springCamelContext.createProducerTemplate();
System.out.println("camelejb::::::" + getUriMap().get("camelejb"));
exchange = template.request(getUriMap().get(camelID), new Processor() {
public void process(Exchange exchng) throws Exception {
exchng.getIn().setBody("");
}
});
System.out.println("Exception:" + exchange.getException());
exchange.getException().printStackTrace();
msg = exchange.getOut();
System.out.println("Message:" + msg);
springCamelContext.stop();
System.out.println("Stopping Camel Context....");
} catch (Exception ex) {
ex.printStackTrace();
}
}
EJB :
#Remote
public interface IHelloRemoteEJB {
public void sayHello(String name);
public void sayHi();
}
Having no clue why this error is thrown when the method is available in my EJB.
Will be really grateful from heart because i am already in soup.

What's the result of below code?
getUriMap().get("camelejb")
If you want to reference an endpoint in the camel route, you should do like this
<endpoint id="endpoint1" uri="direct:start"/>
<endpoint id="endpoint2" uri="mock:end"/>
<route>
<from ref="endpoint1"/>
<to uri="ref:endpoint2"/>
</route>

Related

Apache Camel + Karaf - Using Atmosphere-websocket as client

After having installed my Websocket on Apache Karaf, I am now trying to communicate with it through an Apache Camel blueprint using ATMOSPHERE WEBSOCKET. (I can reach it through a javascript websocket client)
I am getting the following error though :
Blueprint bundle allin.opcmid/0.0.3 is waiting for dependencies [(&(component=atmosphere-websocket)(objectClass=org.apache.camel.spi.ComponentResolver))]
My websocket registration looks like this :
#WebServlet(name = "Allin WebSocket Servlet", urlPatterns = { "/allin-websocket"})
public class AllinWSServlet extends WebSocketServlet {
#Override
public void configure(WebSocketServletFactory factory) {
factory.register(AllinWS.class);
}
}
And the header part of the websocket like this:
#Component(name = "allin-websocket", immediate = true)
#WebSocket
public class AllinWS {
#Reference
private HttpService httpService;
#Activate
public void activate() throws Exception {
httpService.registerServlet("/allin-websocket", new AllinWSServlet(), null, null);
}
Now when I am running my Apache Camel route installed on my Apache Karaf instance, I'm getting the error I have described above. The blueprint looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd
http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0 http://aries.apache.org/schemas/blueprint-cm/blueprint-cm-1.1.0.xsd">
<camelContext id="opcm" xmlns="http://camel.apache.org/schema/blueprint">
<route id="rece">
<from uri="atmosphere-websocket:///allin-websocket" />
<log message="${body}"/>
<to uri="mock:result"/>
</route>
</camelContext>
</blueprint>
Best regards

Camel Interceptor conflict with CXF Interceptor

I am Using custom InterceptStrategy and it throws errors after SOAP response is success.
Error : java.lang.IllegalStateException: It is illegal to call getRequest() after complete() or any of the dispatch() methods has been called
at org.apache.catalina.core.AsyncContextImpl.getRequest(AsyncContextImpl.java:224)
at org.apache.catalina.core.AsyncContextImpl.dispatch(AsyncContextImpl.java:153)
at org.springframework.security.web.servletapi.HttpServlet3RequestFactory$SecurityContextAsyncContext.dispatch(HttpServlet3RequestFactory.java:291)
at org.apache.cxf.transport.http.Servlet3ContinuationProvider$Servlet3Continuation.redispatch(Servlet3ContinuationProvider.java:125)
at org.apache.cxf.transport.http.Servlet3ContinuationProvider$Servlet3Continuation.resume(Servlet3ContinuationProvider.java:131)
public class ApplicationLogStrategy implements InterceptStrategy {
#Override
public Processor wrapProcessorInInterceptors(CamelContext context, ProcessorDefinition<?> definition,
Processor target, Processor nextTarget) throws Exception {
return new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
System.out.println("Display" + definition);
if (definition.getId().equalsIgnoreCase(ApplicationConstants.INITIAL_LOG)) {
//setCommonFields(exchange);
//setSpecificFields(exchange);
}
target.process(exchange);
}
};
}
}
My camel route:
<camelContext id="id-por" xmlns="http://camel.apache.org/schema/spring">
<route>
<!-- route starts from the cxf webservice -->
<from uri="cxf:bean:porEndpoint" />
<doTry>
<to uri="bean:soapBean?method=processSOAP"/>
<bean id="soap_success" method="processSuccess" ref="soapBean"/>
<camel:bean id="published_log" method="info('Message - SUCCESS')" ref="logger"/>
<doCatch>
<camel:exception>java.lang.Exception</camel:exception>
<handled>
<constant>true</constant>
</handled>
<to uri="bean:soapBean?method=processGenericError"/>
</doCatch>
</doTry>
</route>
</camelContext>
It throws error after the message "Message - SUCCESS" is logged. :
<camel:bean id="published_log" method="info('Message - SUCCESS')" ref="logger"/>
I added <stop/> but no luck, still throws the error : It is illegal to call getRequest() after complete() or any of the dispatch() methods
Instead of target.process(exchange);
just return target;

spring camel test using multiple contexts

I have two camel contexts (A and B) at different xml using Spring. When I load just one context my junit works, but when a I try to load both contexts the Endpoint inject fail running junit.
So, someone have a sample how to use Test using multiple context with spring camel?
Spring Test
public class BaseSpringTest extends CamelSpringTestSupport
{
protected AbstractXmlApplicationContext createApplicationContext()
{
return new ClassPathXmlApplicationContext("camel-config.xml");
}
}
My file camel-config.xml
<beans>
<context:annotation-config/>
<import resource="classpath:camel-test-dao.xml" />
<import resource="classpath:camel-contextA.xml"/>
<import resource="classpath:camel-contextB.xml"/>
</beans>
My contexts:
<camelContext xmlns="camel.apache.org/schema/spring" id="contextA">
...
</camelContext>
<camelContext xmlns="camel.apache.org/schema/spring" id="contextB">
...
</camelContext>
My unit test, failing at inject Endpoint:
#EndpointInject(uri = "direct:myroute", context="contextB")
private Endpoint eFooTest;
Stacktrace:
org.apache.camel.spring.GenericBeansException: Error post processing bean: com.mycompany.test.FooTest; nested exception is java.lang.NullPointerException
at org.apache.camel.spring.CamelBeanPostProcessor.postProcessBeforeInitialization(CamelBeanPostProcessor.java:154)
at org.apache.camel.test.spring.CamelSpringTestSupport.postProcessTest(CamelSpringTestSupport.java:62)
at org.apache.camel.test.junit4.CamelTestSupport.doSetUp(CamelTestSupport.java:319)
at org.apache.camel.test.junit4.CamelTestSupport.setUp(CamelTestSupport.java:238)
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.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.NullPointerException
at org.apache.camel.impl.CamelPostProcessorHelper.matchContext(CamelPostProcessorHelper.java:84)
at org.apache.camel.impl.DefaultCamelBeanPostProcessor$1.doWith(DefaultCamelBeanPostProcessor.java:181)
at org.apache.camel.util.ReflectionHelper.doWithFields(ReflectionHelper.java:73)
at org.apache.camel.impl.DefaultCamelBeanPostProcessor.injectFields(DefaultCamelBeanPostProcessor.java:168)
at org.apache.camel.impl.DefaultCamelBeanPostProcessor.postProcessBeforeInitialization(DefaultCamelBeanPostProcessor.java:82)
at org.apache.camel.spring.CamelBeanPostProcessor.postProcessBeforeInitialization(CamelBeanPostProcessor.java:148)
... 31 more
Apparently there is a bug at CamelBeanPostProcessor, when there are more one context a null value is returned!
if (contexts != null && contexts.size() == 1) {
#XmlTransient
private final DefaultCamelBeanPostProcessor delegate = new DefaultCamelBeanPostProcessor() {
#Override
public CamelContext getOrLookupCamelContext() {
if (camelContext == null) {
if (camelId != null) {
LOG.trace("Looking up CamelContext by id: {} from Spring ApplicationContext: {}", camelId, applicationContext);
camelContext = applicationContext.getBean(camelId, CamelContext.class);
} else {
// lookup by type and grab the single CamelContext if exists
LOG.trace("Looking up CamelContext by type from Spring ApplicationContext: {}", applicationContext);
Map<String, CamelContext> contexts = applicationContext.getBeansOfType(CamelContext.class);
if (contexts != null && contexts.size() == 1) {
camelContext = contexts.values().iterator().next();
}
}
}
return camelContext;
}
Camel 2.16.2
Spring 4.1.5
JDK 1.7
JDK 1.8
Thanks #Jorge-c, but using routeContext we continuous having just one single CamelContext.
To use multiply contexts at unit test don't use CamelSpringTestSupport, there are a bug.
public class BaseSpringTest extends CamelSpringTestSupport {...}
Use "#RunWith(SpringJUnit4ClassRunner.class)"
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("/camel-my-root-spring-config.xml")
public class BaseSpringJUnit4
{
#EndpointInject(uri = "direct:myroute", context="contextB")
private Endpoint eFooTest;
}
This works! Doesn't forget to put explicitilly context="contextB" in the endpoint annotation
Camel 2.16.2
Spring 4.1.5
JDK 1.7
JDK 1.8
I've been struggling with this for a while as well. Finally I managed a workaround which allows me to use the original routes xml files used in production but combined into a single camel context to be able to use it for testing. This way I'm able to inject mocks for bean endpoints and check the complete process by asserting on the mocks.
There are two different bundles. One from invoicing and another for emailing. The routes orchestrate the process.
First I externalized the routes on the production xml files. Spring context (invoicing-spring-context.xml) and routes (invoicing-routes.xml) file for invoicing bundle:
<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
...
<camelContext id="invoicingCamelContext"
xmlns="http://camel.apache.org/schema/spring">
<routeContextRef ref="invoicingRoutes"/>
</camelContext>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
<routeContext id="invoicingRoutes" xmlns="http://camel.apache.org/schema/spring">
<route id="planner" autoStartup="true">
<from uri="quartz://planner?cron=0+0+23+16+*+?" />
<to uri="direct:invoicing" />
</route>
<route id="invoicing" autoStartup="true">
<from uri="direct:invoicing?exchangePattern=InOut" />
<to uri="bean:invoicer?method=generateInvoices" />
<to uri="direct-vm:emailing" />
</route>
</routeContext>
</beans>
Spring context (emailing-spring-context.xml) and routes (emailing-routes.xml) for emailing bundle:
<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
...
<camelContext id="emailingCamelContext"
xmlns="http://camel.apache.org/schema/spring">
<routeContextRef ref="emailingRoutes"/>
</camelContext>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
<routeContext id="emailingRoutes" xmlns="http://camel.apache.org/schema/spring">
<route id="emailing" autoStartup="true">
<from uri="direct-vm:emailing" />
<to uri="bean:emailer?method=createEmails" />
<to uri="bean:emailer?method=sendEmails" />
</route>
</routeContext>
</beans>
Then for testing purposes I created another spring context (complete-process-test-spring-context.xml) which imports both routes files:
<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
...
<camelContext id="completeProcessTestCamelContext"
xmlns="http://camel.apache.org/schema/spring">
<routeContextRef ref="invoicingRoutes"/>
<routeContextRef ref="emailingRoutes"/>
</camelContext>
</beans>
And the test class looks like:
public class CompleteProcessTest extends CamelSpringTestSupport {
#Test
public void completeProcess() {
...
invoicerMock.generateInvoices(EasyMock.isA(Exchange.class));
emailerMock.createEmails(EasyMock.isA(Exchange.class));
emailerMock.sendEmails(EasyMock.isA(Exchange.class));
EasyMock.replay(invoicerMock);
EasyMock.replay(emailerMock);
this.template.requestBody(this.context.getEndpoint("direct://invoicing"), "");
EasyMock.verify(invoicerMock);
EasyMock.verify(emailerMock);
}
#Override
protected AbstractApplicationContext createApplicationContext() {
return new ClassPathXmlApplicationContext("classpath:/META-INF/spring/invoicing-routes.xml",
"classpath:/META-INF/spring/emailing-routes.xml",
"classpath:/META-INF/spring/complete-process-test-spring-context.xml");
}
...
}

CXFNonSpringServlet in camel-cxf

I need to set the use-x-forwarded-headers Http header in camel-cxf like the below and make it as an OSGi bundle to be deployed in Karaf.
<servlet>
<servlet-name>cxf</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<init-param>
<param-name>use-x-forwarded-headers</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
I don't want to package this as a WAR, instead i want to make it an OSGi bundle.
Hence, i created a class which extends CXFNonSpringServlet as the code below and set the init-params,
public class XForwadedServlet extends CXFNonSpringServlet {
#Override
protected void loadBus(ServletConfig sc) {
sc.getServletContext().setInitParameter("use-x-forwarded-headers",
"true");
super.loadBus(sc);
Bus bus = getBus();
BusFactory.setDefaultBus(bus);
// createFactoryBean();
}
#Override
public void init(ServletConfig sc) throws ServletException {
sc.getServletContext().setInitParameter("use-x-forwarded-headers",
"true");
super.init(sc);
}
And here's my camel route,
<cxf:cxfEndpoint id="serviceEndpoint"
address="http://localhost:8123/cxf/testCxfRedirect"
loggingFeatureEnabled="true" serviceClass="com.redhat.HelloServiceImpl">
</cxf:cxfEndpoint>
<camelContext trace="false" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="cxf:bean:serviceEndpoint"/>
<log message="${body}" loggingLevel="INFO"/>
<bean ref="clientAddress" method="getClientAddress"/>
</route>
</camelContext>
<bean id="destinationRegistry" class="org.apache.cxf.transport.http.DestinationRegistryImpl">
</bean>
<bean id="osgiServlet" class="com.redhat.XForwadedServlet">
<constructor-arg ref="destinationRegistry"></constructor-arg>
<constructor-arg value="true"></constructor-arg>
</bean>
Through soapui, i set the X-Forwarded-For header as below,
Address: http://localhost:8123/cxf/testCxfRedirect
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml
Headers: {Accept=[*/*], SOAPAction=[""], X-Forwarded-For=[http://google.com]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns1:sayHello xmlns:ns1="http://redhat.com/"><arg0 xmlns="http://redhat.com/">Test</arg0></ns1:sayHello></soap:Body></soap:Envelope>
--------------------------------------
How can i register the CXFNonSpringServlet in OSGi Blueprint container with setting that init-params ?
Is there a way to do this in OSGi ?
This can be achieved by using the pax-web-extender support in Fuse, Camel.
However the packaging will need to be WAR.
Here's the reference from Karaf:
https://ops4j1.jira.com/wiki/display/ops4j/Pax+Web+Extender+-+War+-+Examples
Here's a reference implementation from the Camel Committers:
https://github.com/apache/camel/tree/master/examples/camel-example-reportincident
Hope it helps.

Multiple Camel Proxys in same camel context

I am trying to invoke a direct endpoint using camel proxy and a Java Interface. I exposed this interface as OSGI service to another bundle and accessing the interface in that bundle. Everything worked fine and now i got a requirement to invoke another direct endpoint based on certain conditions in same camel context using same interface. How can i do this?
Camel routes:
<camelContext id="cContext" trace="false" xmlns="http://camel.apache.org/schema/blueprint">
<proxy id="camelProxyService"
serviceInterface="com.xxx.CamelProxyService"
serviceUrl="direct:endpoint1" />
<route id="route1">
<from uri="direct:endpoint1" />
<to uri="seda:a" />
</route>
<route id="route2">
<from uri="direct:endpoint2" />
<to uri="seda:b" />
</route>
</camelContext>
<service ref="camelProxyService" interface="com.xxx.CamelProxyService"/>
public interface CamelProxyService {
public void method1(String str);
public void method2(String str);
}
How can i define the interface as camel proxy in camel context and mention method names to call different direct endpoints? Any help is appreciated.
<proxy id="camelProxyService"
serviceInterface="com.uday.camel.proxy.CamelProxyService"
serviceUrl="direct:endpoint1" />
<camel:route>
<camel:from uri="direct:endpoint1"/>
<camel:process ref="conditionProcess"/>
<camel:choice>
<camel:when>
<camel:header>${condition}=method1</camel:header>
<camel:to uri="seda:a"/>
</camel:when>
<camel:otherwise>
<camel:to uri="seda:b"/>
</camel:otherwise>
</camel:choice>
<camel:stop/>
</camel:route>
public class ConditionProcess implements Processor {
#Override
public void process(Exchange exchange) throws Exception {
BeanInvocation invocation = exchange.getIn().getBody(BeanInvocation.class);
String methodName = invocation.getMethod().getName();
exchange.getIn().setHeader("condition", methodName);
System.out.println("Method "+methodName);
}
}

Resources