How to convert this Apache CXF endpoint definition to work in spring-ws - spring

I have an old CXF application that I am trying to convert to spring-ws. Here's the endpoint:
<!-- The service endpoint-->
<jaxws:endpoint id="storeService"
implementor="#storeServiceImpl"
address="/store">
<!--interceptor for basic security. -->
<jaxws:inInterceptors>
<bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
<constructor-arg>
<map>
<entry key="action"
value="UsernameToken"/>
<entry key="passwordType"
value="PasswordText"/>
<entry key="passwordCallbackRef"
value-ref="storeCallback"/>
</map>
</constructor-arg>
</bean>
</jaxws:inInterceptors>
<jaxws:properties>
<entry key="security.enable.nonce.cache" value="false" />
<entry key="security.enable.timestamp.cache" value="false" />
<entry key="security.timestamp.timeToLive" value="600000000" />
<entry key="ws-security.must-understand" value="false" />
</jaxws:properties>
</jaxws:endpoint>
I get how to setup spring-security so that I do not have to use the old security interceptor.
The issue I am running into is: How do I configure the end point in spring-ws to use properties that I define?
The mustUnderstand property in particular is crucial to using spring-ws. I am getting the so-called "famous" mustUnderstand error which is described in:
Spring-WS WSA header contains hardcoded mustUnderstand attribute
Any help will be appreciated!
PS Partial payload being sent to the service:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:ser="http://example.com/" xmlns:req="http://xmlns.example.com/salesforce/notifications/request">
<soap:Header />
<soap:Body>
<ser:setStore>
<PayloadRequest xmlns:ns2="http://xmlns.example.com/salesforce/notifications/request" xmlns:ns3="urn:sobject.enterprise.soap.sforce.com">
<req:metadata>
<ns2:Version_Number__c>1.0</ns2:Version_Number__c>
<ns2:Time_Stamp__c>2015-11-09T23:41:01.753Z</ns2:Time_Stamp__c>
</req:metadata>
<req:payload>
...
</req:payload>
</ser:setStore>
</soap:setStore>
</soap:Envelope>

Related

pass message to producer through jms

How to pass a message to producer(a method defined to sent message to activemq) through spring integration.
Actual requirement is, i need insert data to database and that data to be moved to a queue in activemq,both the operations need to be happened parallely. How can i do it.
<jms:message-driven-channel-adapter id="helloWorldJMSAdapater" destination="helloWorldJMSQueue" connection-factory="jmsConnectionFactory"
channel="postChannel" />
<int:channel id="requestChannel" />
<int:channel id="outputChannel" />
<int-http:inbound-gateway request-channel="requestChannel"
reply-channel="outputChannel" supported-methods="GET" path="/register"
view-name="register">
<int-http:request-mapping />
</int-http:inbound-gateway>
<int-http:inbound-gateway request-channel="postChannel"
reply-channel="outputChannel" supported-methods="POST" path="/registerNew"
error-channel="errorChannel" view-name="login">
</int-http:inbound-gateway>
<int-jdbc:outbound-channel-adapter
query="insert into user_registration (USER_FSTNAME,USER_ADDRESS,USER_STATE,USER_CITY,USER_OCCUPATION,USER_EMAIL,USER_CONTACT,USER_PASSWORD)
values (:fstName,:addrss,:state,:city,:occupation,:email,:contact,:password)"
channel="postChannel" data-source="dataSource" id="sample" sql-parameter-source-factory="spelSource" />
<int:service-activator ref="userService" input-channel="requestChannel"
output-channel="outputChannel" method="message"/>
<bean id="spelSource"
class="org.springframework.integration.jdbc.ExpressionEvaluatingSqlParameterSourceFactory">
<property name="parameterExpressions">
<map>
<entry key="fstName" value="payload[firstName]" />
<entry key="lstName" value="payload[lastName]" />
<entry key="addrss" value="payload[address]" />
<entry key="state" value="payload[state]" />
<entry key="city" value="payload[city]" />
<entry key="occupation" value="payload[occupation]" />
<entry key="email" value="payload[email]"/>
<entry key="contact" value="payload[contact]"/>
<entry key="password" value="payload[password]"/>
</map>
</property>
</bean>
Use a <publish-subscribe-channel/> and subscribe both endpoints to it. They will be executed serially by default, or in parallel if you add a task-executor to the channel.

PayloadValidatingInterceptor - validate only concrete wsdl

I have one Spring WS servlet with two endpoints and two wsdl files. Requests/responses are being validated with PayloadValidatingInterceptor. Content of spring-ws-servlet.xml:
<context:component-scan base-package="cz.legend.mzv.spi.ws.ei.endpoints" />
<context:component-scan base-package="cz.legend.mzv.spi.ws.de.endpoints" />
<sws:annotation-driven />
<sws:static-wsdl id="entityImport" location="classpath:/wsdl/entityImport.wsdl" />
<sws:static-wsdl id="documentEvidence"
location="classpath:/wsdl/documentEvidence.wsdl" />
<oxm:jaxb2-marshaller id="jaxb2Marshaller"
contextPath="cz.legend.mzv.spi.ws.jaxb.generated" />
<bean id="endpointAdapter" class="org.springframework.ws.server.endpoint.adapter.MarshallingMethodEndpointAdapter">
<constructor-arg ref="jaxb2Marshaller" />
</bean>
<sws:interceptors>
<bean
class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
<property name="schema" value="classpath:/xsd/vums_spi_de.xsd" />
<property name="validateRequest" value="true" />
<property name="validateResponse" value="true" />
</bean>
</sws:interceptors>
Interceptor is applied on both services. I need the interceptor to be applied only on service described by documentEvidence.wsdl. One option is to make two separate spring servlets. But I want to use only one servlet.
Solution:
Alternatively, you can use or
elements to specify for which payload root name or SOAP action the
interceptor should apply:
<sws:interceptors>
<bean class="samples.MyGlobalInterceptor"/>
<sws:payloadRoot namespaceUri="http://www.example.com">
<bean class="samples.MyPayloadRootInterceptor"/>
</sws:payloadRoot>
<sws:soapAction value="http://www.example.com/SoapAction">
<bean class="samples.MySoapActionInterceptor1"/>
<ref bean="mySoapActionInterceptor2"/>
</sws:soapAction>
</sws:interceptors>

Connect to EMS JMS queue using Spring + SSL

I'm having some issues to create a connection to (and reading from) a Tibco EMS JMS queue, using SSL and mutual authentication with certicates.
Here is my Spring config:
<!-- TIBCO Connection Factory Bean -->
<bean id="tibcoConnectionFactory" class="com.tibco.tibjms.TibjmsConnectionFactory">
<constructor-arg value="ssl://mytibco.server.address:30113" />
<property name="userName" value="userName" />
<property name="userPassword" value="${tibcoPwd}" />
<property name="connAttemptCount" value="10" />
<property name="connAttemptDelay" value="100" />
<property name="connAttemptTimeout" value="1000" />
<property name="reconnAttemptCount" value="10" />
<property name="reconnAttemptDelay" value="100" />
<property name="reconnAttemptTimeout" value="1000" />
<property name="SSLVendor" value="j2se" />
<property name="SSLEnableVerifyHost" value="false" />
<property name="SSLEnableVerifyHostName" value="false" />
<property name="SSLTrace" value="true" />
<property name="SSLDebugTrace" value="true" />
<property name="SSLIdentity" value="c:\\cert\\testCert.p12" />
<property name="SSLPassword" value="*******" />
</bean>
<!-- Spring CachingConnectionFactory Bean -->
<bean id="tibcoJmsConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<constructor-arg ref="tibcoConnectionFactory" />
<property name="reconnectOnException" value="true" />
<property name="sessionCacheSize" value="10" />
</bean>
When I try to put something on the queue, I receive the following stack trace:
[TIBCO EMS]: [J] [SSL] initializing security with vendor 'j2se'
[TIBCO EMS]: [J] [SSL] client version 5.1.0, security version 3.0.0, SSL initialized with vendor 'j2se'
[TIBCO EMS]: [J] [SSL] WARNING: server verification is disabled, will trust any server.
[TIBCO EMS]: [J] [SSL] reading client identity from byte array, format=AUTO
WARN [jmsContainer-1] org.springframework.jms.listener.DefaultMessageListenerContainer - Execution of JMS message listener failed
org.springframework.jms.JmsSecurityException: Error occured while reading identity data: Invalid or not supported identity data; nested exception is javax.jms.JMSSecurityException: Error occured while reading identity data: Invalid or not supported identity data
at org.springframework.jms.support.JmsUtils.convertJmsAccessException(JmsUtils.java:283)
at org.springframework.jms.support.JmsAccessor.convertJmsAccessException(JmsAccessor.java:168)
at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:474)
at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:436)
...
at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:543)
at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:482)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:451)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:323)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:241)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:982)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:974)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:876)
at java.lang.Thread.run(Thread.java:662)
Caused by: javax.jms.JMSSecurityException: Error occured while reading identity data: Invalid or not supported identity data
at com.tibco.tibjms.TibjmsSSL._identityFromStore(TibjmsSSL.java:2670)
at com.tibco.tibjms.TibjmsSSL.createIdentity(TibjmsSSL.java:2575)
at com.tibco.tibjms.TibjmsxLinkSSL._initSSL(TibjmsxLinkSSL.java:309)
at com.tibco.tibjms.TibjmsxLinkSSL.connect(TibjmsxLinkSSL.java:390)
at com.tibco.tibjms.TibjmsConnection._create(TibjmsConnection.java:1288)
at com.tibco.tibjms.TibjmsConnection.<init>(TibjmsConnection.java:4115)
at com.tibco.tibjms.TibjmsxCFImpl._createImpl(TibjmsxCFImpl.java:209)
at com.tibco.tibjms.TibjmsxCFImpl._createConnection(TibjmsxCFImpl.java:253)
at com.tibco.tibjms.TibjmsConnectionFactory.createConnection(TibjmsConnectionFactory.java:36)
at org.springframework.jms.connection.SingleConnectionFactory.doCreateConnection(SingleConnectionFactory.java:343)
at org.springframework.jms.connection.SingleConnectionFactory.initConnection(SingleConnectionFactory.java:290)
at org.springframework.jms.connection.SingleConnectionFactory.createConnection(SingleConnectionFactory.java:227)
at org.springframework.jms.support.JmsAccessor.createConnection(JmsAccessor.java:184)
at org.springframework.jms.core.JmsTemplate.access$500(JmsTemplate.java:90)
at org.springframework.jms.core.JmsTemplate$JmsTemplateResourceFactory.createConnection(JmsTemplate.java:1028)
at org.springframework.jms.connection.ConnectionFactoryUtils.doGetTransactionalSession(ConnectionFactoryUtils.java:298)
at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:458)
... 12 more
Until now, I can't succeed to resolve the ssl handshake.
How to resolve this issue?
The problem you having is due to a combination of Spring and the fact that com.tibco.tibjms.TibjmsConnectionFactory overloads the setSSLIdentity method, allowing either a byte[] or String to be passed.
This is confusing Spring which is invoking setSSLIdentity(byte[]) meaning that com.tibco.tibjms.TibjmsConnectionFactory is treating the bytes of the string c:\\cert\\testCert.p12 as a certificate (which it clearly isn't).
Unfortunately Spring doesn't let you force the type on the property element (like it does on constructor-arg, at least at the time of writing), so you'll use the constructor that takes a java.utils.Map and pass the configuration as properties:
<bean id="tibcoConnectionFactory" class="com.tibco.tibjms.TibjmsConnectionFactory">
<constructor-arg value="ssl://mytibco.server.address:30113" />
<constructor-arg><null/></constructor-arg>
<constructor-arg>
<util:map>
<entry key="com.tibco.tibjms.factory.username" value="userName"/>
<entry key="com.tibco.tibjms.factory.password" value="${tibcoPwd}"/>
<entry key="com.tibco.tibjms.connect.attemptcount" value="10"/>
<entry key="com.tibco.tibjms.connect.attemptdelay" value="100"/>
<entry key="com.tibco.tibjms.connect.attempttimeout" value="1000"/>
<entry key="com.tibco.tibjms.reconnect.attemptcount" value="10"/>
<entry key="com.tibco.tibjms.reconnect.attemptdelay" value="10-"/>
<entry key="com.tibco.tibjms.reconnect.attempttimeout" value="1000" />
<entry key="com.tibco.tibjms.ssl.vendor" value="j2se"/>
<entry key="com.tibco.tibjms.ssl.enable_verify_host" value="false"/>
<entry key="com.tibco.tibjms.ssl.enable_verify_hostname" value="false"/>
<entry key="com.tibco.tibjms.ssl.trace" value="true"/>
<entry key="com.tibco.tibjms.ssl.debug_trace" value="true"/>
<entry key="com.tibco.tibjms.ssl.identity" value="c:/cert/testCert.p12"/>
<entry key="com.tibco.tibjms.ssl.password" value="value="*******"/>
<util:map>
</constructor-arg>
</bean>
For anyone looking for the names for other properties, you can drill into the associated setter and see property name there.
The problem is that TibjmsConnectionFactory overloads the setSSLIdentity(..) setter.
The available setters are:
setSSLIdentity(byte[] identity)
setSSLIdentity(java.lang.String sslIdentity)
This means that Spring doesn't know which setter to call. I haven't researched proof of this, but from a google search I found out that it's up to the JVM implementation to decide which setter will be called and, in my case, it was different with every application restart (Oracle JVM). In fact this is a known issue, see https://github.com/flyway/flyway/issues/890 .
One solution is to call the constructor with a Map containing your properties:
TibjmsConnectionFactory(java.lang.String serverUrl,
java.lang.String clientId,
java.util.Map properties)
See also https://docs.tibco.com/pub/enterprise_message_service/8.1.0/doc/html/tib_ems_api_reference/api/javadoc/com/tibco/tibjms/TibjmsConnectionFactory.html#setSSLIdentity(java.lang.String)
PS: Sorry for resurrecting an old question, but as there is quite a high traffic for this question, this may help others in the future.
It seems that it's not reading .p12 correctly. It must log something like:
[TIBCO EMS]: [J] [SSL] reading client identity from file 'c:\cert\testCert.p12', format=PKCS12
note the format=...
Enter SSLIdentity as /c:/cert/testCert.p12. Then only it will recognize your p12 file, else will treat it as byte array

How do you implement Restlet Basic HTTP Authentication on a router?

I read the Restlet documentation on how to implement Basic HTTP Authentication but mine is not working when I make a request to a resource. Any reason why mine is not working?
Application Context:
<!-- Used to map routes to Restlet resources -->
<bean id="router" class="org.restlet.ext.spring.SpringRouter">
<property name="attachments">
<map>
<!-- I removed the actual values because it references a company -->
<entry key="/getCompanies" value="ClassResource" />
<entry key="/getList" value="ClassResource" />
<entry key="/getFile" value="ClassResource" />
<entry key="/archiveFile" value="ClassResource" />
</map>
</property>
</bean>
<!-- Used to have login authentication for requests -->
<bean id="challengeAuthenticator" class="org.restlet.security.ChallengeAuthenticator">
<constructor-arg><null /></constructor-arg>
<!-- Sets the Challenge scheme parameter to the static class member -->
<constructor-arg value="#{ T(org.restlet.data.ChallengeScheme).HTTP_BASIC }" />
<constructor-arg value="WSRealm" />
<property name="next" ref="router" />
</bean>
<!-- Creates a restlet component that contains the server and attachs the application -->
<bean id="restletComponent" class="org.restlet.ext.spring.SpringComponent">
<!-- Sets the server in the Restlet component -->
<property name="server" ref="server" />
<!-- Attachs the application to the virtual host -->
<property name="defaultTarget" ref="application" />
</bean>
I was assuming that since I set the challenge Authenticator next method to the router when I make a request it hits the router and hits the authenticator before going to the resource.
Java Code:
ApplicationContext springContext = new GenericXmlApplicationContext("applicationContext.xml");
Component restletComponent = (Component) springContext.getBean("restletComponent");
GetFilesApplication application = (GetFilesApplication) springContext.getBean("application");
ChallengeAuthenticator challengeAuthenticator =
(ChallengeAuthenticator) springContext.getBean("challengeAuthenticator");
Config config = application.getConfig();
MapVerifier mapVerifier = new MapVerifier();
// Puts the user name and password (encrypted) in the map verifier
mapVerifier.getLocalSecrets().put(config.getUsername(), StringCipher.encrypt(
config.getPassword()).toCharArray());
challengeAuthenticator.setVerifier(mapVerifier);
restletComponent.getDefaultHost().attachDefault(challengeAuthenticator);
// Start the component
restletComponent.start();
Like I said earlier, the only thing I can see wrong with it is, I am unsure about setting challenge authenticator next method value to the router.
Also for the client side added:
clientResource.setChallengeResponse(ChallengeScheme.HTTP_BASIC, "correctUser", StringCipher.encrypt("password"));
Forgot to mention that I am testing this on my local machine the client and the web service.
Solved it. It took so long to figure out but here is how I got it to work.
Java Code on Server Side:
// Removed and added to Application Context
restletComponent.getDefaultHost().attachDefault(challengeAuthenticator);
Application Context:
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>configuration.properties</value>
<value>log4j.properties</value>
</list>
</property>
</bean>
<bean id="config" class="Config class path location">
<property name="filePath" value="${Properties entry value}"/>
<property name="archivePath" value="${Properties entry value}"/>
<property name="username" value="${Properties entry value}"/>
<property name="password" value="${Properties entry value}"/>
</bean>
<!-- Restlet application -->
<bean id="application" class="Application class path location" scope="singleton">
<!-- Sets the router for the application -->
<property name="root" ref="router" />
<property name="config" ref="config" />
</bean>
<!-- Sets up the server -->
<bean id="server" class="org.restlet.ext.spring.SpringServer">
<constructor-arg value="${Properties entry value}" />
<constructor-arg value="${Properties entry value}" />
</bean>
<!-- Used to map routes to Restlet resources -->
<bean id="router" class="org.restlet.ext.spring.SpringRouter">
<property name="attachments">
<map>
<entry key="/getCompanies" value="Resource class path location" />
<entry key="/getList" value="Resource class path location" />
<entry key="/getFile" value="Resource class path location" />
<entry key="/archiveFile" value="Resource class path location" />
</map>
</property>
</bean>
<!-- Creates a restlet component that contains the server and attachs the application -->
<bean id="restletComponent" class="org.restlet.ext.spring.SpringComponent">
<!-- Sets the server in the Restlet component -->
<property name="server" ref="server" />
<!-- Attachs the application to the virtual host -->
<property name="defaultTarget" ref="application" />
<property name="defaultHost" ref="defaultHost" />
</bean>
<!-- Used to have login authentication for requests -->
<bean id="challengeAuthenticator" class="org.restlet.security.ChallengeAuthenticator">
<constructor-arg><null /></constructor-arg>
<!-- Sets the Challenge scheme parameter to the static class member -->
<constructor-arg value="#{ T(org.restlet.data.ChallengeScheme).HTTP_BASIC }" />
<constructor-arg value="GetWSRealm" />
<property name="next" ref="application" />
</bean>
<bean id="defaultHost" class="org.restlet.ext.spring.SpringHost">
<constructor-arg ref="restletComponent" />
<property name="defaultAttachment" ref="challengeAuthenticator" />
</bean>
Hope this helps others trying to get their application working. It took me a while to get this to work. :)

Read template from the database - VelocityEngine

I am storing the templates I use with velocity in the DB and I wan to configure it to read the templates from the DB.
my bean definition is:
<bean id="velocityEngineBasedOnDB" class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
<property name="velocityProperties">
<map>
<entry key="resource.loader" value="ds"/>
<entry key="ds.resource.loader.class" value="org.apache.velocity.runtime.resource.loader.DataSourceResourceLoader"/>
<entry key="ds.resource.loader.resource.table" value="tb_velocity_template"/>
<entry key="ds.resource.loader.resource.keycolumn" value="id_template"/>
<entry key="ds.resource.loader.resource.templatecolumn" value="template_definition"/>
<entry key="ds.resource.loader.resource.datasource" value-ref="dataSource"/>
</map>
</property>
</bean>
but I got java.lang.ClassCastException: 'resource.datasource' doesn't map to a String object.
So how I configure the data source as string?
Works for me
<bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
<property name="velocityProperties">
<map>
<entry key="resource.loader" value="ds"/>
<!--<entry key="ds.resource.loader.class" value="org.apache.velocity.runtime.resource.loader.DataSourceResourceLoader"/>--><!--should be left out-->
<entry key="ds.resource.loader.resource.table" value="templates" />
<entry key="ds.resource.loader.resource.keycolumn" value="tid" />
<entry key="ds.resource.loader.resource.templatecolumn" value="template" />
<entry key="ds.resource.loader.resource.timestampcolumn" value="updated" />
<entry key="ds.resource.loader.instance" value-ref="dataSourceLoader" />
<entry key="ds.resource.loader.cache" value="true" />
</map>
</property>
</bean>
Data Source Loader:
<bean id="dataSourceLoader" class="org.apache.velocity.runtime.resource.loader.DataSourceResourceLoader"> <property name="dataSource" ref="myDataSource"/><!-- myDataSource is a com.mchange.v2.c3p0.ComboPooledDataSource type--> </bean>
You have to configure another bean with id "datasource" and that will allow Spring to instantiate an instance of a class inheriting from java.sql.Datasource. It may be an OracleDataSource, for example if your database is Oracle.
you should set ds.resource.loader.instance ref a spring bean,eg:
<bean id="resourceLoader"
class="xx.common.mail.MongoDataSourceResourceLoader"
p:mongoTemplate-ref="mongoTemplate"/>
<bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
<property name="velocityProperties">
<map>
<entry key="resource.loader" value="ds"/>
<entry key="ds.resource.loader.instance" value-ref="resourceLoader"/>
</map>
</property>
<entry key="ds.resource.loader.resource.datasource" value-ref="dataSource"/>
value-ref doesnt work for me
change to value="datasource" and try.
It may be that value-ref support is added in higher versions (if any).
I am using Velocity 1.7
<!-- myDataSource is a com.mchange.v2.c3p0.ComboPooledDataSource type-->
<bean id="dataSourceLoader" class="org.apache.velocity.runtime.resource.loader.DataSourceResourceLoader">
<property name="dataSource" ref="myDataSource"/>
</bean>

Resources