I have a requirement to publish an encrypted file (file size can be upto 100 M.B) to a jms queue. Along with the file i have to send a decryption key to the same message which is used by the jms listener to to decrypt file.
I have attached the applicationContext.xml and the jms publisher. Currently i am tryign to use MapMessage to publish both the file and the key, but getting the below error.
2015-12-09 19:31:12,709 INFO [simBatchQueueListener-1] - Received a message for updating organization
2015-12-09 19:31:12,719 DEBUG [simBatchQueueListener-1] - Received a JMS message: Key ->null
2015-12-09 19:31:12,729 DEBUG [simBatchQueueListener-1] - Received a JMS message: File ->null
2015-12-09 19:31:12,729 DEBUG [simBatchQueueListener-1] - Received a JMS message: bytesMessage ->null
weblogic.jms.common.MessageFormatException: [JMSClientExceptions:055130]Invalid data type: java.io.BufferedWriter
at weblogic.jms.common.MapMessageImpl.setObject(MapMessageImpl.java:234)
at com.vodafone.m2m.kssv.jms.JMSNotifier$1.createMessage(JMSNotifier.java:113)
at com.vodafone.m2m.kssv.jms.JMSNotifier$1.createMessage(JMSNotifier.java:106)
at org.springframework.jms.core.JmsTemplate.doSend(JmsTemplate.java:602)
at org.springframework.jms.core.JmsTemplate$4.doInJms(JmsTemplate.java:583)
at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:493)
at org.springframework.jms.core.JmsTemplate.send(JmsTemplate.java:579)
at com.vodafone.m2m.kssv.jms.JMSNotifier.publishMessage(JMSNotifier.java:106)
at com.vodafone.m2m.kssv.directoryscanner.file.SIMBatchReturnFileProcessor.run(SIMBatchReturnFileProcessor.java:88)
at java.lang.Thread.run(Thread.java:744)
The jms publish should be synchronous. Once the message is read from the queue an ID will be created and the ID need to be acknowledged to the publisher.
As I am new to coding jms could anyone please help me how I can achieve this.
public class JMSNotifier {
private final Logger LOG = LoggerFactory.getLogger(JMSNotifier.class);
private static final String myName = JMSNotifier.class.getSimpleName();
private String filename = null;
private FileInputStream inStream = null;
private BytesMessage bytesMessage = null;
private int bytes_read = 0;
private int BUFLEN = 64;
private byte[] buf1 = new byte[BUFLEN];
private byte[] buf2 = new byte[BUFLEN];
private int length = 0;
private int exitResult = 0;
#Autowired
private JmsTemplate jmsTemplate;
private String simBatchQueue;
private MapMessage m = null;
#Required
public void setSimBatchQueue(String simBatchQueue) {
this.simBatchQueue = simBatchQueue;
}
public synchronized void publishMessage(String destinationName, String msg) throws JMSException {
LOG.debug("Sending message {} on {} queue...", msg.toString(), destinationName);
try {
filename = new String("C:\\Vijay\\cleartext.txt");
inStream = new FileInputStream(filename);
} catch (IOException e) {
System.out.println("Problem getting file: " + e.toString());
System.exit(1);
}
if (Constants.SIM_BATCH_QUEUE.equals(destinationName)) {
destinationName = simBatchQueue;
LOG.trace("{}: Attempting messgage for D_N_SIM_BATCH_QUEUE {} ", myName, simBatchQueue);
} else {
LOG.trace("{}: Unknow JMS destinaion name {} ", myName, destinationName);
throw new JMSException("Unknow JMS destinaion name {}" + destinationName);
}
jmsTemplate.send(destinationName, new MessageCreator() {
#Override
public MapMessage createMessage(Session session) throws JMSException {
try {
m = session.createMapMessage();
m.setObject("file", writeToFile(inStream));
m.setObject("key","123");
return m;
} catch (Exception ex) {
ex.printStackTrace();
return m;
}
}
});
}
public static String prepareNormalDateString() {
Calendar tzCal = Calendar.getInstance();
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-ddhhmmss");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
StringBuffer date = new StringBuffer(dateFormat.format(tzCal.getTime()));
date.append("UTC");
return (date.toString());
}
private BufferedWriter writeToFile(InputStream is) {
BufferedReader br = null;
String time = prepareNormalDateString();
String filepath = "C:\\vijay\\File" + time + ".csv";
String line;
BufferedWriter bufferedWriter = null;
try {
bufferedWriter = new BufferedWriter(new FileWriter(filepath));
br = new BufferedReader(new InputStreamReader(is));
while ((line = br.readLine()) != null) {
bufferedWriter.write(line);
}
bufferedWriter.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return bufferedWriter;
}
}
public class SimBatchQueueMessageHandler implements MessageListener {
private static org.slf4j.Logger myLogger = LoggerFactory.getLogger(SimBatchQueueMessageHandler.class);
private String myName = SimBatchQueueMessageHandler.class.getSimpleName();
int bytes_read = 0;
final int BUFLEN = 64;
byte[] buf1 = new byte[BUFLEN];
byte[] buf2 = new byte[BUFLEN];
int length = 0;
int exitResult = 0;
FileOutputStream fos = null;
File newFile = null;
private static int count = 1;
#Override
public synchronized void onMessage(Message message) {
try {
myLogger.info("Received a message for updating organization");
Source source;
count = count + 1;
if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
source = new StringSource(textMessage.getText());
myLogger.debug("Text Message received {}", textMessage.getText());
} else if (message instanceof MapMessage) {
MapMessage msg = (MapMessage) message;
myLogger.debug("Received a JMS message: Key ->" + msg.getObject("key"));
myLogger.debug("Received a JMS message: File ->" + msg.getObject("file"));
Object bytesMessage = msg.getObject("file");
myLogger.debug("Received a JMS message: bytesMessage ->" + bytesMessage);
} else if (message instanceof BytesMessage) {
else {
throw new MessageConversionException("Unsupported JMS Message type " + message.getClass() + ", expected instance of TextMessage or BytesMessage for " + message);
}
Object[] params = new Object[]{myName};
} catch (JMSException jmsEx) {
myLogger.error("Error occured while publishing" + jmsEx);
}
}
}
<?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:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:jms="http://www.springframework.org/schema/jms"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:ws="http://jax-ws.dev.java.net/spring/core"
xmlns:wss="http://jax-ws.dev.java.net/spring/servlet"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-3.0.xsd
http://jax-ws.dev.java.net/spring/core
http://jax-ws.java.net/spring/core.xsd
http://jax-ws.dev.java.net/spring/servlet
http://jax-ws.java.net/spring/servlet.xsd">
<!--
Activates various annotations to be detected in bean classes:
Spring's #Required and #Autowired, as well as JSR 250's #Resource.
-->
<context:annotation-config/>
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass" value="org.springframework.util.Log4jConfigurer" />
<property name="targetMethod" value="initLogging" />
<property name="arguments">
<list>
<value>file:///${MYCOMPONENT_CONFIG_PATH}/log4j.properties</value>
</list>
</property>
</bean>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="searchSystemEnvironment" value="true" />
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>file:///${MYCOMPONENT_CONFIG_PATH}/jdbc.properties</value>
<!--<value>file:///${MYCOMPONENT_CONFIG_PATH}/MYCOMPONENTConfig.xml</value>-->
<value>file:///${MYCOMPONENT_CONFIG_PATH}/MYCOMPONENT.properties</value>
</list>
</property>
</bean>
<!--
Uses Apache Commons DBCP for connection pooling. See Commons DBCP documentation
for the required JAR files. Alternatively you can use another connection pool
such as C3P0, similarly configured using Spring.
-->
<!-- USE FOR GLASSFISH DATABASE POOLING
<bean id="dataSourceMYCOMPONENT" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="${MYCOMPONENT.jdbc.dataSource}"/>
</bean>-->
<!-- USE FOR SPRING DATABASE POOLING -->
<bean id="dataSourceMYCOMPONENT" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
p:driverClassName="${jdbc.driverClassName}" p:url="${jdbc.url}" p:username="${jdbc.username}"
p:password="${jdbc.password}" >
<property name="defaultAutoCommit" value="false"/>
<property name="maxActive" value="10"/>
<property name="maxIdle" value="5"/>
<property name="minIdle" value="2"/>
<property name="initialSize" value="1"/>
<property name="maxWait" value="500"/>
<property name="testOnBorrow" value ="true"/>
<property name="timeBetweenEvictionRunsMillis" value ="1800000"/>
<property name="minEvictableIdleTimeMillis" value ="300000"/>
</bean>
<bean id="lobHandler" class="org.springframework.jdbc.support.lob.OracleLobHandler" lazy-init="true">
<property name="nativeJdbcExtractor" ref="nativeJdbcExtractor"/>
</bean>
<bean id="dao" class="com.mycompany.m2m.MYCOMPONENT.support.dataaccess.jdbc.JdbcDataAccessObject">
<!-- Must set schemaName before dataSource! -->
<property name="schemaName" value="${jdbc.schema}"/>
<property name="dbUser" value="${jdbc.username}"/>
<property name="dataSource" ref="dataSourceMYCOMPONENT"/>
</bean>
<!-- Ends -->
<!-- USE FOR JMS CONFIGURATION ************************* -->
<bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate" ref="jndiTemplate" />
<property name="jndiName" value="${MYCOMPONENT.jms.connectionFactory}" />
</bean>
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">${MYCOMPONENT.jndi.initialFactory}</prop>
<prop key="java.naming.provider.url">${MYCOMPONENT.jndi.providerUrl}</prop>
</props>
</property>
</bean>
<bean id="jmsDestinationResolver" class="org.springframework.jms.support.destination.JndiDestinationResolver">
<property name="jndiTemplate" ref="jndiTemplate" />
<property name="cache" value="true" />
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="defaultDestination" ref="simBatchQueue" />
<property name="destinationResolver" ref="jmsDestinationResolver" />
<property name="connectionFactory" ref="connectionFactory" />
<property name="sessionAcknowledgeModeName" value="AUTO_ACKNOWLEDGE" />
<property name="sessionTransacted" value="false" />
</bean>
<bean id="jmsNotifier" class="com.mycompany.m2m.MYCOMPONENT.jms.JMSNotifier">
<property name="simBatchQueue" value="${MYCOMPONENT.jms.simBatchQueue}" />
</bean>
<!-- JMS Message Listener to handle messages from MYCOMPONENT-->
<bean id="simBatchQueueMessageListener" class="com.mycompany.m2m.MYCOMPONENT.jms.listener.SimBatchQueueMessageHandler"/>
<bean id="simBatchQueue" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate" ref="jndiTemplate" />
<property name="jndiName" value="${MYCOMPONENT.jms.simBatchQueue}" />
</bean>
<bean id="simBatchQueueListener" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="concurrentConsumers" value="1" />
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="simBatchQueue" />
<property name="messageListener" ref="simBatchQueueMessageListener" />
<property name="pubSubDomain" value="true"/>
<property name="subscriptionDurable" value="false"/>
<!--<property name="durableSubscriptionName" value="${sasm.jms.orgDurableSubName}"/>-->
</bean>
</beans>
Related
I am developing an application with REST services. I am using dependency injection to, among other things, inject EntityManagerFactory. I have a heavy process where I want to use threads, but it is giving me a deadlock when using EntityManager. The code:
Note: All code has been simplified and renamed classes to explain the problem
persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="mypersistenceunit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<!-- Entities -->
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.event.merge.entity_copy_observer" value="allow" />
<property name="hibernate.connection.autocommit" value="false"/>
</properties>
</persistence-unit>
</persistence>
applicationContext.xml:
<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:tx="http://www.springframework.org/schema/tx"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
"
default-autowire="byName">
<context:property-placeholder location="classpath:database.properties"/>
<bean id="logDao" class="my.package.example.dao.LogDao">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="extractDataDao" class="my.package.example.source.ExtractDataDao">
<property name="completeDatabaseModel" ref="completeDatabaseModel"/>
</bean>
<bean id="completeDatabaseModel" class="my.package.example.source.CompleteDatabaseModel">
<property name="logDao" ref="logDao" />
</bean>
<bean id="fill" class="my.package.example.services.impl.FillDatabaseServiceImpl">
<property name="extractDataDao" ref="extractDataDao" />
</bean>
<!-- Configuracion de acceso a base de datos -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="persistenceUnitName" value="mypersistenceunit"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="false" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
</bean>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
</bean>
<bean id="myDataSource" parent="dataSource">
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
FillDatabaseServiceImpl.java:
public class FillDatabaseServiceImpl implements FillDatabaseService {
private ExtractDataDao extractDataDao;
private final static Gson gson = new Gson();
#Override
public Response start() {
ResultDto resultDto = new ResultDto();
Thread thread = new Thread(this.extractDataDao);
thread.start();
resultDto.setData("Process has started");
return Response.ok(gson.toJson(resultDto)).build();
}
public void setExtractDataDao(ExtractDataDao extractDataDao) {
this.extractDataDao = extractDataDao;
}
}
ExtractDataDao.java:
public class ExtractDataDao implements Runnable {
private CompleteDatabaseModel completeDatabaseModel;
#Override
public void run() {
// Very simplifed class
int numThreads = 5;
ExecutorService executor = Executors.newFixedThreadPool(numThreads);
for (int j = 0; j < numThreads; j++) {
executor.execute(this.completeDatabaseModel);
}
}
public void setCompleteDatabaseModel(CompleteDatabaseModel completeDatabaseModel) {
this.completeDatabaseModel = completeDatabaseModel;
}
}
CompleteDatabaseModel.java
public class CompleteDatabaseModel implements Runnable {
private EntityManagerFactory entityManagerFactory;
private LogDao logDao;
#Override
public void run() {
// Very simplified class
EntityManager entityManager = null;
try {
entityManager = this.entityManagerFactory.createEntityManager();
...
this.logDao.insertLog("Test message", CATEGORY);
...
this.getCountry(entityManager, "country")
} finally {
entityManager.close();
}
}
private synchronized Country getCountry(final EntityManager entityManager, String strCountry) {
Country country = Country.getCountryByCountry(entityManager, strCountry);
if (country == null) {
country = ImdbToMovieDatabase.convert(strCountry, Country.class);
entityManager.getTransaction().begin();
entityManager.persist(country);
entityManager.getTransaction().commit();
country = Country.getCountryByCountry(entityManager, strCountry);
}
return country;
}
public void setLogDao(final LogDao logDao) {
this.logDao = logDao;
}
}
And the classes that provoke deadlock:
LogDao.java:
public class LogDao {
private EntityManagerFactory entityManagerFactory;
public void insertLog(final String message, final Category.CategoryName categoryName) {
Log log = new Log();
EntityManager entityManager = this.entityManagerFactory.createEntityManager();
try {
entityManager.getTransaction().begin();
Category category = Category.getCategoryByName(entityManager, categoryName.name());
log.setCategory(category);
log.setLog(message);
entityManager.persist(log); // // Cause of deadlock in Thread-1 (for example)
entityManager.getTransaction().commit();
} catch (Exception e) {
logger.error("Error persisting log [" + message + "]", e);
entityManager.getTransaction().rollback();
} finally {
if (entityManager != null) {
entityManager.close();
}
}
}
public void setEntityManagerFactory(final EntityManagerFactory entityManagerFactory) {
this.entityManagerFactory = entityManagerFactory;
}
}
Entity.java:
public static Country getCountryByCountry(final EntityManager entityManager, final String strCountry) {
Country country = null;
try {
TypedQuery<Country> typedQuery =
entityManager.createQuery(
"SELECT c FROM Country c WHERE country = ?",
Country.class);
typedQuery.setParameter(1, strCountry);
country = typedQuery.getSingleResult(); // Cause of deadlock in Thread-2 (for example)
} catch (NoResultException e) {
System.out.println("No data found for " + strCountry);
} catch (Exception e) {
e.printStackTrace();
}
return country;
}
Maybe private synchronized Country getCountry is provoking the deadlock? I don't think I should, since logDao has injected its own EntityManagerFactory
Can I use a connection pool?
Thanks in advance.
I have written the below code in Spring for handling custom exceptions. My Exception handler is executing But it returns a view as shown below instead of a String. May I know what is wrong in my code. Thanks in advance.
Code:
#Controller
public class RestController {
#ExceptionHandler(SpringException.class)
public String handleCustomException(SpringException ex) {
String jsonInString = "{}";
JSONObject json = new JSONObject();
Map<String,String> errorMap = new HashMap<String,String>();
errorMap.put("errorMessage",ex.getMessage());
System.out.println("Inside exception handler");
json.putAll(errorMap);
jsonInString = json.toJSONString();
logger.info(jsonInString);
return jsonInString;
}
#RequestMapping(value = "/v1/dist_list/{emailId}/members", method = RequestMethod.GET)
public #ResponseBody String getDistributionListMember(#PathVariable String emailId) throws Exception, SpringException {
String retStatus = null;
retStatus = dataServices.getDistributionListMember(emailId, callerId);
if (!retStatus.isEmpty()) {
if (retStatus.contains("callerid is not valid")) {
throw new SpringException("Error", retStatus);
}
}
}
SpringException class
package com.uniteid.model;
import org.springframework.http.HttpStatus;
public class SpringException extends RuntimeException {
private static final long serialVersionUID = 1L;
private String errCode;
private String errMsg;
public String getErrCode() {
return errCode;
}
public void setErrCode(String errCode) {
this.errCode = errCode;
}
public String getErrMsg() {
return errMsg;
}
public void setErrMsg(String errMsg) {
this.errMsg = errMsg;
}
public SpringException(String errCode, String errMsg) {
this.errCode = errCode;
this.errMsg = errMsg;
}
}
Below is my Spring-config.xml file
<?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:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<context:component-scan base-package="com.uniteid.controller" />
<mvc:annotation-driven
content-negotiation-manager="contentNegociationManager" />
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:uniteidrest.properties" />
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url">
<value>${eidms.url}</value>
</property>
<property name="username">
<value>${eidms.username}</value>
</property>
<property name="password">
<value>${eidms.password}</value>
</property>
</bean>
<!-- <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"
/> <property name="url" value="jdbc:oracle:thin:#un.org:1521:EIDMSUAT"
/> <property name="username" value="EIDMSUAT" /> <property name="password"
value="NewPass" /> </bean> -->
<bean id="contentNegociationManager"
class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="defaultContentType" value="application/json" />
<property name="ignoreAcceptHeader" value="true" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.uniteid.model.User</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.connection.pool_size">10</prop>
</props>
</property>
</bean>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<bean class = "org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name = "exceptionMappings">
<props>
<prop key = "com.uniteid.model.SpringException">
ExceptionPage
</prop>
</props>
</property>
<property name = "defaultErrorView" value = "error"/>
</bean>
<bean id="txManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="persistenceExceptionTranslationPostProcessor"
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<bean id="dataDao" class="com.uniteid.dao.DataDaoImpl"></bean>
<bean id="dataServices" class="com.uniteid.services.DataServicesImpl"></bean>
</beans>
here is my 'GenericQuartzJob' class
public class GenericQuartzJob extends QuartzJobBean
{
private String batchProcessorName;
public String getBatchProcessorName() {
return batchProcessorName;
}
public void setBatchProcessorName(String name) {
// System.out.println("jo"+name);
this.batchProcessorName = name;
}
protected void executeInternal(JobExecutionContext jobCtx) throws JobExecutionException
{
try {
// System.out.println("jo");
SchedulerContext schedCtx = jobCtx.getScheduler().getContext();
ApplicationContext appCtx =
(ApplicationContext) schedCtx.get("applicationContext");
java.lang.Runnable proc = (java.lang.Runnable) appCtx.getBean(batchProcessorName);
proc.run();
}
catch (Exception ex) {
// ex.printStackTrace();
throw new JobExecutionException("Unable to execute batch job: " + batchProcessorName, ex);
}
}
}
Here is my MyRunnableJob Class
#Configuration
#ComponentScan("com.ehydromet.service")
public class MyRunnableJob implements Runnable {
//#Resource private SpringService myService;
#Autowired
public UserService service;
#Override
public void run() {
// System.out.println("hu");
try{
service.getAllAdminUser();
}catch(Exception ex){
System.out.println(ex.getMessage()+" MyRunnableJob");
}MqttImplement mqtt=new MqttImplement();
mqtt.publishMessage();
//Run the Job. This code will run in the Spring context so you can use injected dependencies here.
}
}
Below is my MqttImplement class
public class MqttImplement implements MqttCallback {
#Autowired
private static UserService service;
#RequestMapping("/publish")
public void publishData(ModelMap map){
MyTask.map=map;
pubTopic="tmsdata";
susTopic="tmsack";
if(initializeMqTTParameters() ){
if(suscribeForAck()){
// new ClassPathXmlApplicationContext("spring-quartz.xml");
AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
}
}
// initializeMqTTParameters();
// suscribeForAck();
// publishMessage();
}
public void publishMessage(){
try{
// System.out.print("sending ");
Received received=service.getReceivedDataToPublishTMS();
if(received!=null){
System.out.print("sending you not null");
String publisgMSG=createMessageToPublish(received);
pubMessage="lava," ;
publishMessageTms();
}else{
System.out.println("null hora");
}
}catch(Exception ex){
System.out.println("hora"+ex.getLocalizedMessage()+" "+ex.toString());
}
}
}
and here is 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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- <bean id="exampleBusinessObject" class="com.ehydromet"/> -->
<!-- Old JobDetail Definition
<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="exampleBusinessObject"/>
<property name="targetMethod" value="doIt"/>
</bean>
-->
<!-- Runnable Job: this will be used to call my actual job. Must implement runnable -->
<bean name="myRunnableJob" class="com.ehydromet.controller.MyRunnableJob"></bean>
<!-- New Clusterable Definition -->
<bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="com.ehydromet.schedule.GenericQuartzJob" />
<property name="jobDataAsMap">
<map>
<entry key="batchProcessorName" value="myRunnableJob" />
</map>
</property>
</bean>
<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<!-- see the example of method invoking job above -->
<property name="jobDetail" ref="jobDetail"/>
<!-- 10 seconds -->
<property name="startDelay" value="5000"/>
<!-- repeat every 50 seconds -->
<property name="repeatInterval" value="5000"/>
</bean>
<context:component-scan base-package="com.ehydromet.service"/>
<context:component-scan base-package="com.ehydromet.dao"/>
<context:component-scan base-package="com.ehydromet.service.impl"/>
<context:component-scan base-package="com.ehydromet.dao.impl"/>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.ehydromet.entity.Alarms</value>
<value>com.ehydromet.entity.UserData</value>
<value>com.ehydromet.entity.ModemInfo</value>
<value>com.ehydromet.entity.Received</value>
<value>com.ehydromet.entity.Modems</value>
<value>com.ehydromet.entity.AdminLogin</value>
<value>com.ehydromet.entity.UserPolicy</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.hbm2ddl.auto">validate</prop>
</props>
</property>
</bean>
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
<property name="triggers">
<list>
<ref bean="simpleTrigger" />
</list>
</property>
<!-- Add this to make the Spring Context Available -->
<property name="applicationContextSchedulerContextKey"><value>applicationContext</value></property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/ejava" />
<property name="username" value="root" />
<property name="password" value="" />
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="hibernateInterceptor" class="org.springframework.orm.hibernate3.HibernateInterceptor">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
</beans>
Dao classes are #Transactional and #Repository.
in MqttImplement class service object is null i think autowired is not working with Quartz scheduler. Any suggestion????
i think autowired is kind of resolved. but
error is-- org.springframework.beans.NotWritablePropertyException: Invalid property 'sessionFactory' of bean class [org.springframework.scheduling.quartz.SchedulerFactoryBean]: Bean property 'sessionFactory' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
i am new to it. so may be some foolish mistakes i have done, please have a look.
Have you tried #Autowired without static? Seems weird for me...
From other side you do this:
MqttImplement mqttPublishTms=new MqttImplement();
................
mqttPublishTms.publishMessage();
So, it's new not Dependency Injection. There is no surprise that the service property there is null.
I am new to Spring batch and I am trying to use Spring Batch with restartable feature. I am using MapJobRepositoryFactoryBean as Job repository. Everything looks fine. But when I run the same job multiple times I could see the execution time increasing considerably. I guess some memory leak is happening.If no job is running, I am cleaning the repository as well. But no luck. How do I know whats happening exactly. After running the same job for 4-5 times, the execution time is going to 2-3 times of the first execution.
<jpa:repositories base-package=".reference.data.repository"/>
<context:annotation-config />
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
<property name="url"
value="jdbc:sqlserver://${reference-data-manager.database.hostname}:
${reference-data-manager.database.port};
database=${reference-data-manager.database.name};
user=${reference-data-manager.database.username};
password=${reference-data-manager.database.password}" />
</bean>
<bean id="simpleJobConfiguration" class="reference.job.SimpleJobConfiguration">
</bean>
<bean id="emf"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf" />
</bean>
<bean id="importJob" class="org.springframework.batch.core.job.SimpleJob" scope="prototype">
<property name="jobRepository" ref="jobRepository"></property>
</bean>
<batch:step id="importCodesStep">
<batch:tasklet allow-start-if-complete="true">
<batch:chunk reader="codeMappingReader" writer="codeMappingWriter"
processor="codeMappingProcessor" commit-interval="${reference-data-manager.batch.size}"
skip-policy="reasonRemarkAssnSkipPolicy" skip-limit="${reference-data-manager.skip.limit}">
<batch:skippable-exception-classes>
<batch:include class="org.springframework.batch.item.ParseException"/>
</batch:skippable-exception-classes>
</batch:chunk>
</batch:tasklet>
<batch:listeners>
<batch:listener ref="reasonRemarkAssnStepListener"/>
<batch:listener ref="reasonRemarkAssnSkipListener"/>
</batch:listeners>
</batch:step>
<bean id="reasonRemarkAssnStepListener" class="reference.listeners.ReasonRemarkAssnStepListener">
</bean>
<bean id="reasonRemarkAssnSkipListener" class="reference.listeners.ReasonRemarkAssnSkipListener">
</bean>
<bean id="reasonRemarkAssnSkipPolicy" class="reference.listeners.ReasonRemarkAssnSkipPolicy">
<!-- <property name="skipLimit" value="5"/> -->
</bean>
<bean id="codeMappingWriter" class="reference.writer.ReasonRemarkAssnWriter" scope="step">
<property name="entityManagerFactory" ref="emf" />
</bean>
<bean id="codeMappingProcessor" class="reference.processors.ReasonRemarkAssnProcessor" scope="step">
<property name="userId" value="#{jobParameters['USER_ID']}" />
<property name="clientMnemonic" value="#{jobParameters['CLIENT_MENOMONIC']}" />
</bean>
<bean id="codeMappingReader" class="reference.readers.ReasonRemarkAssnReader" scope="step">
<property name="org" value="#{jobParameters['ORG']}"/>
<property name="resource" value="" />
<property name="linesToSkip" value="1" />
<property name="lineMapper">
<bean class="reference.mapper.ReasonRemarkAassnLineMapper">
<property name="lineTokenizer">
<bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<property name="names" value="Reason Code,Remark Code,Category,Category Priority,Ignore Insight Processing,Active,Comment" />
</bean>
</property>
<property name="fieldSetMapper" ref="reasonRemarkAssnMapper"/>
</bean>
</property>
</bean>
<bean id="reasonRemarkAssnMapper" class="reference.mapper.ReasonRemarkAssnMapper">
<property name="codeGroups" value="${reference-data-manager.code.groups}"></property>
</bean>
<bean id="jobRepository"
class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
</bean>
<bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
<bean class="CryptoPropertyPlaceholderConfigurer">
<property name="configUtil" ref="configUtil" />
<property name="location"
value="file:config/reference-data-manager.conf" />
<property name="ignoreResourceNotFound" value="true" />
<property name="ignoreUnresolvablePlaceholders" value="true" />
</bean>
<bean name="configUtil" class="CoreConfigUtil">
<property name="crypto" ref="crypto" />
</bean>
<bean id="referenceDataManager" class="reference.service.impl.ReferenceDataManagerImpl">
<property name="step" ref="importCodesStep"></property>
</bean>
Here is my job invocation...
#RestfulServiceAddress("/reference")
public class ReferenceDataManagerImpl implements ReferenceDataManager {
#Autowired
private JobLauncher jobLauncher;
#Autowired
IDataAccessService dataAccessService;
#Autowired
private IConfigurationServiceFactory configurationServiceFactory;
#Autowired
private SimpleJob job;
#Autowired
private TaskletStep step;
#Autowired
private SimpleJobConfiguration jobConfiguration;
#Autowired
private MapJobRepositoryFactoryBean jobRepository;
#Override
public Response importData(MultipartBody input, String org,
String userId, MessageContext mc) throws ServiceFault {
Response.ResponseBuilder builder = null;
ReasonRemarkAssnResponse responseObj = null;
boolean isSuccess = false;
UserInfo userInfo= dataAccessService.userInfoFindByUserId(userId);
JobParametersBuilder jobParametersBuilder = new JobParametersBuilder();
List<Attachment> attachments = input.getAllAttachments();
DataHandler dataHandler = attachments.get(0).getDataHandler();
byte[] bFile = null;
if(null != dataHandler){
try {
InputStream is = dataHandler.getInputStream();
bFile = new byte[is.available()];
is.read(bFile);
is.close();
} catch (IOException e) {
//TODO
}
}
SimpleJobConfiguration.customStorage.put(org, bFile);
jobParametersBuilder.addLong(ReferenceConstants.JOB_PARAMS_USERID, userInfo.getId());
jobParametersBuilder.addString(ReferenceConstants.JOB_PARAMS_ORG, org);
jobParametersBuilder.addString(ReferenceConstants.JOB_PARAMS_TIME, Calendar.getInstance().getTime().toString());
String response = "{error:Error occured while importing the file}";
job.setName(ReferenceConstants.JOB_PARAMS_JOB_NAME_PREFIX+org.toUpperCase());
job.addStep(step);
job.setRestartable(true);
JobExecution execution = null;
try {
execution = jobLauncher.run(job, jobParametersBuilder.toJobParameters());
isSuccess = true;
} catch (JobExecutionAlreadyRunningException e) {
//TODO
}catch (JobRestartException e) {
//TODO
}catch (JobInstanceAlreadyCompleteException e) {
//TODO
}catch (JobParametersInvalidException e) {
//TODO
}
response = prepareResponse(responseObj);
synchronized (SimpleJobConfiguration.customStorage){
if(null != SimpleJobConfiguration.customStorage.get(org)){
SimpleJobConfiguration.customStorage.remove(org);
}
if(SimpleJobConfiguration.customStorage.isEmpty()){
jobRepository.clear();
}
}
builder = Response.status(Response.Status.OK);
builder.type(MediaType.APPLICATION_JSON);
builder.entity(response);
return builder.build();
}
}
Don't use the MapJobRepositoryFactoryBean unless it's for testing. That's all it's intended for.
You shouldn't be building a new Job instance with every call to the controller. If you have stateful components within a step, declare them as step scoped so that you get a new instance per step execution.
The Map based JobRepository keeps everything in memory. That's the idea. So as you execute more and more jobs, the repository is going to grow...eating up your space in memory.
For launching a job in a controller, give something like this a try:
#RestController
public class JobLaunchingController {
#Autowired
private JobLauncher jobLauncher;
#Autowired
private Job job;
#RequestMapping(value = "/", method = RequestMethod.POST)
#ResponseStatus(HttpStatus.ACCEPTED)
public void launch(#RequestParam("name") String name) throws Exception {
JobParameters jobParameters =
new JobParametersBuilder()
.addString("name", name)
.toJobParameters();
this.jobLauncher.run(job, jobParameters);
}
}
My acitvemq server always print error below :
2014-07-12 16:14:27,820 | ERROR | Could not accept connection :
org.apache.activemq.transport.tcp.ExceededMaximumConnectionsException:
Exceeded the maximum number of allowed client connections.
See the 'maximumConnections' property on the TCP transport configuration URI
in the ActiveMQ configuration file (e.g., activemq.xml)
| org.apache.activemq.broker.TransportConnector
| ActiveMQ Transport Server Thread Handler:
tcp://0.0.0.0:61616?maximumConnections=1000&wireformat.maxFrameSize=104857600
When I restart the server it will be ok. But after a few days the error come out again.
I don't why the connections always increase to 1000.
My server config:
<!-- activeMQ -->
<bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="${jms.brokerURL}"></property>
</bean>
<!-- Spring Caching -->
<bean id="cachingConnectionFactory"
class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="jmsConnectionFactory" />
<property name="sessionCacheSize" value="10" />
</bean>
<!-- Spring JMS Template -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="cachingConnectionFactory" />
<property name="explicitQosEnabled" value="true" />
<property name="priority" value="4" />
</bean>
<bean id="scoreQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="SCORE" />
</bean>
<bean id="scoreMessage" class="com.tt.score.mq.server.ScoreMessage"></bean>
<bean id="scoreListener"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsConnectionFactory"></property>
<property name="destination" ref="scoreQueue"></property>
<property name="messageListener" ref="scoreMessage"></property>
<property name="concurrentConsumers" value="10" />
<property name="maxConcurrentConsumers" value="100" />
<property name="sessionAcknowledgeModeName" value="CLIENT_ACKNOWLEDGE" />
</bean>
My client config xml:
<!-- Spring Caching -->
<bean id="cachingConnectionFactory"
class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="jmsConnectionFactory" />
<property name="sessionCacheSize" value="10" />
</bean>
<!-- Spring JMS Template -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="cachingConnectionFactory" />
<property name="explicitQosEnabled" value="true" />
<property name="priority" value="4" />
</bean>
<bean id="messageProducer" class="com.tt.score.mq.client.MessageProducer">
<property name="jmsTemplate" ref="jmsTemplate" />
<property name="scoreQueue" ref="scoreQueue" />
</bean>
<bean id="scoreQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="SCORE" />
</bean>
Other info:
acitvemq server : 5.8.0
client acitvemq : 5.4.2
spring : 3.0.7
spring-jms : 3.0.7
We use transactionManager so the DefaultMessageListenerContainer's cachelevel will be set to none.
---update add dao config----------------------------------
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName"><value>${jdbc.driverClass}</value></property>
<property name="username"><value>${jdbc.user}</value></property>
<property name="url"><value>${jdbc.jdbcUrl}</value></property>
<property name="password">
<bean class="com.tongbanjie.commons.util.EncryptDBPasswordFactory">
<property name="password" value="${jdbc.password}" />
</bean>
</property>
<property name="maxActive"><value>${jdbc.maxActive}</value></property>
<property name="initialSize"><value>${jdbc.initialSize}</value></property>
<property name="maxWait"><value>60000</value></property>
<property name="maxIdle"><value>${jdbc.maxIdle}</value></property>
<property name="minIdle"><value>5</value></property>
<property name="removeAbandoned"><value>true</value></property>
<property name="removeAbandonedTimeout"><value>180</value></property>
<property name="timeBetweenEvictionRunsMillis"><value>60000</value></property>
<property name="minEvictableIdleTimeMillis"><value>1800000</value></property>
<property name="defaultAutoCommit" value="false" />
<property name="connectionProperties">
<value>bigStringTryClob=true;clientEncoding=UTF-8;defaultRowPrefetch=50;serverEncoding=ISO-8859-1</value>
</property>
</bean>
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
</bean>
<!-- myBatis -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:META-INF/mybatis/score-configuration.xml" />
<property name="mapperLocations" value="classpath*:META-INF/mybatis/mapper/*.xml" />
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="commonSqlSessionDao" abstract="true">
<property name="sqlSessionFactory">
<ref bean="sqlSessionFactory" />
</property>
</bean>
-----post the code that we how to use the template now
the jmsTemplate wrapped in a class
public class MessageProducer {
private JmsTemplate jmsTemplate;
private ActiveMQQueue scoreQueue;
public void sendScoreQueue(Map<String, String> userMap) {
sendMessage(this.scoreQueue, userMap);
}
private void sendMessage(Destination destination, final Map<String, String> map) {
this.jmsTemplate.send(destination, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
MapMessage message = session.createMapMessage();
for (String key : map.keySet()) {
message.setStringProperty(key, (String) map.get(key));
}
return message;
}
});
}
}
And we use a thead to send call the MessageProducer class's sendScoreQueue method.
As follows:
//the code is old and ugly.that is the original position we call the mq.
ThreadUtils.execute(new Thread(new SendMsgThread(dycc, ScoreMQSendType.SEND_TYPE_SCORE)));
///
public class ThreadUtils {
protected static ThreadPoolExecutor executor = null;
public static Properties Props = null;
public static void execute(Thread thread) {
executor.execute(thread);
}
static {
if (executor == null)
Integer corePoolSize = 5;
Integer maximumPoolSize = 10;
Integer keepAliveTime = 3000;
executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.MINUTES,
new LinkedBlockingQueue());
}
}
public class SendMsgThread implements Runnable {
private Log log = LogFactory.getLog(SendMsgThread.class);
private Map<String, String> map;
private String type;
private static MessageProducer producer = null;
public SendMsgThread(Map<String, String> map, String type){
this.type = type;
this.map = map;
}
public void run() {
try {
if(type.equals(ScoreMQSendType.SEND_TYPE_SCORE) || type.equals(ScoreMQSendType.SEND_TYPE_REGISTER)) {
producer.sendMessage(map);
}
} catch (Exception e) {
this.log.error("sendMsgThread sendScoreQueue error.", e);
}
}
static {
if (producer == null) producer =
(MessageProducer )SpringContextHolder.getBean(MessageProducer .class);
}
}
For this scenario you should use PooledConnectionFactory instead of cachingConnectionFactory.
More information can be found here.The difference between them can be found here
I had the same problem recurring with same error, and the solution was obtained as a result of trial and error, use jms call to concurrent consumers max to 101, instead of 100, and see if results repeat, adding more to the value results the code executed further on debugger, you will reach a value when code works , Also the solution appears to be using a connection pool factory.
Try this, hope it works, rest my implementation is same as yours in bean file