Below are my classes and xml:
#Component
#Service("ApplicationService")
public class ApplicationServiceImpl implements ApplicationService{
public ApplicationDao getApplicationDao() {
return applicationDao;
}
public void setApplicationDao(ApplicationDao applicationDao) {
this.applicationDao = applicationDao;
}
#Autowired
private ApplicationDao applicationDao;
// some methods..
}
#Service
public interface ApplicationService {
// methods...
}
#Component
#Repository("ApplicationDao")
public class ApplicationDaoImpl implements ApplicationDao {
#Autowired
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
// other methods...
}
public interface ApplicationDao {
// methods...
}
xml file:
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven/>
<context:component-scan base-package="com" />
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<!-- <property name="dataSource" ref="dataSource" /> -->
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
</bean>
<bean id="ApplicationDao" class="com.dao.impl.ApplicationDaoImpl"/>
<bean id="ApplicationService" class="com.service.impl.ApplicationServiceImpl"/>
Here autowiring is not working.in ApplicationServiceImpl, I am getting applicationDao as null. Have not tested sessionFactory in ApplicationDaoImpl.
I know that if I am using #Component then bean declaration in xmnl is not required.
You should not instantiate service like that..
At the time of application loading, spring container will create all instances defined in spring.xml or annotated classes and it's dependencies..
So you have to access them with the following example code..
ApplicationContext applicationContext = ApplicationContextProvider.getApplicationContext();
ApplicationService applicationService = (ApplicationService) applicationContext.getBean("ApplicationService");
Since ApplicationService is having property that is ApplicationServiceDAOImpl, it's already been created by spring container and will return you..
But in case of directly instantiating manually by you, you are just creating instance of ApplicationService but not for ApplicationServiceDAOImpl.. so it obviously returns null
I'm currently using this approach only to access beans or services..
update for comment
public class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext applicationContext;
#Override
public void setApplicationContext(ApplicationContext arg0)
throws BeansException {
applicationContext = arg0;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
}
Hope it helps,
try a change like this:
import org.springframework.beans.factory.annotation.Qualifier;
#Autowired
#Qualifier("ApplicationDao")
private ApplicationDao applicationDao;
this give spring a hint.
If you are using annotations in your application, you should denote it using a tag :
<mvc:annotation-driven />
Add this line in application context xml above component scan tag.
Also, if you are using annotations, remove ApplicationDao and ApplicationService bean declarations from xml.
And don't mark you service and dao classes with both #Component and #Service or #Repository annotations. No need to mark them #Component there. Remove it.
Related
I am new to this Spring and trying to learn it.
I am using basic auth jersey and using spring to inject my db props and instantiate the class. However I am getting null pointer exception when I try this with a REST call using postman.
Below is code snippet
AppContx.xml
<context:annotation-config />
<context:component-scan base-package="com.rest" />
<bean id="userDao" class="com.rest.dao.UserDao">
<property name="dataSource" ref="ds" />
</bean>
<bean id="ds" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/Weber" />
<property name="resourceRef" value="true" />
</bean>
Filter
#Provider
public class AuthenticationFilter implements ContainerRequestFilter {
/*ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
IuserDao userDao = (IuserDao) ctx.getBean("userDao");*/
#Autowired
UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public UserDao getUserDao() {
return userDao;
}
if (userDao.getUSerForAuthentication(password, username) == 1) {
String userRole = "ADMIN";
if (rolesSet.contains(userRole)) {
isAllowed = true;
}
DAO
#Autowired
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
I am successfully able to inject DB properties to my data source using #Autowired but I am unable to instantiate the UserDao in my Filter class.
Thank You
Mark
I want to use #Transactional annotation in the save() method of UserService(concrete class) as follows:
#Service
public class UserService {
#Transactional
public Long save(User userCommand, BindingResult result) {
...
}
}
I will use this service in MyRealm by autowiring.
public class MyRealm extends AuthorizingRealm {
#Autowired
private UserService userService;
}
However, it fails with the following error:
java.lang.IllegalArgumentException: Can not set n.r.c.s.user.UserService field n.r.c.s.realm.MyRealm.userService to com.sun.proxy.$Proxy48
Of course, it works if I remove the #Transational annotation.
My transaction manager setting is as follows:
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"></property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
Please, let me know what's wrong with my code?
Do I need to set up something like proxy?
When proxying is enabled you need to use interfaces, not implementations.
#Service
public class UserService implements SomeInterface {
#Transactional
public Long save(User userCommand, BindingResult result) {
...
}
}
public class MyRealm extends AuthorizingRealm {
#Autowired
private SomeInterface userService;
}
If you do not want to do this, you can always check your AOP config. you are probably doing proxy for a proxy somewhere.
i'm using spring data jpa but i want execute some costume query so how can i get the entity manager in my java classes to make entityManager.createQuery(..)
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="persistenceYous" />
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="persistence" />
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
</bean>
You can obtain your EntityManager as in any other spring application:
public class ProductDaoImpl implements ProductDao {
private EntityManager em;
#PersistenceContext
public void setEntityManager(EntityManager em) {
this.em = em;
}
public Collection loadProductsByCategory(String category) {
em. ....
....
}
}
See: http://docs.spring.io/spring/docs/4.0.0.RELEASE/spring-framework-reference/html/orm.html#orm-jpa-straight
In your applicationContext.xml, check that you have the following:
<context:annotation-config />
That will add support for several annotations, such as #PersistenceContext, that injects an EntityManager. So in your Spring-managed beans, you can do:
public class MyClass {
private EntityManager entityManager;
#PersistenceContext
public void setEntityManager(EntityManager em) {
this.entityManager = em
}
public void myMethod() {
Query q = entityManager.createQuery(...);
// ...
}
}
If you want to add suport for just #PersistenceContext, and not the other annotations that <context:annotation-config /> supports, you would delete that from the applicationContext.xml and add the specific BeanPostProcessor:
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" scope="singleton">
<!-- Optional configuration of PersistenceAnnotationBeanPostProcessor, for advanced use cases -->
</bean>
Firstly follow this link to get the steps required to implement..
check this link
In second step he uses #Autowired private JdbcOperations operations;
But that doesn't work for me, so i used the following code.. Which worked for me.
#Component
public class MayorRepositoryImpl extends JdbcDaoSupport implements MayorRepositoryCustom {
#Override
public List<Employee> getUsers(String role) {
return getJdbcTemplate().query("Write your custom query",new RowMapper<Employee>(){
#Override
public Employee mapRow(ResultSet rs, int rownumber) throws SQLException {
// Mapping each row and adding to list and returning the list
Employee employeeBean=new Employee();
employeeBean.setId(rs.getInt("id"));
employeeBean.setEmployeeNumber(rs.getString("employeeNumber"));
employeeBean.setName(rs.getString("name"));
employeeBean.setWorkEmailAddress(rs.getString("workEmailAddress"));
employeeBean.setPersonalEmailAddress(rs.getString("personalEmailAddress"));
return employeeBean;
}
});
}
}
This is perfectly working for me..
If you find any difficulty let me know to help you.
Cheers
If I specify what should be injected into a property, like
<property name="xxx" ref="some_bean" />
or
<property name="xxx">
<bean .../>
</property>
then I have to write a setter method.
May I use some annotation to avoid this like #autowired?
You can do this with constructor injection. 3 main ways to do this:
XML:
<bean id="beanA" class="com.BeanA">
<constructor-arg ref="beanB"/>
</bean>
<bean id="beanB" class="com.BeanB"/>
JavaConfig:
#Configuration
public class MyConfig {
#Bean
public BeanA beanA() {
return new BeanA(beanB());
}
#Bean
public BeanB beanB() {
return new BeanB();
}
}
Autowiring:
#Component
public class BeanA {
private final BeanB beanb;
// This assumes that there is a BeanB in your application context already
#Autowired
public BeanA(final BeanB beanB) {
this.beanB = beanB;
}
}
You can take Autowiring even further, and wire directly to the field:
#Component
public class BeanA {
// This assumes that there is a BeanB in your application context already
#Autowired
private final BeanB beanb;
}
Is there a way in Spring to create a collection, or array, of beans, based on a comma-separated list of classes. For example:
package mypackage;
public class Bla {
private Set<MyBean> beans;
public void setBeans(Set<MyBean> beans) {
this.beans = beans;
}
}
With the application context:
<bean id="bla" class="mypackage.Bla">
<property name="beans">
<set>
<bean class="mypackage.Bean1, mypackage.Bean2" />
</set>
</property>
</bean>
Preferably the beans are all initialized and wired from the context, leaving the code as simplistic as possible, is this possible?
Use a combination of ApplicationContextAware and ApplicationListener:
public class BeanInitializer implements ApplicationContextAware, ApplicationListener<ContextRefreshedEvent> {
private ApplicationContext context;
private List<Class<?>> beanClasses;
public void onApplicationEvent(final ContextRefreshedEvent event) {
final AutowireCapableBeanFactory beanFactory = this.context.getAutowireCapableBeanFactory();
for (final Class<?> beanClass : this.beanClasses) {
beanFactory.autowire(beanClass, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
}
}
public void setApplicationContext(final ApplicationContext context) throws BeansException {
this.context = context;
}
public void setBeanClasses(final List<Class<?>> beanClasses) {
this.beanClasses = beanClasses;
}
}
in your spring config, do this:
<bean class="com.yourcompany.BeanInitializer">
<property name="beanClasses">
<list>
<value>com.yourcompany.Type1</value>
<value>com.yourcompany.Type2</value>
<value>com.yourcompany.Type3</value>
</list>
</property>
</bean>
Edited: Actually, if you want comma separated, it will probably be more like this:
<bean class="com.yourcompany.BeanInitializer">
<property name="beanClasses"
value="com.yourcompany.Type1,com.yourcompany.Type2,com.yourcompany.Type3" />
</bean>
I don't know if there is a built-in property editor that converts a comma delimited string to a list of classes but if not you can either create one yourself or change your setter method to accept a string and parse the string yourself