Spring AuthenticationSuccessHandler autowired Service/DAO is null - spring

I am having a AuthenticationSuccessHandler which should hold a UserService. My problem is that i am getting a NullPointerException on the userService at this line:
logger.debug(userService.getAllUsers().toString());
AuthenticationSuccessHandlerImpl:
#Repository
public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHandler {
private static final Logger logger = LoggerFactory.getLogger(AuthenticationSuccessHandlerImpl.class);
#Autowired
private UserService userService;
#Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
logger.debug(userService.getAllUsers().toString());
response.setStatus(HttpServletResponse.SC_OK);
response.sendRedirect("index");
}
}
I Have also tried #Service and #Component Annotation but the same error.
It works in all other Services and Controller from my project but not in this Handler.
I also have this line of code in my config:
<context:component-scan base-package="com.net4you.*" />
<tx:annotation-driven />
EDIT:
AuthenticationSuccessHandlerImpl is not created with new, but with:
<security:form-login login-page="/login" default-target-url="/index" authentication-failure-url="/fail2login"
authentication-success-handler-ref="customAuthenticationSuccessHandler"/>
<beans:bean id="customAuthenticationSuccessHandler" class="com.net4you.slamanagement.helper.AuthenticationSuccessHandlerImpl"/>
Project structure:
Debugger:

1) you dont need .*
<context:component-scan base-package="com.net4you.*" />
this is enough
<context:component-scan base-package="com.net4you" />
2) are you sure that userService is null?
3) configuration looks fine, maybe getAllUsers() method is returning null,
can you show its implementation?
UPDATE
You can solve this problem in two ways
1) remove
<beans:bean id="customAuthenticationSuccessHandler" class="com.net4you.slamanagement.helper.AuthenticationSuccessHandlerImpl"/>
and annotate AuthenticationSuccessHandlerImpl like this
#Component("customAuthenticationSuccessHandler")
public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHandler {
private static final Logger logger = LoggerFactory.getLogger(AuthenticationSuccessHandlerImpl.class);
#Autowired
private UserService userService;
#Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
logger.debug(userService.getAllUsers().toString());
response.setStatus(HttpServletResponse.SC_OK);
response.sendRedirect("index");
}
}
2) the second way would be creating setter of userservice in AuthenticationSuccessHandlerImpl , create userservice bean in xml manually and then inject it directly using setter property of authenticationSuccessHandlerImpl in xml, this solution is more complicated and i would suggest you to use first one
Your implementation doesn't work because you define a bean in xml without setting the userservice for it (#autowired doesn't work if you define bean manually) and then you inject this bean into form-login

Related

ControllerAdvice annotation in spring 4 is not working

In spring-mvc.xml:
<beans ...>
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" />
<bean class="com.app.controllers.ExceptionController"/>
....
</beans>
In GlobalException.java:
#ControllerAdvice(basePackages = "com.exceptions")
public class GlobalException {
#ExceptionHandler(UserDefinedException.class)
public ModelAndView processCustomException(UserDefinedException ud) {
ModelAndView mav = new ModelAndView("exceptionPage");
mav.addObject("name", ud.getName());
mav.addObject("message", ud.getMessage());
return mav;
}
}
In ExceptionController.java:
public class ExceptionController implements Controller {
#Override
public ModelAndView handleRequest(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception {
throw new UserDefinedException("Custom Exception has occured", "CustomException");
}
}
Ecxception is throwing as com.exceptions.UserDefinedException: Custom Exception has occured. But ExceptionHandler method is not called. Whats wrong is this code. I'm using spring 4.3 version.
enable Spring's component scanning in your spring-mvc.xml by adding this:
<context:component-scan base-package="com.exceptions" />
and remove your obsolete XML configured Spring bean (<bean class="com.app.controllers.ExceptionController"/>)
also annotate your controller classes with #Controller and add a #RequestMapping to your controller methods, e.g. like this:
#Controller
public class ExceptionController {
#RequestMapping(value="/whatever", method=RequestMethod.GET)
public ModelAndView handleRequest(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception {
throw new UserDefinedException("Custom Exception has occured", "CustomException");
}
}
this way, your classes annotated with Spring stereotype annotations (#Component, #Service, #Controller, #Repository) should be found, instantiated and registered as Spring beans by Spring itself at application startup!

Authentication using request scoped context with Spring

I am trying to create custom "userContext" as a SpringBean with request scope but I am unable to do so. Basically I have a Jersey REST api and I want to do authentication and authorization using my custom filters in which I autowire my "userContext" bean. The process looks like this:
REST API called (I expect Spring to create new instance of userContext bean)
AuthenticationFilter autowires new instance of userBean and populates it
AuthorizationFilter autowires the same instance which is populated now and authorize the user
When i first call the REST api (after server restart), it works as expected, but any other call fails, because AutorizationFilter gets an empty instance of userBean. I expect some fundamental misunderstanding of scopes on my part.
Btw: I'd like to avoid using ThreadLocal directly since Request scope should take care of it
I would like to know, why authorizationFilter doesn't see the populated version of the userBean and why the first call works. Thanks in advance for any help.
Just some parts of the code:
#Secured({Role.ADMIN}) //custom annotation
#GET
#Path("{id}")
public Response getUserById(#PathParam("id") Long id) throws IOException, MainException {
#Secured //custom annotation
#Provider
#Priority(Priorities.AUTHENTICATION)
#Scope(value="request", proxyMode= ScopedProxyMode.TARGET_CLASS)
public class AuthenticationFilter implements ContainerRequestFilter
#Autowired
private User userContext;
#Secured //custom annotation
#Provider
#Priority(Priorities.AUTHORIZATION)
#Scope(value="request", proxyMode= ScopedProxyMode.TARGET_CLASS)
public class AuthorizationFilter implements ContainerRequestFilter {
#Autowired
private User userContext;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
#Component
#Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class User extends ModelBase implements Serializable {
Since Providers are not request scoped, I had to inject whole ApplicationContext so I could directly modify the right instance of userContext bean (which is request scoped). Basically I did something like this in both filters:
#Autowired
private ApplicationContext applicationContext;
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
User userBean=applicationContext.getBean(User.class);
....
userBean.setSomething("aaa");
Then I could just autowire such bean in my REST Resources, because they are request scoped by defaul:
#Component
#Api(value="/users", description = "Endpoint for Users listing")
#Consumes({MediaType.APPLICATION_JSON, Constants.API_VERSIONS.V1_HEADER_XML, Constants.API_VERSIONS.V1_HEADER_JSON})
#Produces({MediaType.APPLICATION_JSON, Constants.API_VERSIONS.V1_HEADER_XML, Constants.API_VERSIONS.V1_HEADER_JSON})
#Path("/users")
public class UserResource {
private static final Logger logger = LoggerFactory.getLogger(UserResource.class);
#Autowired
private User authenticatedUser;
This solution should be viable and resistent against thread race conditions etc.

Letting Spring security pick implementation of class implementing custom authentication provider

We have a webapp which implements custom authentication via AuthenticationProvider.
This works fine now. But we want to provide an option for customer to implement their own authentication class implementing AuthenticationProvider. So they will delete our jar from app and add their jar to classpath.
It appears in security xml we need to specify only class implementing AuthenticationProvider but can't tell spring to pick any class implementing interface AuthenticationProvider
Current XML and Class implementation
<authentication-manager alias="authenticationManager">
<authentication-provider ref="customAuthenticationProvider"/>
</authentication-manager>
<beans:bean id="customAuthenticationProvider" class="w.x.y.z.CustomAuthenticationProvider"></beans:bean
#Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
//Implementation
}
#Override
public boolean supports(Class<?> arg0) {
return true;
}
}
Is there anyway I can tell spring to pick any class implementing AuthenticationProvider?
Maybe you can do it by using type autowiring and factory method:
1-The CustomAuthenticationProvider it will be injected by type autowiring defined only in the jar added by your client and the deleted jar(it must be exactly one instance of AuthenticationProvider).
2-And then use a factory method to inject this provider into the authentication-manager.
1-first step
public class AuthenticationProviderFactory {
#Autowired
private AuthenticationProvider authProvider;
public AuthenticationProvider getAuthenticationProvider() {
return authProvider;
}
}
2-second step
<bean name="authenticationProviderFactory"
class="w.x.y.z..AuthenticationProviderFactory"></bean>
<bean name="authenticationProvider" factory-bean="authenticationProviderFactory"
factory-method="getAuthenticationProvider">
</bean>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="authenticationProvider"/>
</authentication-manager>
!!!! The deleted jar and the new jar must have the same applicationContext.xml name(where the AuthenticationProvider is declared) to make the replace working.
<import resource="applicationContextAuthProvider.xml"/>

Access session scoped variable in spring interceptor

How can i access session scoped variable in spring interceptor?
Session scoped class:
#Component
#Scope("session")
public class User {
}
Controller:
#Controller
#RequestMapping("/restricted")
#Scope("request")
public class RestrictedController {
#Autowired
private User user;
}
Dispatcher servlet:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/restricted/*"/>
<bean class="com.interceptors.RestrictedInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
Interceptor class:
public class RestrictedInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
}
}
In prehandle i want to check if user is logged in (some other checks as well), how can i access session scoped user variable here? Autowiring user in Interceptor class throws exception.
You should be able to access your session-scoped user using the following code:
request.getSession().getAttribute("scopedTarget.user");
See related post here and org.springframework.aop.scope.ScopedProxyUtils class.

Spring: Autowired is null in ejb class

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).

Resources