I have written a custom authenticator for my Play 2.3.4 application which has spring dependency injection configured. I want to be able to inject an 'authService' into my authenticator, but this is not working. My authService is always null. Is it possible to configure autowired injection into authenticators? My authenticator is as follows:
package controllers;
#org.springframework.stereotype.Component
public class AppAuthenticator extends Security.Authenticator {
#Autowired
#Qualifier("authService")
private AuthService authService;
#Override
public String getUsername(Context ctx) {
...
authService.getAuthenticatedUser();
...
}
public void setAuthService(AuthService authService) {
this.authService = authService;
}
...
}
And my Spring configuration includes:
<context:component-scan base-package="controllers"/>
<bean id="authService" class="com.my.auth.class.AuthServiceClass" />
<bean class="play.mvc.Security$AuthenticatedAction" scope="prototype" />
In summary, spring doesn't seem to be injecting properties into my Sercuirty.Authenticator. How do you configure this correctly?
Related
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")
I'm using Spring 4.1.6.
I have something like the following:
foo.properties:
valueX=a
valueY=b
Spring bean:
<context:property-placeholder location="classpath:foo.properties" ignore-unresolvable="false" ignore-resource-not-found="false" />
<bean id="foo" class="com.foo.bar.MyClass" >
<property name="someValue" value="${valueX}" />
</bean>
I have a non-Spring class which also needs to use a value from foo.properties.
Non Spring Class:
public void doSomething() {
String valueY = System.getProperty("valueY");
}
When Spring loads foo.properties, is there a way to populate all the properties into System properties so that I can get "valueY" using System.getProperty("valueY").
I don't want to load foo.properties again in my non-Spring class.
The context:property-placeholder will create a PropertySourcesPlaceholderConfigurer config bean for you. You cannot access the properties from this bean programatically as stated here.
What you can do is to load the properties into a separate spring bean as given below.
#Bean(name = "mapper")
public PropertiesFactoryBean mapper() {
PropertiesFactoryBean bean = new PropertiesFactoryBean();
bean.setLocation(new ClassPathResource("application.properties"));
return bean;
}
and then set the system property when the context load is finished using a listener as given below. Got the code from this answer
#Component
public class YourJobClass implements ApplicationListener<ContextRefreshedEvent> {
#Resource(name = "mapper")
private Properties myTranslator;
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
System.setProperties(myTranslator);
}
}
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).
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>
First, the problem is when I invoke the ejb from the rest servlet, the ejb is always null.
I have a rest web service developed in jersey + spring 3.0.5. And an EJB 3.1 for services.
I have package the war and jar in an ear so my application looks like (I'm using maven for dependency):
+ear
++war
++jar
I was wondering how I could call the services in the jar file from my classes in the war file. As far as I remember it's through JNDI and I need to expose the ejb apis? How should I do that?
I'm sure the EJB are created successfully because I can see the log in the server like this:
Portable JNDI names for EJB UserServiceBean :
[java:global/demo-cg-ear-0.0.1-SNAPSHOT/demo-cg-ejbs/UserServiceBean!com.demo.cg.service.user.UserServiceBeanLocal,
java:global/demo-cg-ear-0.0.1-SNAPSHOT/demo-cg-ejbs/UserServiceBean]|#]
But the problem is when I invoke it in the rest jersey servlet, it's always null:
#Path("/payment")
#Stateless
public class PaymentService {
#Path("/payment")
#Stateless
public class PaymentService {
#EJB
private UserServiceBeanLocal userServiceBean;
#GET
#Path("/hello")
public Response savePayment() {
String result = userServiceBean.getName();
return Response.status(200).entity(result).build();
/* return Response.status(200).entity("hello edward").build(); */
}
}
My applicationContext.xml file
<context:annotation-config />
<context:component-scan base-package="com.sido" />
<context:property-placeholder location="WEB-INF/build.properties" />
<!-- <bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor">
<property name="alwaysUseJndiLookup" value="true" /> </bean> -->
<jee:jndi-lookup id="userServiceBean"
jndi-name="java:global/sido-cg-ear-0.0.1-SNAPSHOT/sido-cg-ejbs/UserServiceBean"
resource-ref="true" lookup-on-startup="true"
expected-type="com.sido.cg.service.user.UserServiceBeanLocal"
proxy-interface="com.sido.cg.service.user.UserServiceBeanLocal"></jee:jndi-lookup>
UserBean class
#Interceptors(SpringBeanAutowiringInterceptor.class)
#Stateless
public class UserServiceBean implements UserServiceBeanLocal {
private String name;
public UserServiceBean() {
name = "edward";
}
#PostConstruct
private void init() {
name = "edward";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Thanks,
czetsuya
For those who are interested this is how I did it: http://czetsuya-tech.blogspot.com/2012/05/how-to-call-stateless-ejb-from-spring.html