I am trying to configure JMS connection caching and consumer concurrency with Spring to perform some load tests. The application context xml is below.
<?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:cxf="http://cxf.apache.org/core"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:soap="http://cxf.apache.org/bindings/soap"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<context:annotation-config />
<bean id="amqConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://172.18.2.100:8080"/>
</bean>
<bean id="clientCachingConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="amqConnectionFactory"/>
<property name="sessionCacheSize" value="20"/>
<property name="cacheProducers" value="true"/>
</bean>
<bean id="clientContainerListener" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="clientCachingConnectionFactory" />
<property name="destinationName" value="test.load.outside.multispeak.ch.queue" />
</bean>
<jaxws:client
id="load-test-multispeak-ch-client"
xmlns:ns="http://www.multispeak.org/Version_4.1_Release"
serviceClass="org.multispeak.version_4_1_6.CH.CHServerSoap"
serviceName="ns:CH_Server"
endpointName="ns:CH_ServerSoap"
address="jms://"
wsdlLocation="classpath:CH_Server.wsdl">
<jaxws:features>
<bean class="org.apache.cxf.transport.jms.ConnectionFactoryFeature">
<constructor-arg index="0" ref="clientCachingConnectionFactory"/>
</bean>
</jaxws:features>
</jaxws:client>
<bean id="serverCachingConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="amqConnectionFactory"/>
<property name="sessionCacheSize" value="20"/>
<property name="cacheConsumers" value="true"/>
</bean>
<bean id="serverContainerListener" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="serverCachingConnectionFactory" />
<property name="destinationName" value="test.load.outside.multispeak.ch.queue" />
<property name="cacheLevel" value="3" />
<property name="concurrentConsumers" value="10" />
<property name="maxConcurrentConsumers" value="50" />
</bean>
<jaxws:endpoint
id="load-test-multispeak-ch-server"
xmlns:tns="http://www.multispeak.org/Version_4.1_Release"
implementor="pt.fraunhofer.outside.multispeak.ch.server.CHServerSoapImpl"
serviceName="tns:CH_Server"
endpointName="tns:CH_ServerSoap"
publish="false"
address="jms://"
wsdlLocation="classpath:CH_Server.wsdl">
<jaxws:features>
<bean class="org.apache.cxf.feature.LoggingFeature"/>
<bean class="org.apache.cxf.transport.jms.ConnectionFactoryFeature">
<constructor-arg index="0" ref="serverCachingConnectionFactory"/>
</bean>
</jaxws:features>
</jaxws:endpoint>
According to CXF documentation, from 3.0, a ConnectionFactoryFeature should be used instead of a JMSConfigFeature, which is deprecated (http://cxf.apache.org/docs/jms-transport.html). I was following the examples provided at http://cxf.apache.org/scalable-cxf-applications-using-jms-transport.html, but the documentation there seems to refer to CXF versions earlier than 3.0, because JMSConfiguration class in 3.0 does not have caching or concurrency capabilites (no setters/getters). So, I was trying to use Spring to achieve the same result, but without success. The very same documentation refers to Spring DefaultMessageListenerContainer as a container for caching and concurrency configuration, but I was not able to find examples of this with CXF integration, only for pure JMS. Also, DefaultMessageListenerContainer has a setter to register a JMS MessageListener. In case of CXF, I found that that listener is created and managed by CXF runtime and is not provided provided by the application.
Any advice?
Thanks!
Currently you can not set concurrent consumers for CXF 3. I did some performance tests with ActiveMQ and found the performance with CXF 3 is equal to CXF 2 or even better.
The reason is that we now use a MessageListener approach instead of the polling that spring did.
See my website for the performance tests.
We need to be able to tune concurrent and maximum consumers so we can handle our message load. The constraint is in speed of message processing by our applications; CXF is not the bottleneck. Are there plans to re-introduce these parameters in CXF? Can we configure CXF to use a configured DefaultMessageListenerContainer?
Related
I am trying to use mysql database instead of default HSQL in spring batch admin. For that as per documentation
http://docs.spring.io/spring-batch-admin/reference/reference.xhtml and Using jndi datasource with spring batch admin
I copied env-context.xml to src/main/resources/META-INF/batch/override/manager/env-context.xml and changed its configuration value from
<value>classpath:batch-${ENVIRONMENT:hsql}.properties</value>
to
<value>classpath:batch-mysql.properties</value>
Below is my full 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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Use this to set additional properties on beans at run time -->
<bean id="placeholderProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:/org/springframework/batch/admin/bootstrap/batch.properties</value>
<value>classpath:batch-default.properties</value>
<value>classpath:batch-mysql.properties</value>
</list>
</property>
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="ignoreResourceNotFound" value="true" />
<property name="ignoreUnresolvablePlaceholders" value="false" />
<property name="order" value="1" />
</bean>
</beans>
I also tried coping data-source-context.xml to same folder and changing its configurations to mysql
<?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:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/batch" />
<property name="username" value="root" />
<property name="password" value="root" />
<property name="testWhileIdle" value="true"/>
<property name="validationQuery" value="SELECT 1"/>
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- Initialise the database if enabled: -->
<jdbc:initialize-database data-source="dataSource" enabled="false" ignore-failures="DROPS">
<jdbc:script location="classpath*:/org/springframework/batch/core/schema-drop-mysql.sql"/>
<jdbc:script location="classpath:/org/springframework/batch/core/schema-mysql.sql"/>
<jdbc:script location="classpath:/business-schema-mysql.sql"/>
</jdbc:initialize-database>
</beans>
But it still using hsql database? How to override default configuration to use mysql database ?
You shouldn't replace the <value>classpath:batch-${ENVIRONMENT:hsql}.properties</value>. Instead, pass in an environment variable ENVIRONMENT set to mysql. That should cause all the appropriate components to pick up the correct database. You can read more about that feature here: http://docs.spring.io/spring-batch-admin/reference/infrastructure.html#Environment_Settings
If you want to try using just annotations without any xml configurations - try this
HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
jpaVendorAdapter.setDatabase(Database.MYSQL);
It is working. My code is available here - http://github.com/sidnan/spring-batch-example.
I was able to get the connection working with above approach with below steps
First, I copied env-context.xml to src/main/resources/META-INF/batch/override/manager/env-context.xml:
<?xml version="1.0" encoding="UTF-8"?>`
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">`
<!-- Use this to set additional properties on beans at run time -->
<bean id="placeholderProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:/org/springframework/batch/admin/bootstrap/batch.properties</value>
<value>classpath:batch-default.properties</value>
<value>classpath:batch-${ENVIRONMENT:sqlserver}.properties</value>
</list>
</property>
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="ignoreResourceNotFound" value="true" />
<property name="ignoreUnresolvablePlaceholders" value="false" />
<property name="order" value="1" />
</bean>
</beans>
After that, put the following entries in batch-sqlserver.properties of sql server under resources as
# Default placeholders for database platform independent features
batch.remote.base.url=http://localhost:8080/spring-batch-admin-sample
# Non-platform dependent settings that you might like to change
batch.jdbc.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
batch.jdbc.url=jdbc:sqlserver://localhost;databaseName=batchrepo
batch.jdbc.user=la
batch.jdbc.password=la
atch.jdbc.testWhileIdle=true
batch.data.source.init=false
batch.jdbc.validationQuery=
batch.database.incrementer.class=org.springframework.jdbc.support.incrementer.SqlServerMaxValueIncrementer
batch.lob.handler.class=org.springframework.jdbc.support.lob.DefaultLobHandler
batch.database.incrementer.parent=columnIncrementerParent
batch.grid.size=2
batch.jdbc.pool.size=6
batch.verify.cursor.position=true
batch.isolationlevel=ISOLATION_SERIALIZABLE
batch.initializer.enabled=false
Since my tables were already created in the database, I skipped these entries:
#batch.drop.script=/org/springframework/batch/core/schema-drop-sqlserver.sql
#batch.schema.script=/org/springframework/batch/core/schema-sqlserver.sql
#batch.business.schema.script=business-schema-sqlserver.sql
Finally, with batch.initializer.enabled=false, I was finally able to make the connection.
I can monitor the job as well as lunch the new jobs in my admin application. These launched jobs also appear in the DB.
When I try to execute the code java -cp testThermalMap.jar ActivemqPackage.ActiveMqConsumer in command prompt I keep getting this error
org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Config uration problem: Unable to locate Spring NamespaceHandler for XML schema namespa ce [http://camel.apache.org/schema/spring]
As this link says I checked my jar files but I see camel-spring-2.10.3.jar is there. can anyone tell me what are the other possible ways for this error?
Note: The same code working fine in eclipse.
EDIT: Content of mytest.xml is
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core-5.5.0.xsd
http://camel.apache.org/schema/spring"
>
<!-- setup JMS connection factory -->
<bean id="poolConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory" init-method="start" destroy-method="stop">
<property name="maxConnections" value="8"/>
<property name="connectionFactory" ref="jmsConnectionFactory"/>
</bean>
<bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616?jms.prefetchPolicy.queuePrefetch=1" />
</bean>
<!-- setup spring jms TX manager -->
<bean id="jmsTransactionManager" class="org.springframework.jms.connection.JmsTransactionManager">
<property name="connectionFactory" ref="poolConnectionFactory"/>
</bean>
<camelContext id="activeContext" xmlns="http://camel.apache.org/schema/spring">
<routeBuilder ref="activeMQRouter" />
</camelContext>
<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="connectionFactory" ref="poolConnectionFactory"/>
<property name="transacted" value="true"/>
<property name="transactionManager" ref="jmsTransactionManager"/>
</bean>
<bean id="activeMQRouter" class="ActivemqPackage.ActiveMQRouterBuilder"/>
<bean id="activemqProcessor" class="ActivemqPackage.ActiveMQProcessor"/>
I have two ApplicationContexts for my project (very huge project).
One old xml with data
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans default-autowire="autodetect">
</beans>
now I need to add my other project applicatinContext to it or any other way so that none of the modules will be impacted
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<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"
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">
<bean id="positionResponsesDAO"
class="com.xxx.modules.worklist.DAO.Impl.PositionResponsesDAOImpl">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="positionDAO"
class="com.xxx..modules.worklist.DAO.Impl.PositionDAOImpl">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="nextActionDAO"
class="com.xxx..modules.worklist.DAO.Impl.NextActionDAOImpl">
<property name="dataSource" ref="dataSource" />
</bean>
<bean>
....... few more
</bean>
<bean id="workOrderManager" class="com.xxx.modules.worklist.action.manager.impl.WorkOrderManagerImpl">
<property name="positionDO" ref="positionDO" />
<property name="moveWorkOrderDO" ref="moveWorkOrderDO" />
<property name="nextActionDO" ref="nextActionDO" />
<property name="positionDAO" ref="positionDAO" />
<property name="moveResponsesDAO" ref="moveResponsesDAO" />
<property name="moveWorkOrderDAO" ref="moveWorkOrderDAO" />
<property name="nextActionDAO" ref="nextActionDAO" />
<property name="positionResponsesDAO" ref="positionResponsesDAO" />
</bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="oracle.jdbc.driver.OracleDriver" />
<property name="jdbcUrl" value="driverUrl" />
<property name="user" value="MCMGR" />
<property name="password" value="MC123" />
</bean>
</beans>
the first one has Auto-wiring enabled and this one has and needs manual wiring. How can i combined both of them to put into one xml or read two configurations.
I don't see why reading two or more application context files is difficult. The usual Spring idiom is to partition configuration according to layer. I typically have configuration for persistence, service, web, etc. If it's a web application, I just add all of them in using the ContextLoaderListener. You can specify as many configuration files as you need.
I would consider one huge configuration file a liability in the same way that I would look down on one huge class for everything. Decomposition is a computer science fundamental. I'd recommend partitioning your configuration.
Mixing annotation-based and XML-based configuration isn't a problem, either.
You'll only have an issue if the two configurations overlap. You'll have to remove one or the other for the conflicted beans.
You can use the <import/> tag. See http://forum.springsource.org/showthread.php?41811-Application-Context-and-include
I have a Spring MVC web app running on my server. Recently I wanted to add a functionality to notify any logged in users that their role has changed, so they can logout and in again.
I thought about using JMX, so did a small test and it worked fine, except that its not broadcasting the message. So for example, if i have 2 logged in persons, only 1 is receiving the message.
So my question is, is it possible to broadcast a message with JMX to all instances of a web app (active sessions)?
Edit - using JMS
So I am trying with JMS right now, here is my configuration file:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<bean id="connectionFactory"
class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616"/>
</bean>
<bean id="msgDestination"
class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg value="userToLogout.topic"/>
</bean>
<bean id="jmsTemplate"
class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="pubSubDomain" value="true"/>
<property name="receiveTimeout" value="10000"/>
</bean>
<bean id="userNotifier"
class="com.cap.messaging.UserNotifier">
<property name="destination" ref="msgDestination"/>
<property name="jmsTemplate" ref="jmsTemplate"/>
</bean>
<bean id="userNotificationListener"
class="com.cap.messaging.UserNotificationListener">
</bean>
<bean
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="destinationName" value="userToLogout.topic" />
<property name="messageListener" ref="userNotificationListener" />
</bean>
This isnt working right now. However it works if I change the ActiveMQTopic to ActiveMQQueue. what am I missing here, and would this work?
I think the short answer is no. JMX is a single connection API which uses RMI over TCP/IP sockets. Best you can do is to serially unicast to all of your instances or use threads and send to all of your web app sessions in parallel over a number of JMX client connections.
I want to create my wsdl by spring-ws automatically and I inserted the code below to my app context file, but I got the error;
"Cannot locate BeanDefinitionParser for element [dynamic-wsdl]"
what does that mean and what can I do? tnx
<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:sws="http://www.springframework.org/schema/web-services"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org /schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/web-services http://www.springframework.org/schema/web-services/web-services-2.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="payloadMapping"
class="org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping">
<property name="defaultEndpoint" ref="inferenceEndPoint" />
<property name="interceptors">
<list>
<ref local="validatingInterceptor" />
<ref local="payLoadInterceptor" />
</list>
</property>
</bean>
<bean id="payLoadInterceptor"
class="org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor" />
<bean id="validatingInterceptor"
class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
<description>
This interceptor validates the incoming
message contents
according to the 'Request.xsd' XML
Schema file.
</description>
<property name="schema" value="/WEB-INF/schemas/Request.xsd" />
<property name="validateRequest" value="true" />
<property name="validateResponse" value="false" />
</bean>
<bean id="inferenceEndPoint" class="com.mywebsite.ws.web.InferenceEndPoint">
<property name="messageService" ref="messageService" />
</bean>
<bean id="messageService" class="com.mywebsite.ws.service.MessageService">
<property name="inferenceService" ref="inferenceService" />
</bean>
<bean id="schema" class="org.springframework.xml.xsd.SimpleXsdSchema">
<property name="xsd" value="/WEB-INF/schemas/Request.xsd" />
</bean>
<sws:dynamic-wsdl id="mtwsdl"
portTypeName="mtWS"
locationUri="http://localhost:8080/mws/">
<sws:xsd location="/WEB-INF/schemas/Request.xsd" />
</sws:dynamic-wsdl>
<bean id="inferenceService" class="com.mywebsite.ws.im.InferenceService">
<property name="webServiceConfiguration" ref="playerConfiguration" />
</bean>
<!-- <bean id="inferenceConfig" class="com.mywebsite.ws.im.InferenceService">
<constructor-arg ref="playerConfiguration"/> </bean> -->
<!-- ~~~~~~~ Application beans ~~~~~~~ -->
<bean id="playerConfiguration"
class="com.mywebsite.ws.configuration.WebServiceConfiguration"
init-method="init">
<property name="playerConfigXml" value="/WEB-INF/config/webserviceconfiguration.xml" />
<property name="executingPathResource" value="/WEB-INF" />
<property name="developmentMode" value="true" />
</bean>
Replace the first section of your appcontext where you define namespaces:
<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:sws="http://www.springframework.org/schema/web-services"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/web-services http://www.springframework.org/schema/web-services/web-services-2.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
I highly suggest to use Maven. The error you are getting is due to a missing library. In Maven you should have an entry like the following.
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-core</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
I suggest you look at the class path and also server run time path, I think you may have both (spring-ws 1.5.x and spring-ws 2.x) version's of jar files either in the compile/run time path. If that is not the case clean up the both class and run time path and add only spring-ws 2.x jar files.
As for the differences, when spring framework name space handler (WebServicesNamespaceHandler) encounters (dynamic-wsdl tag in spring context file), It will register a (DynamicWsdlBeanDefinitionParser) bean with all the properties specified in the dynamic wsdl tag. It is essentially same as you registering (DefaultWsdl11Definition) bean in spring context.