Change Implementation for Spring Namespaces (exchange a bean) - spring

I have a question about Spring Integration (or basically Spring in common):
I use the a WebService Inbound Gateway in my Spring XML configuration:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:int-ws="http://www.springframework.org/schema/integration/ws"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration/ws http://www.springframework.org/schema/integration/ws/spring-integration-ws.xsd" >
<int-ws:inbound-gateway
id="ws-in-gw-user"
request-channel="in-user"
reply-channel="out-user"
mapped-request-headers="*"
/>
...
</beans>
When I use <int-ws:inbound-gateway> Tag, a SimpleWebServiceInboundGateway is created. Now I want to exchange this implemantation with a self written extension of this class. Any ideas how to do it?

you could use a BeanPostProcessor bean.
import org.springframework.beans.factory.config.BeanPostProcessor;
public class SimpleWebServiceInboundGatewayBeanPostProcessor implements BeanPostProcessor{
public Object postProcessBeforeInitialization(Object bean, String beanName){
if(bean instanceof SimpleWebServiceInboundGateway) {
return new MyCustomWebSerivceInboundGateway();
}
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}
In your config:
<bean class="....SimpleWebServiceInboundGatewayBeanPostProcessor" />
A BeanPostProcessor allows you to exhange beans during initialization.

Related

Losing autowired attributes after executed the interceptor from Spring AOP

After a lot of time waste trying to find a answer, I decided to post this doubt.
I have a class that I would like to intercept by the Spring AOP.
ObjectToBeProxied.java
package com.ee.beans;
#Service
#Component
#Transactional
public ObjectToBeProxied implements IObjectToBeProxied {
#Autowired
private ParameterValueService parameterValueService;
public void doStuff() {
// do something before the call
getSelfRef().findEventParameterValue(new ParameterValueFilter());
// do something after
}
#HandleException
private Boolean findEventParameterValue(ParameterValueFilter parameterValueFilter) {
ParameterValue parameterValue = getSelfRef().parameterValueService.findParametertValueByFilter(parameterValueFilter);
return parameterValue.value();
}
private ObjectToBeProxied getSelfRef() {
return (ObjectToBeProxied) AopContext.currentProxy();
}
}
ExceptionHandlerAspect.java
package com.ee.aspects;
#Component
public class ExceptionHandlerAspect {
private static Logger LOGGER = Logger.getLogger(ObjectToBeProxied.class);
public Object handleAround(ProceedingJoinPoint joinPoint) throws Throwable {
// Handling the exception. Need to continue either the method throws a expcetion
// but it need to be logged
try {
return joinPoint.proceed();
} catch (Exception e) {
// something to handle the exception
}
return null;
}
}
Spring AOP configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<aop:aspectj-autoproxy expose-proxy="true" proxy-target-class="true"/>
<!-- Activates various annotations to be detected in bean classes -->
<context:annotation-config/>
<context:spring-configured />
<!-- Scans the classpath of this application for #Components to deploy as beans -->
<context:component-scan base-package="com.ee.beans"/>
<bean id="exceptionHandlerAspect" class="com.ee.aspects.ExceptionHandlerAspect" />
<aop:config>
<aop:aspect id="exceptionHandlerConfig" ref="exceptionHandlerAspect">
<!-- Trata exceções lançadas -->
<aop:pointcut id="exceptionHandlerAroundMethod" expression="execution(* com.ee.beans.ObjectToBeProxied.*(..)) && #annotation(com.ee.exceptions.HandleException)" />
<aop:around pointcut-ref="exceptionHandlerAroundMethod" method="handleAround" />
</aop:aspect>
</aop:config>
When I call the method ObjectToBeProxied.doStuff(), ObjectToBeProxied.parameterValueService autowired is ok, not null.
But, when the aspect intercept the method call ObjectToBeProxied.findEventParameterValue(..) and execute the ExceptionHandlerAspect.handleAround(..), the ObjectToBeProxied.parameterValueService is not ok, it's null.
Debugging it, I can figure out that the Spring Aspect return the ObjectToBeProxied proxy after intercept it, but without the autowired attributes objects.
Where am I getting wrong?

Autowiring a Spring Bean from a JSF Controller

I receive NullPoin Exception while calling any method of a Spring Bean, as it seems it is not injected in the container. And I can' t understand why.
Th particularity is that the Controller is using JSF and the Beans are Spring Bean: may be is this the problem? Or just configuration mistake?
The (simplified) code and config is:
Context.xml (called from root context)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:plugin="http://www.springframework.org/schema/plugin"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.0.xsd
http://www.springframework.org/schema/plugin http://www.springframework.org/schema/plugin/spring-plugin.xsd">
<!--===========LANGUAGE_TO_LOCALE SERVICE CONFIG BEGIN===========-->
<bean
id="languagesCountryLocaleHelper"
class="com.i18n.MyControllerHelper"
scope="request" />
</beans>
JSF COntroller:
#RequestScoped
#Named
public class MyController {
#Autowired
private MyControllerHelper helper;
public void doSomething() {
helper.doSomething ();
}
}
MyControllerHelper:
#Component
public class MyControllerHelper {
public void doSomething() {
// do something useful
}
}
So, this is the simplified case.. do you have any idea on where my error can be?
Thank you in advance!
#Autowired
private MyControllerHelper helper = new MyControllerHelper();
change to this
#Autowired
private MyControllerHelper languagesCountryLocaleHelper;
I solved the problem injecting MyControllerHelper through:
helper = AppContext.getBean(MyControllerHelper.class);
After that, the bean is instantiated and injected and at cascade all the other beans after it.
I suppose it was due by the fact as JSF Controller the Controller instance Object was in a different container now automatically aware of Spring Beans.

Inject property to spring bean using annotation

As explained here and here it is quite clear how to do it but still can't seem to make it work.
I simply like to use the #Value annotation in order to inject a property to a spring bean. I created a basic spring MVC project with one controller and one bean.
Here is my application context:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util" xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd
http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.1.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<context:component-scan base-package="me.co.fatsecret" />
<!-- Properties -->
<bean id="props"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:fatProperties.properties" />
</bean>
</beans>
I have one bean called Configuration:
package me.co.fatsecret;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
#Component
public class Configuration {
/*--- Members ---*/
#Value("${api_key}")
protected String API_KEY;
#Value("${api_secret}")
protected String API_SECRET;
#Value("${api_url}")
protected String API_URL;
/*--- Constructors ---*/
public Configuration() {
}
/*--- Getters & Setters ---*/
public String getAPI_KEY() {
return API_KEY;
}
public void setAPI_KEY(String aPI_KEY) {
API_KEY = aPI_KEY;
}
public String getAPI_SECRET() {
return API_SECRET;
}
public void setAPI_SECRET(String aPI_SECRET) {
API_SECRET = aPI_SECRET;
}
public String getAPI_URL() {
return API_URL;
}
public void setAPI_URL(String aPI_URL) {
API_URL = aPI_URL;
}
}
Now I have only one controller, injected with this Configuration class and as I call this controller I see that the values in the Configuration class are not populated right.
My properties file is located under the resources folder (src/main/resources) and is a part of my classpath (done by default since this is a maven project). Here it is:
api_url=http://platform.fatsecret.com/js?
api_key=SomeKey
api_secret=SomeSecret
The file name is fatProperties.properties.
As I debug my server when calling the controller I see that the content of the Configuration class is:
${api_key}
${api_secret}
${api_url}
This is the actual value of the Strings, wich means that the vales from the properties file are not getting injected for some reason.
Am I missing something here?
UPDATE1: I replaced the PropertyPlaceholderConfigurer bean with:
<context:property-placeholder location="classpath:fatProperties.properties"/>
Getting the same result
Ok, got it!
I'm using a spring MVC project, which means I have a separated context for my web layer (the controllers). The "Configuration" bean which hods the properties using the #Value annotation is injected to a controller. My property-placeholder is defined within my root-context hence it cannot be seen from my controller. To resolve the issue I simply added the property-placeholder definition to my DispatcherServlet context and it works like a charm :)
Add this to your application context file:
<context:property-placeholder location="classpath:fatProperties.properties" />
Try
#Value("#{props['api_key']}")
private String apiKey;

Spring and auto-wiring: NullPointerException

I'm trying to get a grip on auto-wiring in Spring, but I can't seem to properly instantiate the bean (a DocumentBuilder). I have created a custom JSP tag as such:
public class MyTag extends SimpleTagSupport {
#Autowired
private DocumentBuilder documentBuilder;
public void setBuilder(DocumentBuilder builder) {
this.documentBuilder = builder;
}
#Override
public void doTag() throws IOException {
// documentBuilder is null in here!
}
}
This is the servlet configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- Scan for HTTP/REST controllers -->
<context:component-scan base-package="the.right.package" />
<context:annotation-config/>
<bean id="documentBuilderFactory"
class="javax.xml.parsers.DocumentBuilderFactory"
factory-method="newInstance">
<property name="validating" value="false" />
<property name="ignoringElementContentWhitespace" value="true" />
</bean>
<bean id="documentBuilder" class="javax.xml.parsers.DocumentBuilder"
factory-bean="documentBuilderFactory"
factory-method="newDocumentBuilder">
</bean>
</beans>
Any ideas?
You can only inject in spring beans! But Jsp-Tags are no Spring Beans, so the Autowird annotation will be completely ignored, and therefore the field is null.
There are two solution:
use the #Configurable Support. -- But that requires real AspectJ. (I have never tried it for Tags, but I guess it will work for tags like for every other normal class). #see Spring Reference: Chapter 7.8.1 Using AspectJ to dependency inject domain objects with Spring
Extend your tag from the abstract Spring class RequestContextAwareTag. This provides access to the WebApplicationContext via getRequestContext().getWebApplicationContext(). Then you can use the WebApplicationContext to obtain the required beans programmatic.
Try to modify the code like this
public class MyTag extends SimpleTagSupport {
private DocumentBuilder documentBuilder;
#Autowired
public void setBuilder(DocumentBuilder builder) {
this.documentBuilder = builder;
}
#Override
public void doTag() throws IOException {
// documentBuilder is null in here!
}
}
You can use #Autowired if you mark your tag class as Spring bean. But it's stupid, because simple tags not caching by container. Each request creates own tag instance, but wiring happend only conteiner starts.

Why destroy-method is giving error in Spring MVC?

I have destroy method in my bean but it is not showing in the out put. Could you please help me here.
package com.vaannila;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class HelloWorldApp {
public static void main(String[] args) {
AbstractApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Ticket helloWorld = (Ticket) context.getBean("ticket");
helloWorld.setTicketNo("ABC009");
helloWorld.display();
context.close();
}
}
below is my xml file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="helloWorld" class="com.vaannila.HelloWorld">
<property name="message" value="Hello World!"></property>
</bean>
<bean id="ticket" class="com.vaannila.Ticket"
scope="prototype" init-method="init" destroy-method="destroy"/>
</beans>
and Ticket class is below
package com.vaannila;
public class Ticket {
private String ticketNo="";
public String getTicketNo() {
return ticketNo;
}
public void setTicketNo(String ticketNo) {
this.ticketNo = ticketNo;
}
public void display()
{
System.out.println("Your Ticket No. is"+ ticketNo);
}
public void init()
{
System.out.println("Bean is ready You can use it now");
}
public void destroy()
{
System.out.println("Bean is going to destroy");
}
}
The out put is giving for init method but not for destroy method..
If i changed the init-method and destroy-method as default as below it is giving error in destroying the bean called "helloWorld"
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
default-init-method="init" default-destroy-method="destroy">
<bean id="helloWorld" class="com.vaannila.HelloWorld">
<property name="message" value="Hello World!"></property>
</bean>
<bean id="ticket" class="com.vaannila.Ticket"
scope="prototype"/>
</beans>
When a bean is defined as prototype, the bean container creates new instances of this been whenever it is asked for that bean. That's the idea behind prototype-scoped beans.
After they are created, the container gives up responsibility for the bean. It cannot know if you are still holding a reference to it, or when is the moment you drop the last reference. This is true even after the container is closed. (The container is not the garbage collector.) So it cannot possibly know when is the right moment to call the destroy method.
If you need deinitialization for your ticket, you will have to call such a method from your code directly I think (assuming that it makes no sense to have singleton tickets).

Resources