Autowiring in Spring 3 MDP - spring

Firstly I've checked some of the possible answers that come up when posting a new question and none that I have come across deals with my issue.
I have a Spring MDP which works nicely i.e. can receive messages. The problem is when I try to autowire a dependency, the autowiring doesn't seem to work. I'm using Netbeans and Glassfish 3.1.2 so I'm able to step through the code and can confirm that the dependencies are null. Autowiring in other parts of the application are working fine. The MDP is picked up in the component-scan.
I used the example from springsource to create my MDP:
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/jms.html
And I've autowired the dependencies by setter methods.
I cannot figure out why this won't work. I've checked around and I don't think anyone else has had this issue.
Any ideas, pointers in the right direction, examples I can reference will be much appreciated.
Thanks.
KSS
MDP Class:
public class ExampleListener implements MessageListener {
private Transformer transformer;
private MurexService murexService;
#Autowired
public void setTransformer(Transformer transformer) {
this.transformer = transformer;
}
#Autowired
public void setMurexService(MurexService murexService) {
this.murexService = murexService;
}
#Override
public void onMessage(Message message) {
if (message instanceof TextMessage) {
try {
System.out.println(((TextMessage) message).getText());
} catch (JMSException ex) {
throw new RuntimeException(ex);
}
}
}
}
ApplicationContext:
<jee:jndi-lookup id="connectionFactory" jndi-name="jms/QueueConnectionFactory" />
<jee:jndi-lookup id="testQueueOne" jndi-name="jms/ITFS_RECEIVE" />
<!-- this is the Message Driven POJO (MDP) -->
<bean id="messageListener" class="com.scm.service.ExampleListener" />
<!-- and this is the message listener container -->
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destination" ref="testQueueOne"/>
<property name="messageListener" ref="messageListener" />
</bean>

An AutowiredAnnotationBeanPostProcessor needs to be registered for wiring in the #Autowired fields. The javadoc has more details. See here for the solution to a similar issue.
Essentially adding this should get the autowiring to work:
<context:annotation-config/>

Related

Stop a spring jms message listener

I have a scenario where i need to stop the spring's DefaultMessageListenerContainer and then later start that again. I have 10 different DefaultMessageListenerContainer listening to 10 different queue.
All 10 different containers are calling the same method of same message listener class.
Now i want to stop the messagelistenercontainer for a particular queue depending on the exception i get in onMessage method.
Please suggest me how i can achieve the above scenario.
Below is my listener configuration
<bean id="msglistenerForAuditError" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsFactory"/>
<property name="sessionTransacted" value="true"/>
<property name="destinationName" value="test.audit.error2"/>
<property name="messageListener" ref="auditerrorListener" />
</bean>
<bean id="msglistenerForAuditEvent" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsFactory"/>
<property name="sessionTransacted" value="true"/>
<property name="destinationName" value="test.audit.event2"/>
<property name="messageListener" ref="auditerrorListener" />
</bean>
The DefaultMessageListenerContainer is a lifecycle bean and as such it exposes a start and a stop method that you can use to start and stop the listener, respectively.
You can build a service on your own that is gathering all known instances in the context and you can then loop over those to stop the containers, something like
#Service
public class MyService {
private final Collection<DefaultMessageListenerContainer> containers;
#Autowired
public MyService(Collection<DefaultMessageListenerContainer> containers) {
this.containers = containers;
}
public void stopAll() {
// iterate over the collection and call "stop()" on each item
}
}
That being said:
You should not invoke this service as part of a message listener as attempting to stop the container while the thread is processing a message will have weird side effect
The whole use case looks suspicious to me. Your message listeners should be resilient and, more importantly, they should be independent of each other; if you are stopping listener A because listener B threw an exception, something is definitely wrong in your design
stop method on DefaultMessageListenerContainer did not worked but shutdown method worked perfectly.
for(DefaultMessageListenerContainer defaultCont:containers){
defaultCont.shutdown();
}
Injecting a collection of DefaultMessageListenerContainer did not work for me, I use Spring Boot 1.4.x, with Spring 4.3.x
Here's how I solved it:
package org.example.queue;
import org.springframework.jms.config.JmsListenerEndpointRegistry;
//import other stuffs
#Component
public class QueueManager {
#Autowired
JmsListenerEndpointRegistry endpointRegistry;
public void shutdown() {
endpointRegistry.getListenerContainers().forEach((container) -> {
if (container.isRunning()) {
log.debug("Shutting down listener: " + container.getClass().getName());
container.stop();
}
});
}
public void start() {
endpointRegistry.getListenerContainers().forEach((container) -> {
if (!container.isRunning()) {
log.debug("Starting listener: " + container.getClass().getName());
container.start();
}
});
}
}

Spring 3 MVC:java.lang.IllegalArgumentException: Property 'dataSource' is required.How to set JdbcTemplate correctly?

I'm new to Spring development.And right now,i'm really facing a problem.Here are the code snippets to make you realize my problem clearly.............
Here is my DAO class:
public class LoginDaoImpl {
private DataSource dataSource;
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public int checkLoginDetails(LoginVo loginVo){
String sql = "select count(*) from empsctygrp where username=? and password=?";
jdbcTemplate = new JdbcTemplate(dataSource);
int count = jdbcTemplate.queryForObject(sql,new Object[]{loginVo.getUserName(),loginVo.getPassword()},Integer.class);
return count;
}
}
Now here is my Business-Object(BO) class:
public class LoginBo {
LoginDaoImpl loginDaoImpl = new LoginDaoImpl();
public int checkLoginDetails(LoginVo loginVo){
return loginDaoImpl.checkLoginDetails(loginVo);
}
}
Now,here is my dispatcher-servlet xml code:
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:#117.194.83.9:1521:XE"/>
<property name="username" value="system"/>
<property name="password" value="password1$"/>
</bean>
<bean id="loginDaoImpl" class="com.abhinabyte.dao.LoginDaoImpl">
<property name="dataSource" ref="dataSource" />
</bean>
Now whenever i'm trying to run this on server the following exception is given:
SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/A] threw exception [Request processing failed; nested exception is java.lang.IllegalArgumentException: Property 'dataSource' is required] with root cause
java.lang.IllegalArgumentException: Property 'dataSource' is required
Please help me solve this problem.............:(
Try this in LoginBo class:
#Autowired
LoginDaoImpl loginDaoImpl;
instead of
LoginDaoImpl loginDaoImpl = new LoginDaoImpl();
The problem is that you manually instantiate LoginDaoImpl.
I was having the same problem and could not find a comprehensive answer on the web, so I decided to post one here for anyone else, or for future me.
I'm still learning so if you think I have made a mistake below, please feel free to edit.
Summary:
Include <integration:annotation-config/> <context:component-scan base-package="myproject"/> in your servlet to pick up annotations
Configure JUnit tests with #RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("file:WEB-INF/FinanceImportTool-servlet.xml")
Don't autowire dataSource or jdbcTemplate if these fields are already provided by a parent class e.g. StoredProcedure
Don't use new() as this initializes classes outside the applicationContext
Beware of using properties in your constructor which have not yet been set - obvious but embarrassingly easy to do
My original class (now altered):
public class MyDAOImpl extends StoredProcedure implements MyDAO {
private static final String SPROC_NAME = "dbo.MySP";
public MyDAOImpl(DataSource dataSource) {
super(dataSource, SPROC_NAME);
// ...declared parameters...
compile();
}
}
MyProject-servlet.xml file (only relevant bits included):
<!-- Used by Spring to pick up annotations -->
<integration:annotation-config/>
<context:component-scan base-package="myproject"/>
<bean id="MyDAOBean" class="myproject.dao.MyDAOImpl" >
<constructor-arg name="dataSource" ref="myDataSource"/>
</bean>
<!-- properties stored in a separate file -->
<bean id="myDataSource" class="com.microsoft.sqlserver.jdbc.SQLServerDataSource">
<property name="databaseName" value="${myDataSource.dbname}" />
<property name="serverName" value="${myDataSource.svrname}" />
<!-- also loaded portNumber, user, password, selectMethod -->
</bean>
Error: property 'dataSource' is required, or NullPointerException (1)
Other answers say make sure you have passed dataSource as a <property> for your bean in the servlet, etc.
I think #Abhinabyte the OP needed to annotate his setDataSource() method with #Annotation, and use <integration:annotation-config/> <context:component-scan base-package="myproject"/> in his servlet to successfully pass in dataSource as a dependency to LoginDaoImpl.
In my case, I tried adding 'dataSource' as a property and autowiring it. The "dataSource is required" error message became a NullPointerException error.
I realised after far too long that MyDAOImpl extends StoredProcedure.
dataSource was already a property of StoredProcedure. By having a dataSource property for MyDAOImpl, the autowiring was not picking up and setting the dataSource property of StoredProcedure, which left dataSource for StoredProcedure as null.
This was not picked up when I tested the value of MyDAOImpl.dataSource, as of course by now I had added a MyDAOImpl.dataSource field that had been autowired successfully. However the compile() method inherited from StoredProcedure used StoredProcedure.dataSource.
Therefore I didn't need public DataSource dataSource; property in MyDAOImpl class. I just needed to use the StoredProcedure constructor with super(dataSource, sql); in the constructor for MyDAOImpl.
I also didn't need a MyDAOImpl.jdbcTemplate property. It was set automatically by using the StoredProcedure(dataSource, sql) constructor.
Error: NullPointerException (2)
I had been using this constructor:
private static final String SPROC_NAME = "dbo.MySP";
public MyDAOImpl(DataSource dataSource) {
super(dataSource, SPROC_NAME);
}
This caused a NullPointerException because SPROC_NAME had not been initialized before it was used in the constructor (yes I know, rookie error). To solve this, I passed in sql as a constructor-arg in the servlet.
Error: [same error message appeared when I had changed file name]
The applicationContext was referring to the bin/ instances of my beans and classes. I had to delete bin/ and rebuild the project.
My new class:
public class MyDAOImpl extends StoredProcedure implements MyDAO {
#Autowired // Necessary to prevent error 'no default constructor found'
public MyDAOImpl(DataSource dataSource, String sql) {
super(dataSource, sql);
// ...declared parameters...
compile();
}
New MyProject-servlet.xml file (only relevant bits included):
<!-- Used by Spring to pick up annotations -->
<integration:annotation-config/>
<context:component-scan base-package="myproject"/>
<bean id="myDAOBean" class="org.gosh.financeimport.dao.MyDAOImpl" >
<constructor-arg name="dataSource" ref="reDataSource"/>
<constructor-arg name="sql" value="dbo.MySP" />
</bean>
<!-- properties stored in a separate file -->
<bean id="myDataSource" class="com.microsoft.sqlserver.jdbc.SQLServerDataSource">
<property name="databaseName" value="${myDataSource.dbname}" />
<property name="serverName" value="${myDataSource.svrname}" />
<!-- also loaded portNumber, user, password, selectMethod -->
</bean>
Helpful places:
If you can get past the rage, this answer on Spring forums might help too
This answer gives a broad introduction to Spring configuration
This answer has simple but useful suggestions
You should annotate that beans that will suffer IoC. Like
#Bean public class LoginDAOImpl { #Inject DataSource dataSource;......}
You set up in spring context this beans, but, you're not using them.
OBS:
When I use the JDBCTemplate I configure de IoC of JDBC like
<bean id="dataSourcePerfil" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${br.com.dao.jdbc.driver}" />
<property name="url" value="${br.com.dao.jdbc.url}" />
<property name="username" value="${br.com.dao.jdbc.user}" />
<property name="password" value="${br.com.dao.jdbc.pass}" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="dataSourcePerfil" />
</bean>
then.... after at all
#Bean
public class LoginDAOImpl {
#Autowired
private JdbcTemplate jdbcTemplate;
#Override
public List<ClienteReport> getClientes() {
return Collections<ClienteReport>. emptyList();
}
}

Injecting EntityManager using Spring ( Null Pointer Exception ) [duplicate]

This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
Closed 7 years ago.
Here's the code insidy my ApplicationContext.xml
<context:spring-configured />
<context:annotation-config />
<context:component-scan base-package="com.apsas.jpa" />
<tx:annotation-driven />
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="testjpa" />
</bean>
<bean id="entityManager"
class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
and here's my Dao Implementation
public class TeacherDaoImpl implements TeacherDao {
#Autowired
private EntityManager entityManager;
#Transactional
public Teacher addTeacher(Teacher teacher) {
entityManager.persist(teacher);
return teacher;
}
}
Here's my Main Class
public class TestApp {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"config/ApplicationContext.xml");
TeacherDao teacherDao = new TeacherDaoImpl();
Teacher teacher1 = teacherDao.addTeacher(new Teacher("First Teacher"));
}
}
Please help, i am getting a null pointer exception
Exception in thread "main" java.lang.NullPointerException
at com.apsas.jpa.dao.impl.TeacherDaoImpl.addTeacher(TeacherDaoImpl.java:22)
at com.apsas.jpa.main.TestApp.main(TestApp.java:26)
ive been solving this problem in 2 days but still i cant find any resources that may solve this problem. i appreciate if you give me your opinion,answers or any idea that might help me solving this,
ps: i am new on learning spring
Since you are instantiating TeacherDaoImpl yourself (with the new keyword) within main, Spring is not injecting the EntityManager and hence the NPE.
Annotate the field TeacherDaoImpl.entityManager with #PersistenceContext and annotate the TeacherDaoImpl class with #Component to have Spring instantiate it for you. Then in your main, get a hold of that bean:
TeacherDao dao = applicationContext.getBean(TeacherDao.class);
// ...
Also these two directives seem to be unnecessary:
<context:annotation-config />
<context:spring-configured />
The former is implied when you are using <context:component-scan />. The latter is only useful if you are using #Configurable in your code.
You will want to use #PersistenceContext for injecting the EntityManager.
See
PersistenceContext EntityManager injection NullPointerException
which is pretty much the same question.

Injection of autowired dependencies failed while using #Transactional

I testing my DAO, but it didn't work. The following error occurs:
Tests in error:
testAccountOperations(com.tsekhan.rssreader.dao.HibernateControllerTest): Error creating bean with name 'com.tsekhan.rssreader.dao.HibernateControllerTest': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.tsekhan.rssreader.dao.HibernateController com.tsekhan.rssreader.dao.HibernateControllerTest.hibernateController; nested exception is java.lang.IllegalArgumentException: Can not set com.tsekhan.rssreader.dao.HibernateController field com.tsekhan.rssreader.dao.HibernateControllerTest.hibernateController to $Proxy25
My DAO:
#Service
#Scope("singleton")
public class HibernateController extends HibernateDaoSupport {
#Autowired
public SessionFactory sessionFactory;
#Transactional
public void addAcount(Account account) {
sessionFactory.getCurrentSession().saveOrUpdate(account);
}
}
My test for this DAO:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath:/applicationContext.xml")
public class HibernateControllerTest {
#Autowired
HibernateController hibernateController;
private Set<Channel> getTestChannelList(String channelLink) {
Channel testChannel = new Channel();
testChannel.setSourceLink(channelLink);
Set<Channel> testChannelList = new HashSet<Channel>();
testChannelList.add(testChannel);
return testChannelList;
}
private Account getTestAccount(String accountLogin, String channelLink) {
Account testAccount = new Account();
testAccount.setAccountLogin(accountLogin);
testAccount.setChannelList(getTestChannelList(channelLink));
return testAccount;
}
#Test
public void testAccountOperations() {
hibernateController
.addAcount(getTestAccount("test_login", "test_link"));
}
}
My applicationContext.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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd"
default-autowire="byName">
<!-- Enabling spring-transaction annotations -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- Enabling annotation-driven configurating -->
<context:annotation-config />
<!-- Creation of transaction manager -->
<bean id="transactionManager" scope="singleton"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="sessionFactory" scope="singleton"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="configLocation" value="classpath:/hibernate.cfg.xml"/>
<property name="configurationClass">
<value>org.hibernate.cfg.AnnotationConfiguration</value>
</property>
</bean>
<!--
A Spring interceptor that takes care of Hibernate session lifecycle.
-->
<bean id="hibernateInterceptor"
class="org.springframework.orm.hibernate3.HibernateInterceptor">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
<bean name="employeeDAO" scope="prototype"
class="com.tsekhan.rssreader.dao.HibernateController" />
<!-- Searching for hibernate POJO files in package com.tsekhan.rssreader.web -->
<context:component-scan base-package="com.tsekhan.rssreader.web" />
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
</beans>
I note, that if you comment #Transactional in DAO, bean is created correctly. What happens?
First of all its realy bad to give name ending in Controller to a DAO its very confusing, Controller and DAO have all together different purpose.
When you add #Transactional to a service or dao class, for spring to make it work in a transaction needs to create a proxy of that class, its a kind of wrapper where in before the execution of proxied class(class in consideration which is proxied) method spring starts the transaction and after the execution in case no exceptions completes the transaction, this can be done in spring via AOP and Annotations. To describe in code.
public class OriginalDaoImpl implements OriginalDao extends DaoSupport {
public void save(Object o){
manager.save(o);
}
}
public class ProxyDaoImpl implements OriginalDao {
private OriginalDao originalDaoImpl; //instance of OriginalDaoImpl
public void save(Object o){
try{
transaction.start();
originalDaoImpl.save(o);
transaction.commit();
}catch(Exception e){
transaction.rollback();
}finally{
//clean up code
}
}
}
As you see this is not an exact implementation but a foundation code, how transaction magically works for you. The key point is there interface OriginalDao which makes this injection easy as OriginalDaoImpl and ProxyDaoImpl both implement same interface. Hence they can be swapped i.e. proxy taking place of original. This dynamic proxy can be created in java by Java dynamic proxy. Now, the question what if your class is not implementing an interface, it gets harder for the replacement to happen.
One of the libraries CGLIB as far as I know, helps in such a scenario, whereby it generates a dynamic subclass for the class in consideration and in overriden method performs the magic as described above, by calling super.save(o) to delegate to original code.
Now to the problem of injection.
Create interface and make your dao implement that and spring will default to JDK proxy as it is behaving now.
Add proxy-target-class="true" attribute to <tx:annotation-driven transaction-manager="transactionManager"/>
As far as exception is concerned it is throwing as it is expecting injected bean to be of type 'HibernateController' but its not.
For you reference you can refer links below.
10.5.6 Using #Transactional
Spring AOP Doc
Hope this helps !!!!!.
If your are using Spring MVC make sure to scan specific controller classes alone in servlet context file. Otherwise it will scan 2 times and transaction is not available on the application context.

Spring JPA - Injecting transaction manager vs injecting entity manager

If I wanted manage transactions programmatically, what is the difference between starting the transaction by injecting a PlatformTransactionManager vs directly injecting EntityMangerFactory/EntityManager and getting transaction from Entitymanager
public class MyDAO {
#PersistenceContext(unitName="test") EntityManager em;
JpaTransactionManager txnManager = null;
public void setTxnManager(JpaTransactionManager mgr) {
txnManager = mgr;
}
public void process(Request request) throws Exception {
TransactionStatus status =
txnManager.getTransaction(new DefaultTransactionDefinition());
try {
em.persist(request);
txnManager.commit(status);
} catch (Exception up) {
txnManager.rollback(status);
throw up;
}
}
As apposed to injecting EntityManager directly
public class MyDAO {
#PersistenceContext(unitName="test")
EntityManager em;
public void process(Request request) throws Exception {
EntityTransaction txn = em.getTransaction();
try {
em.persist(request);
txn.commit();
} catch (Exception up) {
txn.rollback();
throw up;
}
}
where as spring config snippet looks like this
<beans>
<bean id="MyDAO" class="com.xyz.app.dao.MyDAO">
<context:annotation-config />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerE ntityManagerFactoryBean">
<property name="persistenceUnitName" value="persistence" />
<property name="dataSource" ref="dataSourceProvider" />
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
</bean>
<bean id="transactionManagerJpa" class="org.springframework.orm.jpa.JpaTransactionM anager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
</beans>
Transaction managers should not be injected into DAOs, because a DAO has no way to tell whether they're one participant in a larger transaction or not.
I think the transaction manager belongs with the service layer, not the persistence layer. The services know about use cases and units of work. They orchestrate other services, DAOs and model objects to fulfill their use cases.

Resources