Spring dependency injection to other instance - spring

from the app-context.xml:
<bean id="userDao" class="com.vaannila.dao.UserDAOImpl">
<property name="sessionFactory" ref="mySessionFactory"/>
</bean>
<bean name="MyServiceT" class="com.s.server.ServiceT">
<property name="userDao" ref="userDao"/>
</bean>
and inside ServiceT.java:
private UserDAO userDao;
public void setUserDao(UserDAO userDao){
this.userDao = userDao;
}
the issue is: the setUserDao is called when the server goes on but when I call my doGet method:
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
PrintWriter writer = response.getWriter();
writer.write("hello");
}
the userDao is null.
I put a breakpoint inside the setUserDao method and than another one inside the doGet method and saw that it is not the same insatnce... what is the reason? how can I fix it?
thanks!

Spring is atowiring your bean correctly, the problem is that servlet container instantiates your servlet independently of spring. So you basically have two different instances - one created by spring and another created by container.
One workaround is to use ServletContextAttributeExporter, by putting the following in your app-context.xml:
<bean class="org.springframework.web.context.support.ServletContextAttributeExporter">
<property name="attributes">
<map>
<entry key="userDao">
<ref bean="userDao"/>
</entry>
</map>
</property>
and then, in your servlet:
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
UserDao userDao = (UserDao)getServletContext().getAttribute("userDao");
// do something with userDao
PrintWriter writer = response.getWriter();
writer.write("hello");
}
another is to access the WebApplicationContext directly:
protected void doGet(HttpServletRequest reqest, HttpServletResponse response)
throws ServletException, IOException {
WebApplicationContext springContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
UserDao userDao =(UserDao)springContext.getBean("userDao");
}
... or simply use Spring MVC and let it autowire everything like it should.
Also see this blog post. It might be easier to convert your servlet to HttpRequestHandler and let it be served by HttpRequestHandlerServlet, both provided by spring.

Related

Replace Private Method of Spring Bean

i have requirement to replace private method of spring bean, can i achieve through spring replace.
My Code :
Replacer Class :
public class PrivateCarRep extends Car implements MethodReplacer{
#Override
public Object reimplement(Object obj, Method method, Object[] args) throws
Throwable {
// new property of Car.breaks() method.
System.out.println("New privateBreaksIs Done from Shiv");
return obj;
}
}
Car.java
package org.websparrow.beans;
public class Car {
private void privateBreaks() {
System.out.println("Old car break. privateBreaks");
}
}
My Spring Configuration:
<bean id="PrivateCarRep" class="org.websparrow.beans.PrivateCarRep"/>
<bean id="car" class="org.websparrow.beans.Car">
<replaced-method name="privateBreaks" replacer="PrivateCarRep" />
</bean>
Dear All,
i already know that i can't replace private method through spring replacer but is there any workaround for this in spring..
You need to define PrivateCarRep as a bean:
<bean id="privateCarReplacer" class="com.xx.yy.zz.PrivateCarRep" />
<bean id="car" class="org.websparrow.beans.Car">
<replaced-method name="privateBreaks" replacer="privateCarReplacer" />
</bean>
I'm afraid you can't do that,I thing the method should be be protected or public.

Spring Integration: ClientHttpRequestInterceptor intercept() method not called when request is sent

I have set up a spring-integration application as followed, and want to log the outbound request using ClientHttpRequestInterceptor.
The setup is below.
I sent the Http-get using curl and got result, but the method CustomClientHttpRequestInterceptor.intercept() never gets called when app is debugged.
I must have missed something in the setup. Thanks for helping.
Configuration:
<bean id="customRT" class="org.springframework.web.client.RestTemplate">
<property name="interceptors">
<list>
<bean class="hello.CustomClientHttpRequestInterceptor" />
</list>
</property>
</bean>
<int:chain...>
<int:header-enricher....
<int-http:outbound-gateway url="http://example.com/vhosts"
rest-template="customRT"
http-method="GET"/>
</int:chain>
public class CustomClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
Logger logger = LoggerFactory.getLogger(this.getClass());
#Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
throws IOException {
logger.info("request.getURI().toString());
return execution.execute( request, body );
}
The configuration and code are correct. I've forgot that there is a cache installed, and that's why the intercept() method never gets called.

With Spring MVC can you make one controller call another controller to handle an error page?

I have a controller which can throw an exception. When it does throw an exception it will show my errorpage.jsp, instead of the jsp page I wanted to show. An exxample of this controller is:
public class myController implements Controller {
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
Map<String, Object> model = new HashMap<>();
// Some logic which can throw an error....
return model;
}
}
The application-servlet.xml looks like this:
...
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/"/>
<property name="suffix" value=".jsp"/>
</bean>
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/login.html">myController</prop>
<prop key="/errorpage.html">myErrorController</prop>
</props>
</property>
</bean>
...
Normally when an error, like navigating to a page that doesn't exist, occurs the error controller will be called which will return a hashmap of variables for the error page jsp. However, when the login controller encounters an error it will show the error page, but it won't call the error controller which would provide some of these parameters, so the page is incomplete.
Is there some way to define in the servlet.xml for the myController to call the myErrorController when it encounters an error and redirects to the error page?
You can annotate a controller class with #ControllerAdvice which will be shared between all Controllers. Then using the #ExceptionHandler annotation you can create methods to handle specific exceptions.
Example:
#ControllerAdvice
public class ExceptionHandlerAdvice {
#ExceptionHandler(MyException.class)
public ModelAndView handleException(MyException e, HttpServletRequest request, HttpServletResponse response) { // included servlet request and response
ModelAndView model = new ModelAndView("error/errorpage.jsp");
model.addObject("exception", e);
return model;
}
}
And anytime you throw MyException in any of your other controllers, this controller advice method will handle the exception for you! As the exception, servlet request and response is passed to the ExceptionHandler method, all of that information is available to you.
Example in another controller:
#Controller
public class SomeController {
#Autowired
private DataService dataService;
#RequestMapping(value = '/', method = RequestMethod.POST)
public String doSomething() {
return dataService.foobar(); // throws MyException which is handled with ExceptionHandler
}
}

Spring AuthenticationSuccessHandler autowired Service/DAO is null

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

Is it possible to attach BeanPostProcessor with specific bean initilzation

I am wondering if it is possible to define a BeanPostProcessor class which can only be executed for specific beans.
As per configuration, I can have 2 beans like as mentioned below. Here InitHelloWorld is implementing BeanPostProcessor. postProcessBeforeInitialization and postProcessAfterInitialization methods are overwritten here. These methods gets called for all the bean initialized. I want these methods being called only for com.tutorialspoint.HelloWorld
<bean id="helloWorld" class="com.tutorialspoint.HelloWorld"
init-method="init" destroy-method="destroy">
<property name="message" value="Hello World!"/>
</bean>
<bean id="helloWorld1" class="com.tutorialspoint.HelloWorld1"
init-method="init" destroy-method="destroy">
<property name="message" value="Hello World!"/>
</bean>
<bean class="com.tutorialspoint.InitHelloWorld" />
Consider to use some marker annotation on those classes:
public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException {
Class<?> targetClass = AopUtils.getTargetClass(bean);
if (AnnotationUtils.findAnnotation(beanClass, MyMarker.class) != null) {
....
return bean;
}
return bean;
}
Try checking the class itself when defining the method something like:
public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException {
if (bean.getClass().equals(HelloWorld.class)) {
ReflectionUtils.doWithFields(bean.getClass(), new FieldCallback() {
......
}
A simple if-statement that checks the class instance in the postProcessor initialization will do the trick, that is:
if (bean instanceof HelloWorld){...}
or
if (bean.getClass().equals(HelloWorld.class)){...}
To put it in context:
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof HelloWorld){
System.out.println("This only prints for an instance of HelloWord");
}

Resources