Annotated beans not getting injected for JAX-RS CXF service - cxf

I have a CXF RESTful service which is working just fine. Problem is when I try to inject my DAO using an annotation:
#Resource
private MyDAO myDAO;
It's not getting injected. My JAX-RS service is Spring configured like so:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xmlns:cxf="http://cxf.apache.org/core"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml"/>
<import resource="classpath:META-INF/cxf/cxf-extension-jaxrs-binding.xml"/>
<import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
<jaxrs:server id="message" serviceClass="com.foo.MessageResourceImpl" address="/">
<jaxrs:features>
<cxf:logging/>
</jaxrs:features>
</jaxrs:server>
</beans>
The DAO is getting initialized by Spring and I have verified the bean works in any other POJO, just not the CXF service. Furthermore, I don't see any errors in the logs

The solution is to serviceBeans:
<jaxrs:serviceBeans>
<bean class="com.foo.MessageResourceImpl"/>
</jaxrs:serviceBeans>
When using #serviceClass, CXF instantiates the class, not Spring.

Related

injecting properties in camel route from wildfly modules

I am using SwithcYard 2.0.0.Beta1. Application server is WildFly 8.1. I want to load properties from modules.
As example I have a module /wildfly/modules/system/layers/base/org/study/configuration/test
my module.xml
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.3" name="org.study.configuration" slot="test">
<resources>
<resource-root path="."/>
</resources>
</module>
This is properties file:
user=foo
password=bar
provider=CryptoProvider
directory=domain;login:pwd#host/dir?password=pwd&preMove=backup&move=processed&moveFailed=error&charset=UTF-8
This is how I include that module in wildfly profile:
<subsystem xmlns="urn:jboss:domain:ee:2.0">
<global-modules>
<module name="org.study.configuration" slot="test"/>
</global-modules>
And now I want to load that properties in my camel route:
.to("smb://{{directory}}")
or
in bean
KeyStore ks = KeyStore.getInstance("PKCS12", {{provider}});
Is it possible? how to do this?
It is possible, but as long as your properties are in the file you have to load it first.
What you define in the module - it is just a class path for your application.
If you use Java DSL:
Properties myProps = new Properties();
Stream is = this.getClass().getClassLoader().getResourceAsStream("MyAppProp.properties");
myProps.load(is);
System.getProperties().putAll(myProps);
If you use Spring DSL just define regular Spring properties.
a. with Spring bean namespace
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>MyAppProp.properties</value>
</property>
</bean>
b. with Spring context namespace
<context:property-placeholder location="MyAppProp.properties"/>
Then you can use them inside Camel route as you said:
.to("smb://{{directory}}")
PS. you have an ability to define properties directly in the module.xml as well
<module xmlns="urn:jboss:module:1.3" name="org.study.configuration" slot="test">
<properties>
<property name="directory" value="myTestDirectory"/>
</properties>
...

Spring bean from one bundle is not accessible in camel route in another bundle

I have one jar file (connection.jar) which is an OSGI bundle with folder structure src/main/resources/META-INF/spring/mq-connect.xml
following connectivity code is placed in the mq-connect.xml
<beans ...... >
....
....
....
....
<!-- AMQ jms component -->
<bean id="amqtx" class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="connectionFactory" ref="amqPooledConnectFactory" />
...
...
...
<property name="maxConcurrentConsumers" value="${concurrent.consumers}" />
</bean>
</beans>
I have another osgi bundle (connection_impl.jar) which contains camel routes. I want to use "amqtx" bean as the component in the camel endpoint.
Following is the code which I put in the camel-context.xml to access the "amqtx"
<beans ...... >
<import resource="classpath*:mq-connect.xml"/>
...
...
...
...
<camelContext trace="true" streamCache="true" autoStartup="true" xmlns="http://camel.apache.org/schema/spring">
<route customId="true" id="TEST_AMQ">
<description>Test connectivity from another file</description>
<from uri="amqtx:INBOUND.QUEUE" />
<transacted ref="AMQ_PROPAGATION_REQUIRED" />
<to uri="OUTBOUND.QUEUE" />
<log message="Route completed successfully" />
</route>
</camelContext>
</beans>
I am using jboss-a-mq-6.2.1 and deploying to Karaf container. OSGi bundle connection.jar deploys successfully but connection_impl fails to deploy.
It gives following error in the A-MQ logs
Stack Trace:
org.apache.camel.RuntimeCamelException: org.apache.camel.FailedToCreateRouteException: Failed to create route TEST_AMQ:
Route(TEST_AMQ)[[From[amqtx:INBOUND.QUEUE]] -> ... because of Failed to resolve endpoint: amqtx://INBOUND.QUEUE due to: No component found with scheme: amqtx
I tried the part in various ways but still amqtx is not accessible in another bundle.
Please suggest any missing import,export/wrong configuration so that amqtx component in connection.jar is accessible in connection_impl.jar
Not sure if you can make this work at all but it is definitely not recommended to import a spring xml in another bundle.
Better export the bean as a service in the first bundle and refer it as a service in the second. This will also decouple your bundle in a better way.
I am in agreement with Christian. When you are using OSGI bundles are typically isolated unless you explicitly set exports for a library another bundle uses or you are exposing an OSGI Service. If you would like to setup an OSGI service my recommendation is doing it the Spring Framework way since its relatively clean. You can expose your Component via an interface. I'll show an example below.
Typically I like to have 3 bundles managing this. I usually have a bundle that contains just the interface that I will be exposing between separate bundles. A Bundle that is the implementation of the interface and a bundle that leverages the interface's injected implementation to accomplish a task.
//Interface bundle will expose an Interface and any Pojos associated. Ex:
public interface AlternateFacilityApi {
public String getAlternateFacility(String facilityName);
}
//Implementation bundle will register an OSGI service based off of the implementation bean from your interface (yes the previous bundle is a dependency OSGI wires in)
public Class MyAlternateFacilityImpl implements AlternateFacilityApi {
public String getAlternateFacility(String facilityName) {
return "Bob's house";
}
//camel context
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:osgi="http://www.springframework.org/schema/osgi"
xmlns:ctx="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
http://www.springframework.org/schema/osgi
http://www.springframework.org/schema/osgi/spring-osgi.xsd">
<osgi:service id="AlternateFacilityService" ref="alternateFacilityService" interface="com.world.api.AlternateFacilityApi" />
<bean id="alternateFacilityService" class="com.world.service.MyAlternateFacilityImpl"
/>
</beans>
//Ok and finally the Process looking to leverage the OSGI Service
public Class AlternateFacilityLookup {
private AlternateFacilityApi apiLookupBean;
public String getMyAlternateFacility(String facilityName) {
return apiLookupBean.getAlternateFacility(facilityName);
}
//excluded setters and getters
}
//camel context
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:osgi="http://www.springframework.org/schema/osgi"
xmlns:ctx="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
http://www.springframework.org/schema/osgi
http://www.springframework.org/schema/osgi/spring-osgi.xsd">
<osgi:reference id="AlternateFacilityLookupService" interface="com.world.api.AlternateFacilityApi" />
<bean id="MyAlternateFacilityBean" class="com.awesome.AlternateFacilityLookup">
<property name="apiLookupBean" ref="AlternateFacilityLookupService" />
</bean>

Bundle is waiting for namespace handlers blueprint and cxf

I'm having problems re-deployin a JAR on Servicemix (5.5.1) using Blueprint, Camel and Camel-CXF:
org.apache.aries.blueprint.core - 1.4.3 | Bundle my-camel-project is waiting
for namespace handlers [http://camel.apache.org/schema/blueprint/cxf,
http://camel.apache.org/schema/blueprint]
Aparently, certains URLs has been modified today:
http://camel.apache.org/schema/blueprint/cxf -> Not found
http://camel.apache.org/schema/blueprint -> Index of /schema/blueprint
This is a part of my blueprint definition:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cxf="http://cxf.apache.org/blueprint/core"
xmlns:jaxws="http://cxf.apache.org/blueprint/jaxws"
xmlns:jaxrs="http://cxf.apache.org/blueprint/jaxrs"
xmlns:camelcxf="http://camel.apache.org/schema/blueprint/cxf"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0
http://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://cxf.apache.org/blueprint/core
http://cxf.apache.org/schemas/blueprint/core.xsd
http://cxf.apache.org/blueprint/jaxrs
http://cxf.apache.org/schemas/blueprint/jaxrs.xsd
http://cxf.apache.org/blueprint/jaxws
http://cxf.apache.org/schemas/blueprint/jaxws.xsd">
...
<camelcxf:cxfEndpoint id="serviceSoap"
address="http://localhost:8989/soap" serviceClass="my.path.ServiceSOAP" />
...
<camelContext xmlns="http://camel.apache.org/schema/blueprint">
...
</camelContext>
</blueprint>
I builded this codes following a lot of examples on Camel tutorials and Camel In Action book. Was working some days, but not right now.
There are something new recently?

IllegalStateException on camel cxf route in FUSE (servicemix) ESB

I try to set up a camel (Ver. 2.4.0) route in a FUSE (Ver. 4.3.0) ESB/OSGi container.
It should be a simple cxf-proxy to route a WebService call from a 'proxy' address to a real service.
I read several documentation:
CXF Proxy Example
camel cxf component
and set up the following spring configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:camel="http://camel.apache.org/schema/spring"
xmlns:osgi="http://www.springframework.org/schema/osgi"
xmlns:cxf="http://camel.apache.org/schema/cxf"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/osgi
http://www.springframework.org/schema/osgi/spring-osgi.xsd
http://camel.apache.org/schema/osgi
http://camel.apache.org/schema/osgi/camel-osgi.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd
http://camel.apache.org/schema/cxf
http://camel.apache.org/schema/cxf/camel-cxf.xsd">
<import
resource="classpath:META-INF/cxf/cxf.xml" />
<import
resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import
resource="classpath:META-INF/cxf/cxf-extension-http.xml" />
<import
resource="classpath:META-INF/cxf/osgi/cxf-extension-osgi.xml" />
<!-- the proxy service -->
<cxf:cxfEndpoint
id="myServiceProxy"
address="http://localhost:9003/cxf/myService"
serviceClass="foo.bar.iface.MyServiceInterface" />
<!-- my real existing cxf soap service -->
<cxf:cxfEndpoint
id="myService"
address="http://foo.bar/services/myService"
wsdlURL="http://foo.bar/services/myService?wsdl"
serviceClass="foo.bar.iface.MyServiceInterface"
serviceName="s:MyService"
endpointName="s:MyServiceEndpoint"
xmlns:s="http://foo.bar/iface/" />
<!-- route -->
<camel:camelContext>
<camel:route>
<camel:from
uri="cxf:bean:myServiceProxy" />
<camel:to
uri="cxf:bean:myService" />
</camel:route>
</camel:camelContext>
</beans>
Trying to start the bundle in FUSE leads to this exception
karaf#root> Exception in thread "SpringOsgiExtenderThread-22" org.apache.camel.RuntimeCamelException: java.lang.IllegalStateException: Endpoint address should be a relative URI wrt to the servlet address (use '/xxx' for example)
at org.apache.camel.util.ObjectHelper.wrapRuntimeCamelException(ObjectHelper.java:1126)
at org.apache.camel.spring.SpringCamelContext.onApplicationEvent(SpringCamelContext.java:103)
at org.apache.camel.spring.CamelContextFactoryBean.onApplicationEvent(CamelContextFactoryBean.java:231)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:97)
I do not know what's wrong. I doubt that my Endpoint address is wrong and I do not know what my servlet address is (there is no cxf:cxfEndoint servelt address attribute).
Any help to lead me in the right direction to solve this problem would be appreciated.
Thanks
Klaus
I finally found out what's wrong.
Instead
<!-- the proxy service -->
<cxf:cxfEndpoint
id="myServiceProxy"
address="http://localhost:9003/cxf/myService"
serviceClass="foo.bar.iface.MyServiceInterface" />
it has to be
<!-- the proxy service -->
<cxf:cxfEndpoint
id="myServiceProxy"
address="/myService"
serviceClass="foo.bar.iface.MyServiceInterface" />
As the first approach worked well running the camel project outside FUSE (in this case a the http server will be started to provide the service) it has to be a relative address inside FUSE.
Inside FUSE the embedded HTTP server which runs on (localhost:8181) will be used and the service url will be extended to http://localhost:8181/cxf/myService.

Starting ActiveMQ message listener in Tomcat?

I've created an ActiveMQ MessageListener and configured it using Spring. I'm hosting the listener in Tomcat. When I start up the web application (that features only the listener), should the listener automatically start? Or do I need additional configuration?
Here's what I have. First, updated the web.xml to allow spring to configure itself on startup,
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/spring/applicationContext.xml</param-value>
</context-param>
</web-app>
Then I created the applicationContext.xml to configure the ActiveMQ listener,
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:amq="http://activemq.apache.org/schema/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config />
<context:component-scan base-package="com.somepackage"/>
<context:property-placeholder location="classpath:env.properties"/>
<bean id="jmsFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616" />
</bean>
<bean id="documentListener" class="com.somepackage.SomeListener" />
<bean id="container"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="cachingConnectionFactory"/>
<property name="messageListener" ref="documentListener"/>
<property name="destinationName" value="STOCKS.MSFT" />
</bean>
<bean id="cachingConnectionFactory"
class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="jmsFactory" />
<property name="sessionCacheSize" value="1" />
</bean>
</beans>
And that's it. Based on what I've seen around the web, I can't tell if that's all I need? Maybe I need some other configuration in Tomcat to kick off the listener?
This was actually working. I was debugging this using Eclipse and I had to do a couple refreshes, cleans and restarts before it suddenly decided to work.
To answer my own question, yes, this is all that is required in order to run a listener in a web application from within Tomcat. It can be totally configured with XML only.

Resources