I am trying to get a simple Spring Integration test working to retrieve messages from a JMS queue hosted by HornetQ on JBoss EAP (version 6.4.0.GA running on Windows 7 Pro) running in standalone mode (standalone.bat -c standalone-full.xml).
The JMS test ran fine when using a simple Java JMS program; now, I'm trying to add Spring Integration and I get the following error:
18:29:03,197 ERROR [org.springframework.jms.listener.DefaultMessageListenerContainer]
(org.springframework.jms.listener.DefaultMessageListenerContainer#0-1)
Could not refresh JMS Connection for destination 'anotherQueue' -
retrying in 5000 ms. Cause: AOP configuration seems to be invalid:
tried calling method [public abstract javax.jms.Connection javax.jms.ConnectionFactory.createConnection()
throws javax.jms.JMSException] on target [HornetQQueue[anotherQueue]];
nested exception is java.lang.IllegalArgumentException: java.lang.ClassCastException#511504f4
The Spring config files are:
applicationContext-ordering-inbound-jms-spring-integration.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:aop=...
<bean id="jndiTemplateBilling" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">org.jboss.as.naming.InitialContextFactory</prop>
<prop key="java.naming.provider.url">remote://localhost:4447</prop>
</props>
</property>
</bean>
<bean id="jndiObjectFactoryBeanBilling" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate" ref="jndiTemplateBilling" />
<property name="jndiName" value="java:jboss/exported/jms/queue/anotherQueue" />
<property name="lookupOnStartup" value="false" />
<property name="proxyInterfaces">
<list>
<value>javax.jms.QueueConnectionFactory</value>
<value>javax.jms.TopicConnectionFactory</value>
<value>java.io.Externalizable</value>
</list>
</property>
</bean>
<bean id="jndiDestinationResolver"
class="org.springframework.jms.support.destination.JndiDestinationResolver">
<property name="jndiTemplate" ref="jndiTemplateBilling" />
<property name="cache" value="true" />
</bean>
<int-jms:inbound-gateway
request-destination-name="anotherQueue"
request-channel="inboundOrderingBillingJms"
destination-resolver="jndiDestinationResolver"
connection-factory="jndiObjectFactoryBeanBilling" />
<int:channel id="inboundOrderingBillingJms" /> <!-- handled by OrderingBillingInboundEndpoint -->
<context:component-scan base-package="com.att.ordering.endpoints.jms" />
<context:annotation-config />
<context:spring-configured />
<int:annotation-config />
</beans>
and applicationContext-ordering-inbound-jms.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans ...">
<context:annotation-config />
<context:spring-configured />
<int:annotation-config />
<context:component-scan base-package="com.att.ordering.endpoints.jms"/>
</beans>
The ServiceActivator class:
package com.att.ordering.endpoints.jms;
import javax.xml.bind.JAXBElement;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component
public class OrderingBillingInboundEndpoint
{
#ServiceActivator(inputChannel = "inboundOrderingBillingJms")
//public void handleMessage(JAXBElement<String> accountNumber)
public void handleMessage(String accountNumber)
{
System.out.println("In OrderingBillingInboundEndpoint.handleMessage - accountNumber=" + accountNumber);
}
}
I bootstrap spring with a WAR; WEB-INF/web.xml is:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>parentContextKey</param-name>
<param-value>ordering-spring-bootstrap.war.context</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</context-param>
</web-app>
WEB-INF/classes/beanRefContext.xml is:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="ordering-spring-bootstrap.war.context"
class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg>
<list>
<value>/applicationContext-ordering-inbound-jms-spring-integration.xml</value>
<value>/applicationContext-ordering-inbound-jms.xml</value>
</list>
</constructor-arg>
</bean>
</beans>
FOLLOWING ADDED AFTER ARTEM'S INITIAL REPLY
My JNDI name is java:jboss/exported/jms/queue/anotherQueue. It is bound to HornetQQueue[anotherQueue].
Following shows it in JBoss - note: there are 2 JNDI entries; I'm using the second one:
This is correct - I was able to get a Java JMS program (without Spring Integration) working as follows:
final Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
env.put(Context.PROVIDER_URL, "remote://localhost:4447");
env.put(Context.SECURITY_PRINCIPAL, "appuser");
env.put(Context.SECURITY_CREDENTIALS, "appuser1!");
context = new InitialContext(env);
// JNDI name in JBoss is: java:jboss/exported/jms/queue/anotherQueue
connectionFactory = (ConnectionFactory) context.lookup("jms/RemoteConnectionFactory");
destination = (Destination) context.lookup("jms/queue/anotherQueue");
connection = connectionFactory.createConnection("appuser", "appuser1!");
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
consumer = session.createConsumer(destination);
consumer.setMessageListener(new MyListener());
connection.start();
I am now trying to get the same simple example working using Spring Integration.
Questions:
(A) Where should I put the user id and password?
(B) Is the following correct? If not, what should it exactly be?
<bean id="jndiTemplateBilling" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">org.jboss.as.naming.InitialContextFactory</prop>
<prop key="java.naming.provider.url">remote://localhost:4447</prop>
</props>
</property>
</bean>
(C) How should I change the following? I removed the proxyInterfaces; what else should change? I don't know how to use jee:jndi-lookup
<bean id="jndiObjectFactoryBeanBilling" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate" ref="jndiTemplateBilling" />
<property name="jndiName" value="java:jboss/exported/jms/queue/anotherQueue" />
<property name="lookupOnStartup" value="false" />
</bean>
(D) Does the following stay the same?
<bean id="jndiDestinationResolver"
class="org.springframework.jms.support.destination.JndiDestinationResolver">
<property name="jndiTemplate" ref="jndiTemplateBilling" />
<property name="cache" value="true" />
</bean>
(E) Does the following change?
<int-jms:inbound-gateway
request-destination-name="anotherQueue"
request-channel="inboundOrderingBillingJms"
destination-resolver="jndiDestinationResolver"
connection-factory="jndiObjectFactoryBeanBilling" />
Looks like you are wrong with your jndiObjectFactoryBeanBilling bean definition. It is for
<property name="jndiName" value="java:jboss/exported/jms/queue/anotherQueue" />
what is confirmed by the logs:
on target [HornetQQueue[anotherQueue]];
But it really must be for the javax.jms.ConnectionFactory:
connection-factory="jndiObjectFactoryBeanBilling"
So, just try to change the JNDI name to the correct one.
From other side I have never used all those proxyInterfaces options for JBOSS JNDI resources. They work well as is, e.g.:
<jee:jndi-lookup id="jndiMqConnectionFactory" jndi-name="${mqConnectionFactory}"/>
<jee:jndi-lookup id="auditQueue" jndi-name="queue/AuditQueue"/>
Related
like in topic, but if I will do just persistence.xml file in META-INF with unitName, and do that by this, then everything is good, and my sql query is working, and connection is open.
Here is my view of my project:
project structure
Here is code where I invoke method, my HomeController.java:
#Controller
#RequestMapping("/")
#SessionAttributes("/")
public class HomeController {
#Autowired
private UserDao userDao;
#Autowired
private EmployeeDAO employeeDao;
#RequestMapping(value = {"/dam"}, method = RequestMethod.GET)
public String setupForm(Model model)
{
userDao.getUserByUserId("2");
//employeeDao.getAllEmployees();
return "listEmployeeView";
}
}
Here is UserDao.java:
#Repository
#Transactional
public class UserDao {
#PersistenceContext
private EntityManager entityManager;
public UserModel getUserByUserId(String userId) {
UserModel user = null;
//EntityManagerFactory emf = Persistence.createEntityManagerFactory("movie-unit");
//entityManager = emf.createEntityManager();
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<UserModel> cq = cb.createQuery(UserModel.class);
Root<User> userRoot = cq.from(User.class);
cq.multiselect(
userRoot.get("firstName"),
userRoot.get("middleName"),
userRoot.get("lastName"),
userRoot.get("email"),
userRoot.get("userId"),
userRoot.get("password")
);
cq.where(cb.equal(userRoot.get("userId"), userId));
TypedQuery<UserModel> q = entityManager.createQuery(cq);
user = q.getSingleResult();
System.out.print(user.getUserId()+"&"+user.getPassword());
return user;
}
}
here is web.xml:
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Spring Hibernate JPA Hello World Application</display-name>
<!-- Configuration file for the root application context -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring-servlet.xml
</param-value>
</context-param>
<!-- Configuration for the DispatcherServlet -->
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
and here is spring-servlet.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:mvc="http://www.springframework.org/schema/mvc"
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
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
<!-- It register the beans in context and scan the annotations inside beans and activate them -->
<context:component-scan base-package="com.howtodoinjava.demo" />
<!-- This allow for dispatching requests to Controllers by registering
two beans - DefaultAnnotationHandlerMapping and AnnotationMethodHandlerAdapter -->
<mvc:annotation-driven />
<!-- This helps in mapping the logical view names to directly view files under a certain pre-configured directory -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- This resolves messages from resource bundles for different locales -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="messages" />
</bean>
<!-- To validate the posted add employee form -->
<bean id="employeeValidator" class="com.howtodoinjava.demo.validator.EmployeeValidator" />
<!-- This produces a container-managed EntityManagerFactory;
rather than application-managed EntityManagerFactory as in case of LocalEntityManagerFactoryBean-->
<bean id="entityManagerFactoryBean" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- This makes /META-INF/persistence.xml is no longer necessary -->
<property name="packagesToScan" value="com.howtodoinjava.demo.model" />
<!-- JpaVendorAdapter implementation for Hibernate EntityManager.
Exposes Hibernate's persistence provider and EntityManager extension interface -->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">validate</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
</props>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/baza" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<!-- This transaction manager is appropriate for applications that use a single JPA EntityManagerFactory for transactional data access.
JTA (usually through JtaTransactionManager) is necessary for accessing multiple transactional resources within the same transaction. -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactoryBean" />
</bean>
<!-- responsible for registering the necessary Spring components that power annotation-driven transaction management;
such as when #Transactional methods are invoked -->
<tx:annotation-driven />
</beans>
Like I said, if I do entitymanager and entitymanagerfactory in java code which is commented here in UserDao.java with persistence.xml like this:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="movie-unit">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.connection.url" value="jdbc:mysql://localhost/baza" />
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />
<property name="hibernate.connection.username" value="root" />
<property name="hibernate.archive.autodetection" value="class" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hbm2ddl.auto" value="update" />
</properties>
</persistence-unit>
then everythings works fine.
In mysql server I have privileges like this:
Any % -- USAGE
Any localhost no password USAGE
root 127.0.0.1 no password ALL PRIVILEGES
root ::1 no password ALL PRIVILEGES
root localhost with password ALL PRIVILEGES
Where is problem?
I have developed a JAX-WS based web-service. I have Web service layer, service layer and a Dao layer. When i call a service method from web service class it gives null pointer exception. The reason is the service class bean is not getting injected.
web-service class:
package com.test.webservice.controller;
import javax.jws.WebMethod;
import javax.jws.WebService;
import com.test.salary.service.SalaryService;
#WebService
public class EmployeeSalaryWebService {
private SalaryService salaryService;
/**
* #param salaryService the salaryService to set
*/
#WebMethod(exclude = true)
public void setSalaryService(SalaryService salaryService) {
this.salaryService = salaryService;
}
#WebMethod
public double getEmployeeSalary(String name){
System.out.println("==== Inside getEmployee Salary === "+salaryService );
return salaryService.calculateSalary(name);
}
}
Application-context
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean name="salaryWebService"
class="com.test.webservice.controller.EmployeeSalaryWebService">
<property name="salaryService" ref="salaryService" />
</bean>
<bean name="salaryService" class="com.test.salary.service.SalaryServiceImpl">
<property name="salaryDAO" ref="salaryDAO" />
</bean>
<bean name="salaryDAO" class="com.test.salary.dao.SalaryDaoImpl">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:hibernate.cfg.xml" />
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:#localhost:1521:xe" />
<property name="username" value="LOCAL" />
<property name="password" value="abcdef" />
</bean>
</beans>
web.xml:
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>Archetype Created Web Application</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/salaryConfiguration.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
Please let me know why the SalaryService salaryService not getting injected.
Your service class and bean in context is two separate things. I believe that you don't get bean from context and just use class, aren't you?
I advice you marking your service class with
#Component
That will make your class to become spring bean.
Then you can use inside following annotation.
#Autowired
This will try to find appropriate bean with annotated element type in spring context.
And don't forget to put into your context.
<context:component-scan base-package="..." />
This will search all classes marked as #Component and add it to spring context as beans.
For more detailed instruction you can check this article
https://www.javacodegeeks.com/2010/11/jaxws-with-spring-and-maven-tutorial.html
Make your SalaryService auto wired as follows:
public class EmployeeSalaryWebService {
#Autowired
private SalaryService salaryService;
....
I have been working with the Spring framework for a few days trying to set up a project, based off of something like this tutorial.
Unfortunately, when i deploy the project using Tomcat, I get a screen that looks something like this:
I'm not really sure to go from here. I've checked the web.xml and any other relevant .xml files that would maybe affect the error, but I can't see an error. Below I will post my web.xml and spring-config.xml files.
web.xml
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>Campaign Spring V2</display-name>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
spring_config.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: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.bridge.campaignspring.controller" />
<context:property-placeholder location="classpath:application.properties" />
<!-- Enables the Spring MVC #Controller programming model -->
<mvc:annotation-driven />
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${database.driver}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.user}" />
<property name="password" value="${database.password}" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.bridge.campaignspring.Campaign</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</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 class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="CampaignDao" class="com.bridge.campaignspring.dao.CampaignDAOImpl" />
<bean id="CampaignService" class="com.bridge.campaignspring.service.CampaignServiceImpl" />
</beans>
If need be, I can post the project to GitHub to see if there is an even larger flaw that could be found in the code. Also, if any other parts of the project need to be posted I will update the OP to display anything. Thanks!
EDIT: http://localhost/ does not load either, I was incorrect with my previous statement.
EDIT2: Here is a link to the project on GitHub.
EDIT3: After going through the Spring tutorial again this was resolved!
You didn't follow the tutorial well. The controller mapping starts with
#RequestMapping("/")
public class AppController {
The first annotation #RequestMapping("/") is important for spring to calculate the path used by the request.
And this code is missing
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "com.bridge.compaignspring.model" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
Without it Spring cannot autowire properties that depend on sessionFactory.
Just done a quick check through the github project, you have more problems that I thought.
You are using XML config to create the DispatchServer with the config at Spring-config.xml, while also having a AppInitializer on the class path.
The AppInitializer uses AppConfig which creates a Datasource bean, your XML also creates a Datasource bean and also a SessionFactory.
Tomcat will find the AppInitializer and is running through that first.
This means it tries to autowire the SessionFactory before the one in the XML have been created.
To move your code off this problem do the following things.
move spring_config.xml from /webapp/WEB-INF to /resources
add the following #import line to AppConfig.java
#Configuration
#EnableWebMvc
#ImportResource("classpath:spring-config.xml")
#ComponentScan(basePackages = "com.bridge.campaignspring")
public class AppConfig {
Now you need to remove 1 of the 2 DataSource beans you are creating. I would suggest removing the one in the XML as that is using invalid property values. i.e. ${database.driver} does not exist.
After you have made those changes, you will still have other problems, but you are further along than you were.
did u set Web Module Path in tomcat settings ?
refer these question Unable to run Spring REST application using Tomcat
Well, very likely there isn't any mystery but I am just not smart enough to figure out what my problem is. However usually it is the mystery after all!
Sorry for the introduction, my problem is that the prototype scope doesn't seem to work for me. I have created a REST service with a Spring Integration flow (there is a http inbound gateway in the front of the flow). The scopes of most of the beans are prototype. I tested the flow by calling it ten times with threads. Also I logged the bean references (just print the 'this' in the object being called) and I saw the same reference ten times!
e.g. org.protneut.server.common.utils.XmlToMapConverter#755d7bc2
To my knowledge it means that no new instance is being created for the XmlToMapConverter but using the same instance ten times. Am I right?
Very likely I configured the Spring incorrectly but I just cannot find out what I missed.
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.4"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/SpringIntegration-servlet.xml</param-value>
</context-param>
<servlet>
<servlet-name>SpringIntegration</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringIntegration</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
SpringIntegration-servlet.xml
<beans ...>
<mvc:annotation-driven/>
<context:component-scan base-package="org.protneut.server.controller, org.protneut.server.common.persistence.service" />
<jpa:repositories base-package="org.protneut.server.common.persistence.repository"/>
<!-- ********************* importing the mysql config ********************* -->
<import resource="/mysql-config-context.xml"/>
<!-- ********************* importing the message flow ********************* -->
<import resource="classpath:META-INF/spring/integration/processing_req_wokflow.xml"/>
<tx:annotation-driven />
<!-- ************************************************************************* -->
<!-- ******************************** for JPA ******************************** -->
<!-- ************************************************************************* -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="org.protneut.server.common.persistence.model" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect"/>
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<!-- ********************* the used property files ********************* -->
<context:property-placeholder location="classpath:protneut-server-config.properties"/>
<!--
****************************************************************************************
********************** Beans used in the Spring Integration flow **********************
****************************************************************************************
-->
<!-- it has to be prototype, it cannot be request as it is in an async call so it is not in the request! -->
<bean id="logManager" class="org.protneut.server.log.LogManager" scope="prototype"></bean>
<bean id="convertRestToWorkflowBean" class="org.protneut.server.rest.ConvertRestMessageToWorkflowBean" scope="prototype"/>
<bean id="xmlToMapConverter" class="org.protneut.server.common.utils.XmlToMapConverter" scope="prototype"/>
<bean id="serviceStorageManager" class="org.protneut.server.cache.ServiceStorageManager" scope="singleton">
<property name="cacheBeanDAO" ref="cacheBeanDAO"/>
</bean>
<bean id="serviceCall" class="org.protneut.server.call.ServiceCall" scope="prototype">
<property name="httpClient" ref="httpClient"/>
</bean>
<bean id="xmlResponseExtractor" class="org.protneut.server.extract.XmlResponseExtractor" scope="prototype">
<property name="xmlToMapConverter" ref="xmlToMapConverter"/>
</bean>
...
</beans>
flow configuration
<?xml version="1.0" encoding="UTF-8"?>
<beans ..>
<task:executor id="async_executor" pool-size="50" />
<!-- ***************************************************************************************************** -->
<!-- ************************************* WORKFLOW STARTING ********************************************* -->
<!-- ***************************************************************************************************** -->
<int-http:inbound-gateway id="receivingRest-inboundGateway"
supported-methods="POST" path="/service/get"
request-payload-type="java.lang.String" reply-timeout="10000"
request-channel="arrivedRestReq_channel" auto-startup="true"
error-channel="error_channel" reply-channel="restResponse-channel" >
</int-http:inbound-gateway>
<int:channel id="arrivedRestReq_channel" scope="prototype"></int:channel>
<int:json-to-object-transformer type="java.util.Map"
input-channel="arrivedRestReq_channel"
output-channel="fromConvertToActivator-channel"
id="convertJsonToMap_">
</int:json-to-object-transformer>
<int:channel id="fromConvertToActivator-channel"></int:channel>
<int:service-activator
input-channel="fromConvertToActivator-channel"
output-channel="toCallChain-channel"
id="convertRestToWorkflowBean-serviceActivator"
ref="convertRestToWorkflowBean" method="convert">
</int:service-activator>
<int:channel id="toCallChain-channel"></int:channel>
<int:chain input-channel="toCallChain-channel" id="call_chain">
<int:service-activator
id="serviceStorageManager-serviceActivator"
ref="serviceStorageManager" method="getServiceInfo">
</int:service-activator>
<int:service-activator id="serviceRequestCreator-serviceActivator" ref="serviceRequestCreator" method="create"/>
<int:service-activator id="call-serviceActivator"
ref="serviceCall" method="call">
</int:service-activator>
<int:router expression="payload.extractType.name()"
id="responseExtractor-router">
<int:mapping value="XPATH" channel="xmlResponse-channel"/>
<int:mapping value="JSONPATH" channel="jsonResponse-channel"/>
</int:router>
</int:chain>
...
<int:service-activator id="xmlResponseExtractor-serviceActivator"
ref="xmlResponseExtractor" method="extract" input-channel="xmlResponse-channel" output-channel="toRestResponseCreator_chain"></int:service-activator>
</beans>
So I defined the scope of XmlToMapConverter is prototype but still I can't have new object at a new request. The situation is the same for convertRestToWorkflowBean which is the first service call in the flow (service-activator).
Could you please explain to me where the problem is?
Thanks, V.
I don't see xmlToMapConverter usage, but I see this:
<int:service-activator
input-channel="fromConvertToActivator-channel"
output-channel="toCallChain-channel"
id="convertRestToWorkflowBean-serviceActivator"
ref="convertRestToWorkflowBean" method="convert">
where you use this:
<bean id="convertRestToWorkflowBean" class="org.protneut.server.rest.ConvertRestMessageToWorkflowBean" scope="prototype"/>
The issue you are facing is called scope impendance. That's because <int:service-activator> populates several singleton beans, hence the reference to your prototype becomes as singleton, too.
One way to overcome that to use SpEL from there:
<int:service-activator
input-channel="fromConvertToActivator-channel"
output-channel="toCallChain-channel"
id="convertRestToWorkflowBean-serviceActivator"
expression="#convertRestToWorkflowBean.convert(payload)"/>
In this case your convertRestToWorkflowBean is retrieved from the BeanFactory on each call.
Another trick to go ahead looks like:
<bean id="convertRestToWorkflowBean" class="org.protneut.server.rest.ConvertRestMessageToWorkflowBean" scope="prototype">
<aop:scoped-proxy/>
</bean>
In this case your bean will be wrapped to the ScopedProxyFactoryBean and all invocation will be delegated to your prototype on demand.
Prototype scoped beans will be created every time you call ApplicationContext.getBean(...)
You've included the bean definition but haven't shown how other services reference it. My guess is it's injected into a singleton service once during initialization hence there's only one. Perhaps you need to call ApplicationContext.getBean() each time to get a new instance.
There are other solutions involving dynamic proxies that ultimately invoke getBean(), I'm on my mobile at the moment so too hard to find a link for you.
I am attempting to split out the Hibernate DAO and Model Object layer from an existing application so they can be used across multiple applications. Unfortunately, I'm not having much success: a NoSuchBeanDefinitionException is thrown when trying to get the SessionFactory from the Application Context.
All of DAO classes extend a class called GenericDaoHibernate2. Each DAO extends this, and passes a Class in the constructor. Pretty standard Generic DAO stuff.
I figured this would be the logical place to set the session factory as well (there are ALOT of DAO classes). So, in the constructor class, I did this:
public GenericDaoHibernate2(final Class<T> persistentClass) {
ctx = new ClassPathXmlApplicationContext("META-INF/applicationContext-dao.xml");
this.sessionFactory = (SessionFactory) ctx.getBean(SessionFactory.class);
log.debug("Value of app context: " + ctx.toString());
log.debug("Value of sessionFactory: " + sessionFactory);
this.persistentClass = persistentClass;
}
Unfortunately, this blew up with the previously mentioned exception:
Caused By: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [org.hibernate.SessionFactory] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:924)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:793)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:707)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:551)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
Truncated. see log file for complete stacktrace
I've also attempted this with the app context file just in the classpath, setting the value when declaring the variable, etc, etc.
I'm guessing what is happing is that as part of the Maven build, the jar isn't referencing the libraries on the classpath, but I really don't know...
UPDATE: Stupid, stupid me... forgot to show the application context file.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
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-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd"
default-lazy-init="true">
<tx:annotation-driven transaction-manager="transactionManager" />
<context:component-scan base-package="org.jason.dao.hibernate" />
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:#//192.168.1.1/db01" />
<property name="username" value="USER" />
<property name="password" value="PASSWORD" />
</bean>
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibername.format_sql">true</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.jdbc.use_get_generated_keys">true</prop>
<prop key="hibernate.cglib.use_reflection_optimizer">true</prop>
<prop key="hibernate.default_catalog">CATALOG</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
</prop>
</props>
</property>
<property name="packagesToScan">
<list>
<value>org.jason.model</value>
</list>
</property>
</bean>
</beans>
Another update: Was asked for a sample DAO. The interface is a "standard" generic interface, accepting the generic paramters T and PK, just like the Impl. The following one doesn't have any specific methods other than what it inherits from GenericDaoHibernate2.
#Repository("AreaOfPreferenceDAO")
public class HibernateAreaOfPreferenceDAO extends GenericDaoHibernate2<AreaOfPreference, AreaOfPreferenceCompositeId> implements AreaOfPreferenceDAO {
public HibernateAreaOfPreferenceDAO()
{
super(AreaOfPreference.class);
}
}
In order to wire in the SessionFactory into your custom generic DAO, you can go ahead and simply use #Autowire, as long as the overall Spring context is defining the SessionFactory bean.
To define the bean:
<bean id="sessionFactory" class=
"org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="org.rest" />
<property name="hibernateProperties">
...
</property>
</bean>
<bean id="dataSource" class=
"org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${driverClassName}" />
<property name="url" value="${url}" />
<property name="username" value="restUser" />
<property name="password" value="restmy5ql" />
</bean>
And to wire, simply:
#Autowired
SessionFactory sessionFactory;
The right place to bootstrap the context is not in the constructor of your DAO; if you're working with a web application, you can go with the traditional approach:
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/dispatcher-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Since this is not a web application, then the context cannot be bootstrapped in web.xml; however, the bootstrapping still needs to be external - a main class would simply need to create the XmlWebApplicationContext and configure it.
Hope this helps.
The fact that you are creating a new application context in each DAO object may be getting you into trouble.
ctx = new ClassPathXmlApplicationContext("META-INF/applicationContext-dao.xml");
This is kind of circular if you think about it. You call the context, which does a component scan for DAO's, then the DAO instantiates a new context, which does a component scan for DAO's ...
I would just autowire the sessionfactory directly as someone else had mentioned.
#Repository("AreaOfPreferenceDAO")
public class HibernateAreaOfPreferenceDAO extends GenericDaoHibernate2<AreaOfPreference, AreaOfPreferenceCompositeId> implements AreaOfPreferenceDAO {
#Autowired
public HibernateAreaOfPreferenceDAO(SessionFactory sessionFactory)
{
super(sessionFactory, AreaOfPreference.class);
}
}
No component should need to construct a new application context.
Had the same problem, unable to make injection work.
My problem was "sequence". Hibernate xml must be invoked first.
dispatcher-servlet.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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
<!-- init hibernate first -->
<import resource="classpath:HibernateContext.xml"/>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/" />
<property name="suffix" value=".jsp" />
</bean>
<mvc:annotation-driven />
<context:component-scan base-package="com.xxx.yyy" />
content of hibernateContext.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:database.properties</value>
</list>
</property>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.xxx.yyy.model" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- bean id="transactionManager" class=" org.springframework.transaction.jta.JtaTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean-->