Spring: Autowired is null in ejb class - spring

I have the following situation:
#Controller
public class myController {
#Autowired
private IProxy service;
public ModelAndView init(HttpServletRequest request, HttpServletResponse response) throws Exception {
List<String> list = service.getName();
}
}
Then my Service is define as follow:
public interface IProxy {
public List<String> getName();
}
Proxy class is responsible for the lookup to the remote bean
#Service("service")
public class Proxy implements IProxy {
...
public List<String> getName() {
return myClass.getName();
}
And the implementation is the following:
#Interceptors(interceptor.class)
#Stateless
#Resource(name = "java:/db")
#Remote(MyClassRemote.class)
public class MyClassImpl extends MyEjb implements MyClassRemote{
#PersistenceContext(unitName = "db")
private EntityManager em;
#Resource
private SessionContext sctx;
#Autowired
public IMyRepo myRepo;
#Override
public List<String> getName() {
try {
return myRepo.getName(em);
}
catch (Exception ex) {
ex.printStackTrace();
throw ex;
}
finally {}
}
So, the problem is that here myRepo is null. I don't know why because IMyRepo and his implementation are always located within the path scanned by Spring.
Just one clarification: MyRepo class that implements IMyRepo is annotated with #Repository.
Any idea?

you can inject spring beans in EJB using Spring interceptors, as explained here in the official documentation. Basically you'll need to adjust your class as follows:
// added the SpringBeanAutowiringInterceptor class
#Interceptors({ interceptor.class, SpringBeanAutowiringInterceptor.class })
#Stateless
#Resource(name = "java:/db")
#Remote(MyClassRemote.class)
public class MyClassImpl extends MyEjb implements MyClassRemote{
// your code
}
You'll also need to define the context location in a beanRefContext.xml file (with your own application context file):
application-context.xml version
<bean id="context"
class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg>
<list>
<value>application-context.xml</value>
</list>
</constructor-arg>
</bean>
Java Configuration version:
<bean id="context"
class="org.springframework.context.annotation.AnnotationConfigApplicationContext">
<constructor-arg>
<list>
<value type="java.lang.Class">com.your.app.Configuration</value>
</list>
</constructor-arg>
</bean>

Spring beans and EJB are two different things, you can't just inject a Spring bean in an EJB, because that EJB is no Spring bean, so Spring doesn't know there is a field which should be injected by Spring (unless you use some fancy AOP stuff, which can enable injection into non-Spring-managed beans).

Related

springboot+mybatis Exception : org.springframework.beans.factory.NoSuchBeanDefinitionException

I got the following exception:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [pers.panxin.springboot.demo.mapper.UserMapper] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Controller :
#Controller
public class HelloController {
#Autowired
private UserService userService;
#RequestMapping("/userList")
#ResponseBody
public String getAllUser(){
return "userList : "+userService.getAllUser().toString();//+list.toString();
}
}
Service:
public interface UserService {
public String getString();
public List<User> getAllUser();
}
ServiceImpl:
#Service
public class UserServiceImpl implements UserService {
#Autowired
private UserMapper userMapper;
#Override
public String getString() {
return "something else ... ";
}
#Override
public List<User> getAllUser() {
return userMapper.getAllUser();
}
}
Mapper Interface:
#Service
public interface UserMapper {
/**
* #return
*/
public List<User> getAllUser();
}
Application's main class
#ComponentScan
#EnableAutoConfiguration
#SpringBootApplication
public class ApplicationStarter {
public static void main(String[] args) {
SpringApplication.run(ApplicationStarter.class, args);
}
}
how the exception happened or something wrong in my code?
1.
I am not sure if you are using mybatis-spring library. If you are trying to integrate MyBatis with Spring you should use it. So make sure you have it as dependency.
2.
When you have mybatis-spring as dependency, just add this annotation to you configuration class:
#MapperScan("package.where.mappers.are.located")
It is because mybatis-spring has separate scanning for MyBatis mappers. Also you should remove #Service annotation from you mapper because if this separate mybatis-spring scanning.
EDIT:
As #Persia pointed out, you can use mybatis-spring-boot-starter library to pull mybatis-spring dependency into your Spring Boot project.
Get the same error today. Check the bean configuration org.mybatis.spring.mapper.MapperScannerConfigurer and org.mybatis.spring.SqlSessionFactoryBean. I mistyped the "basePackage" value for the former one, and the "typeAliasesPackage" value for the second one. After fixing the path, it works fine. Like this:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="package.path.to.your.model"/>
<property name="mapperLocations" value="classpath*:mappers/*.xml"/>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="package.path.to.your.dao"/>
</bean>
Add MappedTypes along with #MapperScan with
Code looks like the below
#MappedTypes({UserMapper.class})
#MapperScan("package.where.mappers.are.located")

Spring autowired annotation with java timertask

Autowired annotation doesn't work. I thought there must be a problem with Timertask or run method. My other classes working fine(I mean Autowired annotation initialize genericService without any problem) but in this class genericService value is null. Is there any idea?
public class UsersUpdateTask extends TimerTask {
#Autowired
GenericService genericService;
#Override
public void run() {
//genericService.save() gives null pointer.
}
}
My applicationContext definition;
<bean id="usersUpdateTask" class="myPackage.UsersUpdateTask">
</bean>
<bean id="genericLogger" class="utilPack.Logger">
</bean>
<bean id="genericService" class="servicePack.GenericService">
This class working perfectly;
public class Logger implements Serializable {
#Autowired
private GenericService genericService; //works fine
.....
}
There is a method in another class to call UsersUpdateTask's run method;
public void updateUsersList(){
timer.schedule(new UsersUpdateTask(), 1000, 60*60*1000);
}
Well there it is
timer.schedule(new UsersUpdateTask(), 1000, 60*60*1000);
you're creating the object yourself. Spring can't autowire objects it doesn't control or process. Use the injected UsersUpdateTask bean.

How can we switch between different Implementations in Spring Context XML with an Boolean?

How can we switch between different Implementations in Spring Context XML with an Boolean?
for example:
<bean id="detailsController" class="com.something.detailsController" >
if true then
<property name="dao" ref="firstDao"/>
else
<property name="dao" ref="secoundDao"/>
I know in Spring3 we can work with profiles
You could do that by modifying your Java code and use Spring EL together with ApplicationAware and InitializingBean.
public class DetailsController implements ApplicationContextAware, InitializingBean {
private DetailsControllerDAO dao;
private String daoName;
private ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
public void afterPropertiesSet() {
dao = applicationContext.getBean(daoName);
}
public void setDaoName(String daoName) {
this.daoName = daoName;
}
}
In XML:
<bean id="detailsController" class="com.something.detailsController">
<property name="daoName" value="#{myCondition ? 'firstDao' : 'secondDao'}" />
</bean>
Of course, this solution has the disadvantage to add dependency to Spring code in your controller. To avoid that, you could move that code in a proxy class, as described by Guillaume Darmont.
I dont think this can be done at the XML level.
Spring really cannot do that. See the bean lifecycle. Been classes are created, than properties are injected and than afterPropertiesSet() or #PostConstructor methods are invoked. Of course when I omit lazy initialized beans.
But if you want for testing etc. and so you need just the firstDao or the secondDao in your application at the sametime that depends just on your settings, you can use a bean factory. The bean factory creates your bean as you want. I also use it for to split development environment, test environment and production environment.
package com.dummyexample.config;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Factory bean to create real or test dao.
* The result depends on realDaoEnabled configuration parameter.
*
* #author Martin Strejc
*/
#Configuration
public class DaoBeanFactory {
// mapping to servlet context configuration
#Resource(mappedName = "realDaoEnabled")
private Boolean realDaoEnabled = true;
// TestDao extends or implements Dao
#Autowired
private TestDao testDao;
// ProdDao extends or implements Dao
#Autowired
private ProdDao prodDao;
public DaoBeanFactory() {
}
#Bean(name="dao")
public Dao getDao() {
if(realDaoEnabled) {
return prodDao;
}
return testDao;
}
}
Since your DAOs are exchangeable, they inherits the same type (abstract class or interface). Thus you can write a RoutingDetailsControllerDAO.
Let's say that your common interface is named DetailsControllerDAO, with two methods getDetails and getMoreDetails inside, the code would be :
public class RoutingDetailsControllerDAO implements DetailsControllerDAO {
private DetailsControllerDAO firstDAO;
private DetailsControllerDAO secondDAO;
protected DetailsControllerDAO getDAOToUse() {
return YOUR_BOOLEAN_CONDITION ? firstDAO : secondDAO;
}
#Override
public Details getDetails() {
return getDAOToUse().getDetails();
}
#Override
public Details getMoreDetails() {
return getDAOToUse().getMoreDetails();
}
// Insert firstDAO and secondDAO setters below
...
}
Your Spring XML config is now :
<bean id="detailsController" class="com.something.detailsController" >
<property name="dao" ref="routingDetailsControllerDAO"/>
</bean>
<bean id="routingDetailsControllerDAO" class="com.something.RoutingDetailsControllerDAO">
<property name="firstDao" ref="firstDao"/>
<property name="secondDao" ref="secondDao"/>
</bean>
Few possibilities:
You can either use profiles (<beans profiles="profileOne">).
You can use FactoryBean to create the correct DAO
You can use SPeL
The last one is the easiest:
<bean id="detailsController" class="com.something.detailsController">
<property name="dao" ref="#{condition ? 'firstDao' : 'secondDao'}" />
</bean>
Of course you can load bean name from properties file via property configurer:
<bean id="detailsController" class="com.something.detailsController">
<property name="dao" ref="${bean.name.from.properties.file}" />
</bean>

Injecting EJB 3 into Spring Bean

I am trying to inject EJB into Spring (3.1.2) service (both in different WARs)
Both are very simple (methods removed to simplify example):
EJB:
#Remote
public interface MyBean {
}
#Singleton
public class MyBeanImpl implements MyBean{
}
Service:
#Service
public class MyServiceImpl implements MyService{
}
At first sight thing is very simple, but I tried:
#EJB(lookup = "java:global/ejbApp/MyBeanImpl!com.my.MyBean")
private MyBean myBean;
and it didin't work. Then I also tried:
#EJB(mappedName = "java:global/ejbApp/MyBeanImpl!com.my.MyBean")
private MyBean myBean;
And
#Resource(mappedName = "java:global/ejbApp/MyBeanImpl!com.my.MyBean")
private MyBean myBean;
but neither worked.
I managed to inject my EJB using:
<jee:jndi-lookup id="myBean" jndi-name="java:global/ejbApp/MyBeanImpl!com.my.MyBean" />
in my spring configuration and in the service:
#Autowired
private MyBean myBean;
But I really dont like this solution. I would like to have my JNDI path in some annotation to be able to do e.g:
#EJB(lookup = MyBean.JNDI_NAME)
private MyBean myBean;
We have found quite nice and simple solution.
Into spring configuration file one has to put:
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor">
<property name="alwaysUseJndiLookup" value="true" />
</bean>
And that enables spring to search for the beans annotated with #Resource in JNDI.
So now one can do:
#Resource(mappedName = MyBean.JNDI_NAME)
private MyBean myBean;
Are you aiming to get rid of XML or to have JNDI name in annotation? If the former, I haven't tested it, but should work:
#Configuration
public class EjbCfg {
#Bean
public JndiObjectFactoryBean myBean() {
JndiObjectFactoryBean factory = new JndiObjectFactoryBean();
factory.setJndiName(MyBean.JNDI_NAME);
return factory;
}
}
Now you can simply inject:
#Autowired
private MyBean myBean;

spring3-annotation-JdbcDaoSupport

Use annotation in dao
#Repository("testDao")
public class TestDaoImpl extends JdbcDaoSupport implements BaseDao{
#Override
public Object addObject(String sqlid, Object obj) {
// TODO Auto-generated method stub
return null;
}
Caused by: java.lang.IllegalArgumentException: 'dataSource' or 'jdbcTemplate' is required
I do not want to use :
<bean id="termsDao" class="com.manage.base.dao.impl.TestDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
this code set in xml, and “jdbcTemplate” has been defined in other “spring-xml”。
How to solve this problem by an annotation :“'dataSource' or 'jdbcTemplate' is required”
You can use one of the below approaches. The first one - taking a dataSource is preferred / recommended as you don't expose a SpringFramework class in your public interface. Both will work.
#Repository("testDao")
public class TestDaoImpl extends JdbcDaoSupport implements BaseDao{
#Autowired
TestDaoImpl(DataSource dataSource) {
setDataSource(dataSource);
}
}
Or
#Repository("testDao")
public class TestDaoImpl extends JdbcDaoSupport implements BaseDao{
#Autowired
TestDaoImpl(JDBCTemplate template) {
setJdbcTemplate(template);
}
}
I even feel injecting datasource as a constructor to your DAO is a unnecessary coding step.
Why not inject datasource in Spring config XML into JDBC template and just get jdbctTemplate
object in every DAO.
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
and let your DAO extend JDBCSupport class.
public class PersonDao extends JdbcDaoSupport{
public List<Person> selectAll(){
String selectAllSql = "SELECT * FROM PERSON;";
return getJdbcTemplate().query(selectAllSql, new PersonRowMapper());
........
}
}
Full example :
http://www.studytrails.com/frameworks/spring/spring-jdbc-dao-support.jsp

Resources