Accessing OpenMQ JMS Broker from ServiceMix+Camel - apache-camel

I am trying to get ServiceMix+Camel talking to OpenMQ JMS Broker. I have a Camel route definition defined in Blueprint DSL which posts messages into an ActiveMQ JMS Queue. This is working fine, but I am now trying to convert this to post messages to an instance of OpenMQ running inside a Glassfish4 container.
I'm running the following configuration:
JDK 1.7.0_60
ServiceMix 5.1.1 (so Camel 2.13.2)
The documentation on this topic is somewhat minimal, but I've gathered various snippets from Google searches here and here and come up with the following (relevant parts only):
....
<!-- Post over JMS into Manager -->
<to uri="openmq:queue:resman"/>
</route>
</camelContext>
<bean id="openmq" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory">
<bean class="com.sun.messaging.ConnectionFactory">
<property name="imqAddressList" value="localhost:7676"/>
</bean>
</property>
</bean>
I have the following JMS related "features" enabled in Servicemix/OSGI:
[installed ] [3.2.4.RELEASE ] spring-jms
[installed ] [2.13.2 ] camel-jms
and I have the following OSGI bundles installed and active:
[ 89] [Active ] [ ] [ ] [ 50] geronimo-jms_1.1_spec (1.1.1)
[ 126] [Active ] [ ] [ ] [ 50] camel-jms (2.13.2)
The problem I have is a ClassNotFoundException at the point I deploy the Came Route Blueprint into ServiceMix. Here are the relevant snippets from the Stacktrace logged:
org.osgi.service.blueprint.container.ComponentDefinitionException: Unable to instantiate components
Caused by: java.lang.NoClassDefFoundError: javax/jms/JMSContext
Caused by: java.lang.ClassNotFoundException: javax.jms.JMSContext not found by org.apache.geronimo.specs.geronimo-jms_1.1_spec [89]
So on the assumption this is an OSGI bundling issue, I've dug down into the Camel "features" just to confirm the dependencies:
karaf#root> features:info camel-jms
Description of camel-jms 2.13.2 feature
----------------------------------------------------------------
Feature has no configuration
Feature has no configuration files
Feature depends on:
spring [3.2,4)
spring-jms [3.2,4)
camel-core 2.13.2
Feature contains followed bundles:
mvn:org.apache.geronimo.specs/geronimo-jta_1.1_spec/1.1.1 start-level=50
mvn:commons-pool/commons-pool/1.6 start-level=50
mvn:org.apache.geronimo.specs/geronimo-jms_1.1_spec/1.1.1 start-level=50
mvn:org.apache.camel/camel-jms/2.13.2 start-level=50
So it appears that it is the "geronimo-jms_1.1_spec" that is causing the stack trace as it can't find JMSContext. I making a big assumption that as ApacheMQ must be using the same JMS class, so it must be in the environment somewhere. Also, JMSContext seems to be a JMS 2.0 API interface, so is the issue here that the geronimo-jms_1.1_spec bundle is trying to reference a JMS2 API?
I also have the issue of getting the client JARs for OpenMQ installed into the environment. The OpenMQ client JARs shipped with Glassfish4 are plain JARs and not OSGI bundles (see https://java.net/jira/browse/MQ-328), so I plan to either use the "file:wrap" feature to deploy this into ServiceMix, or otherwise unpack and re-pack into the JAR containing my Beans. I don't think this is related to this problem, but I could be wrong.

OK, managed to work this one out finally. The clue was in the reference to javax.jms.JMSContext which is new in the JMS 2.0 API. I was attempting to use the OpenMQ client libraries (imq.jar and jms.jar) taken from the Glassfish4 distribution, which is at JEE7 and hence JMS v1.1. ServiceMix 5.1.1 is still at JMS V1.1, hence the ClassNotFoundException.
Solution:
When connecting to an instance of OpenMQ running under Glassfish4, you need to download and use the OpenMQ client libraries from the previous Glassfish 3.2.2 release. You can obtain this release release from the Glassfish project archives here.
Tests so far show this to be working fine, so if I find anything of relevance going forward I'll come back and update this post.

Related

how to configure Camel transport for CXF with Blueprint

The Documentation of Camel transport for CXF with blueprint
https://camel.apache.org/components/latest/cxf-transport.html
says, the configuration looks like:
client:
<camel:conduit id="*.camel-conduit" camelContextId="camel1" />
server:
<camel:destination id="*.camel-destination" camelContextId="camel1" />
But Blueprint complaints: '*.camel-destination' is not a valid value for 'NCname'. Same for '*.camel-conduit' .
If I leave out the id attribute, the CXF client or CXF server starts up.
But when called, it doesn't find the Camel context.
CXF client:
org.apache.camel.component.cxf.transport.CamelConduit says
IllegalAgumentException "CamelContext must be specified on: conduit:"
CXF server:
org.apache.camel.component.cxf.transport.CamelDestination says
IllegalAgumentException "CamelContext must be specified on:"
Running on Fuse 6.3.
Does anybody know how I must configure CXF transport for Camel in Blueprint?
Try using the "name" attribute instead of the "id" one.
It seems the documentation page(https://camel.apache.org/components/latest/cxf-transport.html) indicates that both the attributes can be used by I think that "name" is the correct one.

Log soap request and response using apache-cxf

I am working on Maven project in Intellij.I have generated wsdl to java using cxf-codegen-plugin. I have created a client and created a tester.java to test the client. I have to log the soap request and response. I have one cxf.xml, config.properties and a client.java files. I am not sure where to configure to log the soap messages. Also i have less idea about webservices. I have also copied log4j.xml to my METAINF.
I have tried all possible scenarios in stack overflow. Not sure which is going wrong.
Assuming you have the latest version of CXF (or fairly recent), the easiest way is to enable the logging feature on the CXF bus in the cxf.xml:
...
<cxf:bus>
<cxf:features>
<cxf:logging/>
</cxf:features>
</cxf:bus>
...
or only on your jaxws endpoint:
<jaxws:endpoint...>
<jaxws:features>
<bean class="org.apache.cxf.feature.LoggingFeature"/>
</jaxws:features>
</jaxws:endpoint>
Make sure you have cxf-rt-features-logging-XXX.jar on your classpath (XXX = your version of CXF).
And configure logging as described here:
http://cxf.apache.org/docs/general-cxf-logging.html
You need to be in INFO level at least.

How to configure dependencies for DataNucleus AppEngine plugin v3?

In my project (Spring Framework + Google App Engine + DataNucleus + JPA) I get the following exception on the server startup:
WARNING: Nestedin org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaMappingContext': Invocation of init method failed;
nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in ServletContext resource [/WEB-INF/spring/db.xml]: Invocation of init method failed;
nested exception is java.lang.NoSuchMethodError: org.datanucleus.metadata.MetaDataUtils.parsePersistenceFiles(Lorg/datanucleus/plugin/PluginManager;Ljava/lang/String;ZLorg/datanucleus/NucleusContext;)[Lorg/datanucleus/metadata/PersistenceFileMetaData;:
java.lang.NoSuchMethodError: org.datanucleus.metadata.MetaDataUtils.parsePersistenceFiles(Lorg/datanucleus/plugin/PluginManager;Ljava/lang/String;ZLorg/datanucleus/NucleusContext;)[Lorg/datanucleus/metadata/PersistenceFileMetaData;
at org.datanucleus.api.jpa.JPAEntityManagerFactory.<init>(JPAEntityManagerFactory.java:342)
at org.datanucleus.api.jpa.PersistenceProviderImpl.createEntityManagerFactory(PersistenceProviderImpl.java:91)
Obviously this exception is throwed during persistence.xml parsing. Spring tries to invoke method MetaDataUtils#parsePersistenceFiles(PluginManager,String,NucleusContext,nucCtx), but it is absent. This method is a part of org.datanucleus:datanucleus-core. At first I thought that I have a missing or duplicate dependency somewhere. I've executed
gradle dependencies
carefully scanned output and found nothing suspicious: only a single version of the dependency.
According to the documentation MetaDataUtils has only one parsePersistenceFiles method:
public static PersistenceFileMetaData[] parsePersistenceFiles(
PluginManager pluginMgr, String persistenceFilename, boolean validate, ClassLoaderResolver clr);
If you are observant, you've probably noticed that it differs in arguments: there is an extra boolean validate argument. Odd thing is that there is no such method in any version of DataNucleus. Why is DataNucleus looking for the method that haven't even existed? I can't get it.
Please help DataNucleus and me find the missing method!
UPDATE
As Neil Stockton pointed out it's because I'm using inconsistent versions of datanucleus-core and datanucleus-api-jpa. But I don't know the right combination of dependencies. And I'm starting to think, that DataNucleus App Engine Plugin 3.0 is not currently ready for usage.
I want to use DataNucleus App Engine Plugin 3.0 because of this issue (fixed in DataNucleus versions 3.2.6 and 3.3.3) and because I need JPA 2.1 features (fetch groups / entity graphs). The DataNucleus App Engine Plugin 3.0 is compatible with the mentioned versions of DataNucleus, but unreleased. I've checked out the plugin from SVN, packaged it, and added to my project as jar (an identical jar is available for download, if you want to repeat this setup yourself).
build.gradle:
apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'appengine'
dependencies {
// App Engine
compile fileTree(dir: 'libs', include: ['*.jar']) // There is datanucleus-appengine-3.0.0-20140128.jar in libs
appengineSdk 'com.google.appengine:appengine-java-sdk:1.9.19'
compile 'com.google.appengine:appengine-api-1.0-sdk:1.9.19'
// persistence
// App Engine and DataNucleus compatibility:
// https://code.google.com/p/datanucleus-appengine/wiki/Compatibility
compile 'org.eclipse.persistence:javax.persistence:2.1.0'
runtime 'org.datanucleus:datanucleus-core:3.2.15'
compile 'org.datanucleus:datanucleus-api-jpa:3.1.3'
compile 'javax.jdo:jdo-api:3.1'
compile 'org.datanucleus:datanucleus-jodatime:3.2.1'
// Spring Framework
compile("org.springframework:spring-webmvc:4.1.6.RELEASE")
compile ("org.springframework.data:spring-data-jpa:1.8.0.RELEASE")
providedCompile 'javax.annotation:javax.annotation-api:1.2'
compile 'com.google.code.gson:gson:2.3.1'
providedCompile 'org.projectlombok:lombok:1.16.+'
}
appengine {
downloadSdk = true
httpAddress = "0.0.0.0"
}
Spring context:
<?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:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"
default-autowire="byName">
<jpa:repositories base-package="<my.package.name>.repositories" />
<!-- The simplest and the most limited form of JPA deployment -->
<!-- For details see http://docs.spring.io/spring/docs/current/spring-framework-reference/html/orm.html#orm-jpa -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="transactions-optional" />
</bean>
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
Persistence unit
<persistence-unit name="transactions-optional">
<provider>org.datanucleus.api.jpa.PersistenceProviderImpl</provider>
<properties>
<property name="datanucleus.NontransactionalRead" value="true" />
<property name="datanucleus.NontransactionalWrite" value="true" />
<property name="datanucleus.ConnectionURL" value="appengine" />
<property name="datanucleus.appengine.datastoreEnableXGTransactions" value="true" />
</properties>
</persistence-unit>
UPDATE:
If I put datanucleus-api-jpa of another version on CLASSPATH, for example
compile 'org.datanucleus:datanucleus-api-jpa:3.2.2'
I get an exception during enhancement:
java.lang.RuntimeException: Unexpected exception
at com.google.appengine.tools.enhancer.Enhancer.execute(Enhancer.java:76)
at com.google.appengine.tools.enhancer.Enhance.<init>(Enhance.java:71)
... 1 more
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
... 5 more
Caused by: org.datanucleus.exceptions.NucleusException:
Plugin (Bundle) "org.datanucleus.api.jpa" is already registered.
Ensure you dont have multiple JAR versions of the same plugin in the classpath.
The URL "file:/<GRADLE_HOME>/appengine-sdk/appengine-java-sdk-1.9.19/lib/opt/tools/datanucleus/v2/datanucleus-api-jpa-3.1.3.jar" is already registered,
and you are trying to register an identical plugin located at URL "file:/<GRADLE_HOME>/caches/modules-2/files-2.1/org.datanucleus/datanucleus-api-jpa/3.2.2/c24c14634c39b5b9a59dcd379dbb6d93da97f3e7/datanucleus-api-jpa-3.2.2.jar."
at org.datanucleus.plugin.NonManagedPluginRegistry.registerBundle(NonManagedPluginRegistry.java:541)
at org.datanucleus.plugin.NonManagedPluginRegistry.registerBundle(NonManagedPluginRegistry.java:395)
From documentation:
The App Engine Java SDK includes version 2.x of the DataNucleus plugin for App Engine. This plugin corresponds to version 3.0 of the DataNucleus Access Platform, which enables you to use the App Engine Datastore via JPA 2.0.
JPA presents a standard interface for interacting with relational databases, but the App Engine datastore is not a relational database. As a result, there are features of JPA that App Engine simply cannot support.
The simple fact is that you have to use consistent versions of the various jars. If using Google's "datanucleus-appengine" v3.0 (SVN) then you MUST have DataNucleus project "datanucleus-core", "datanucleus-api-jpa" v3.2.x (or 3.3.x of the datanucleus-api-jpa) and no other versions. If you get some message about
Plugin (Bundle) "org.datanucleus.api.jpa" is already registered.
then you have multiple versions of that plugin in the CLASSPATH and you should FIX your CLASSPATH (just print out what is in the CLASSPATH and it will tell you ... something like System.getProperty("java.class.path")).
In your case you have
file://appengine-sdk/appengine-java-sdk-1.9.19/lib/opt/tools/datanucleus/v2/datanucleus-api-jpa-3.1.3.jar
and
file://caches/modules-2/files-2.1/org.datanucleus/datanucleus-api-jpa/3.2.2/c24c14634c39b5b9a59dcd379dbb6d93da97f3e7/datanucleus-api-jpa-3.2.2.jar
so get rid of the first one

CXF Web service client not encrypting the SOAP Request XML message

I am learning Webservice security . I am using CXF framework for that. I have developed one test service it will just double up the value whatever we sent. Based on this tutorial
i have added the WS-Policy for XML encryption and signature.
Then i developed the web service client for this service as a eclipse project using CXF.
The following is my client configuration file
<jaxws:client id="doubleItClient" serviceClass="com.DoubleIt" address="http://localhost:8080/myencws/services/DoubleItPort?wsdl">
<jaxws:features>
<bean class="org.apache.cxf.feature.LoggingFeature" />
</jaxws:features>
<jaxws:properties>
<entry key="ws-security.callback-handler" value="com.ClientKeystorePasswordCallback"/>
<entry key="ws-security.encryption.properties" value="com/clientKeystore.properties"/>
<entry key="ws-security.signature.properties" value="com/clientKeystore.properties"/>
<entry key="ws-security.encryption.username" value="myservicekey"/>
</jaxws:properties>
I have generated all the keystore file , and i created the clientKeystore.properties file and placed in the src directory of my project.
But whenever i run this client the SOAP request message was not encrypted. So inn server side i am getting exception like
These policy alternatives can not be satisfied:
{http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}EncryptedParts
{http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702}SignedParts
The following is my SOAP request
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:doubleValue
xmlns:ns2="http://com/"><arg0>5</arg0></ns2:doubleValue></soap:Body></soap:Envelope>
I am using CXF2.7.3. I dont know whats wrong . Please help me.
I have a similar issue with my code before, what was missing was the jar dependencies which does the actual encryption when the security policy are read by your client from the WSDL.
My fix was to add certain maven dependencies in your POM to enable encryption. Check this url: http://cxf.apache.org/docs/using-cxf-with-maven.html
Also read "Enabling WS-SecurityPolicy" section in url http://cxf.apache.org/docs/ws-securitypolicy.html
I hope this helps
Make sure you are using the correct library. Try to include cxf bundle only, remove other cxf dependencies
If you are using maven, something like this:
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-bundle</artifactId>
<version>2.7.18</version>
</dependency>
I ran into the same issue and after much experimentation, the following guidelines help every single time.
Structure your cxf client config xml to have import of META-INF cxf.xml.
Define the cxf bus features (for logging)
Define the http conduits (if needed for TLS Handshake etc)
jaxws:client bean with name attribute as {targetNameSpaceWSDL)/PortName and createdFromAPI=true and abstract=true
Make client tag contain jaxws features. Remember to use latest "security" and not "ws-security"
In your java client class, use the SpringBus to load the cxf client config xml.SVN Link for SpringBus Client Config
Make sure all the required dependencies for WS policy processing is present in classpath like cxf-rt-ws-policy and cxf-rt-ws-security.jar and bouncycastle providers if needed
Note:
security.signature.properties and security.encryption.properties can be externalized as well and directly referred to with the absolute path in the xml value.

CXF Weblogic - Override CXF logger to Slf4j

We are using Apache CXF 2.5.2 for webservice client proxies. We use weblogic 10.3.4. To override the CXF logger we use the following option:
-Dorg.apache.cxf.Logger=org.apache.cxf.common.logging.Slf4jLogger
For the org.apache.cxf.common.logging.Slf4jLogger, we've included the cxf-common-utilities-2.5.2 in our build.
When we try to deploy to weblogic we get the following exception:
[ERROR] Target state: deploy failed on Server AdminServer
[ERROR] java.lang.NoClassDefFoundError: weblogic/wsee/jaxws/spi/WLSProvider
According to documentation, your WebService client should have wseeclient.jar as it's runtime dependency. If the problems is still there, then include wlfullclient.jar (see Creating a wlfullclient.jar for JDK 1.6 client applications ).

Resources