Log Axis Client Requests and Responses Using Spring bean - spring

I have an integration set up with spring using Apache Axis as a SOAP client.
I am able to set up the client-config.wsdd to configure a handler as a class that is outside of the spring context. What I would like to do is configure the handler so that it is within the spring context. Is this possbile?
Here is my current client-config.wsdd
<?xml version="1.0" encoding="UTF-8"?>
<deployment name="defaultClientConfig"
xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<handler name="log" type="java:xxx.xxx.handler.SOAPLogHandler">
</handler>
<globalConfiguration>
<parameter name="disablePrettyXML" value="false"/>
<requestFlow>
<handler type="log"/>
</requestFlow>
<responseFlow>
<handler type="log"/>
</responseFlow>
</globalConfiguration>
<transport name="http" pivot="java:org.apache.axis.transport.http.HTTPSender"/>
</deployment>
I also have the service registered with spring:
<bean id="wsYPSoap" class="xxx.xxx.core.ws.WsYPSoapProxy">
<constructor-arg value="${xxx.service.url}" />
</bean>

I was looking for a way to use Spring bean directly as a handler for Axis client and exactly for the purposes of logging request/response details.
It seems that currently there is no easy and straightforward way to do this.
There is, however, a way to do it by accessing a Spring bean from Axis handler via application root context. There are few issues here:
Axis handlers are instantiated when they are needed as a simple classes (not beans)
handler instances can't rely on existence of any servlet (or, i.e. Faces) context at the time their invoke() method is called
Because of this, you have to place your Spring bean in the root application context. Problem is that you can't access the application context in the usual way (i.e. via ServletContext of FacesContext). Workaround for this is to create your own ApplicationContextAware bean which will store the reference to root application context on app startup for you to use in Axis handler.
Minimal ApplicationContextAware bean implementation example:
public class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext rootAppContext;
#Override
public void setApplicationContext(ApplicationContext ctx) throws BeansException {
rootAppContext = ctx;
}
public static ApplicationContext getApplicationContext() {
return rootAppContext;
}
}
and in application-context.xml declare the bean:
<bean id="appContextProvider" lazy-init="false" class="package.where.the.class.is.ApplicationContextProvider" />
Notice the lazy-init="false" in declaration, this is important. Since this bean is not referenced (or auto-wired) anywhere, Spring will not create the instance of it ever, because Spring uses lazy strategy for bean creation. Setting lazy-init to false makes sure that the bean is created on app startup.
Provided that you have your DB logging bean (implemented by DBLogBean class) properly set up and loaded/created by Spring, you can access it in the Axis handler i.e. like this:
ApplicationContext ctx = ApplicationContextProvider.getApplicationContext();
if (ctx != null) {
DBLogBean bean = (DBLogBean) ctx.getBean("yourDBLogBeanId");
if( bean != null ) {
bean.doLogOrSomething();
}
}
Make sure you check if ApplicationContextProvider.getApplicationContext() returns null or not before fetching DB bean from context. Note now you also must check if ctx.getBean() returns null or not.
If this is not an option (i.e. for some reason you must have the DB bean whenever Axis handler is called), then you have to make sure Axis handler is only ever called after ApplicationContextProvider bean has been created. That topic, however, is out of scope here ;)
NOTE: Creating beans by using lazy-init="false" is not a
preferred way of creating bean instances. Beans should be
auto-wired/referenced by other beans/code and left to Spring to manage
their life cycle. For example, one downside of forcing bean creation
on startup is you can't be sure at which point they have been created
and become available, unless you take extra steps to handle that (or
make sure they are referenced by other code but then, why use
lazy-init="false" in the first place?).

Related

How many instances created for singleton bean referring to a session bean/prototype bean

I have a doubt about the number of instances that will be created in the scenario mentioned below, when Spring Framework is used:
The bean configuration is like this
<bean id="a" class="A">
<property name="b" ref="b"/>
</bean>
<bean id="b" class="B" scope="session"/> or
<bean id="b" class="B" scope="prototype"/>
By default, bean "a" has singleton scope. So there is a singleton bean with a reference to a bean with session scope or prototype scope.
In this case, if there are 2 simultaneous requests to the application, then how many instances of A will be created and how many instances of B will be created?
It will be of great help if anyone can explain how this works.
Thanks,
Divya
The singleton scope
When a bean is a singleton, only one shared instance of the bean will be managed, and all requests for beans with an id or ids matching that bean definition will result in that one specific bean instance being returned by the Spring container.
To put it another way, when you define a bean definition and it is scoped as a singleton, then the Spring IoC container will create exactly one instance of the object defined by that bean definition. This single instance will be stored in a cache of such singleton beans, and all subsequent requests and references for that named bean will result in the cached object being returned.
The session scope
With the above bean definition in place, the Spring container will create a brand new instance of the bean , for the lifetime of a single HTTP Session.
According to Spring framework reference, a different approach needs to be followed in cases where a class which "lives longer"(singleton bean in this case) needs to be injected with another class having a comparatively shorter life-span(session-scoped bean). The approach is different for prototype & singleton scope though.
In your XML, what we want is that the singletonBean instance should be instantiated only once, and it should be injected with sessionBean. But since sessionBean is session-scoped(which means it should be re-instantiated for every session), the configuration is ambiguous(as the dependencies are set at instantiation time and the session scoped value can change later also).
So instead of injecting with that class, its injected with a proxy that exposes the exact same public interface as sessionBean. The container injects this proxy object into the singletonBean bean, which is unaware that this sessionBean reference is a proxy. Its specified by writing this tag in the sessionBean:
<aop:scoped-proxy/>
XML Configuration:
<bean name="singletonBean" class="somepkg.SingletonBean">
<property name="someProperty" ref="sessionBean"/>
</bean>
<bean name="sessionBean" class="somepkg.SessionBean" scope="session">
<aop:scoped-proxy/>
</bean>
When a singletonBean instance invokes a method on the dependency-injected sessionBean object, it actually is invoking a method on the proxy. The proxy then fetches the real sessionBean object from (in this case) the HTTP Session, and delegates the method invocation onto the retrieved real sessionBean object.
Alse please refer this for more info.
Singleton beans with prototype-bean dependencies
Lookup Method Injection
When you use singleton-scoped beans with dependencies on prototype beans, be aware that dependencies are resolved at instantiation time. Thus if you dependency-inject a prototype-scoped bean into a singleton-scoped bean, a new prototype bean is instantiated and then dependency-injected into the singleton bean. The prototype instance is the sole instance that is ever supplied to the singleton-scoped bean.
However, suppose you want the singleton-scoped bean to acquire a new instance of the prototype-scoped bean repeatedly at runtime. You cannot dependency-inject a prototype-scoped bean into your singleton bean, because that injection occurs only once, when the Spring container is instantiating the singleton bean and resolving and injecting its dependencies.
<!-- a stateful bean deployed as a prototype (non-singleton) -->
<bean id="command" class="fiona.apple.AsyncCommand" scope="prototype">
<!-- inject dependencies here as required -->
</bean>
<!-- commandProcessor uses statefulCommandHelper -->
<bean id="commandManager" class="fiona.apple.CommandManager">
<lookup-method name="createCommand" bean="command"/>
</bean>
Lookup method injection is the ability of the container to override methods on container managed beans, to return the lookup result for another named bean in the container. The lookup typically involves a prototype bean as in the scenario described in the preceding section. The Spring Framework implements this method injection by using bytecode generation from the CGLIB library to generate dynamically a subclass that overrides the method.
Refer lookup method injection.
Follow for more detailed example and information.
If we use the way as mentioned in question spring IOC will create always return the same object as singleton, In order to inject prototype bean inside singleton we have two way
1) Lookup method injection
2) Scoped Proxies
see more detail here
First of all, I don't think it is valid to define a bean, both with session and prototype scopes at the same time with the same bean id.
How many instances created for singleton bean referring to a prototype bean?
In your case: one
In general: depending on how you access the bean:
One
#Component
class MySingletonBean{
#Autowired
MyPrototypeBean b;
}
Two
#Component
class MySingletonBean{
#Autowired
MyPrototypeBean b;
#Autowired
MyPrototypeBean bSecondInstance;
}
Or more
#Component
class MySingletonBean{
#Autowired
javax.inject.Provider<MyPrototypeBean> providerOfB;
void accessMultipleInstances(){
MyPrototypeBean bInstance1 = providerOfB.get();
MyPrototypeBean bInstance2 = providerOfB.get();
MyPrototypeBean bInstance3 = providerOfB.get();
//.....
}
}
Note: MyPrototypeBean is considered to have been marked with: #Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE). If you omit it ,then in all the above cases you will reference the same singleton instance.
Regarding session-scoped bean:
One per session.
According to this answer spring will automatically create a proxy which targets different instance depending on the session.
This means that in all the above cases you will get access to the same instance while you are on the same session.
Regarding the provided xml config:
To me it would be more meaningful something like this:
<bean id="a" class="A">
<property name="b" ref="b"/>
<property name="b2" ref="b2"/>
</bean>
<bean id="b" class="B" scope="session"/> or
<bean id="b2" class="B" scope="prototype"/>
In which case you would get one instance per session for b and one and only instance for b2 because you use it from a singleton and you don't use the provider or some similar pattern.

Make a bean unautowireable or that disposes of it self?

We need a spring bean that will either
Prevent the framework from #Autowired -ing it.
or
Once it does its work it destroys itself?
The bean roughly looks like this:
public final class Registrar implements ApplicationListener<SOFrameworkInitializedEvent>
So after it receives this 1 time event do the work and go away. We are using Spring 3.0.7.
Use the autowire-candidate property in the bean definition XML, e.g.:
<bean id="MyBean" class="com.acme.SimpleTestServiceImpl" autowire-candidate="false"/>

overriding bean configuration in spring

Let's say I have two modules. One is core and another is core dependent implementation module.
Core is a jar file for that dependent implementation module war.
In the core I have a bean defined like
<bean id="x" class="com.pokuri.X">
<property name="y" ref="y"/>
<property name="z" ref="z"/>
</bean>
And that class has a method as follows
public class X{
public void doSomeJob(){
.......
}
}
this method is being called from some core classes. Now I need to alter the logic in that doSomeJob() method of X as per my core dependent implementation. So, I create a class like this
public class ExtX extends X{
#override
public void doSomeJob(){
// changed logic
}
}
and defined the bean with same id in another application context xml file like this.
<bean id="x" class="com.pokuri.ExtX">
<property name="y" ref="y"/>
<property name="z" ref="z"/>
</bean>
and we are building application context using contextConfigLocation context parameter in web.xml specifying value as classpath:springfolder.
But in the core logic I am getting core bean instance only(i.e X instance) not ExtX. How can we override that bean definition and let system start using new extend bean definition?
And I heard that with same ID in different application context files will override first loaded bean definition with later loaded bean definition. Is there any priority kind of attribute on bean definition to let ApplicationContext use highest priority one to consider over low priority one when beans with same ID were found.
One way of overriding the bean definition is what you have indicated - to define it with the same id multiple times and the last bean definition with the same id is the one which takes effect. So if you ensure that ExtX is the last one loaded up, it should just work, and to ensure this you can do this in your war file, instead of loading up by saying classpath:springfolder, you can explicitly import the core configuration in your war's Spring config file and then override the bean this way:
<import resource="core-resource.xml"/>
<bean id="x" class="com.pokuri.ExtX">
<property name="y" ref="y"/>
<property name="z" ref="z"/>
</bean>
This will ensure that your overridden bean is the one which takes effect.
There is no priority/order field that you can make use of here though - if you want you can load up all bean definitions of a type by providing Map<String,X> as a parameter, and sort it by expecting an order property and use it that way, but there is lot more work to it.
A second approach is described here: Overriding the bean defined in parent context in a child context

Why is there a need to specify the class in both the xml file and in the getBean() method in Spring

This might be an obvious but I'm having a hard time understanding why we need to define the class of a bean in two places....
From the spring reference manual...
...
<bean id="petStore"
class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl">
<property name="accountDao" ref="accountDao"/>
<property name="itemDao" ref="itemDao"/>
<!-- additional collaborators and configuration for this bean go here -->
</bean>
// retrieve configured instance
PetStoreServiceImpl service = context.getBean("petStore", PetStoreServiceImpl.class);
Shouldn't the xml fine be enough for the container to know the class of petStore?
You can use the following method:
context.getBean("petStore")
However, as this returns a java.lang.Object, you'd still need to have a cast:
PetStoreServiceImpl petstore = (PetStoreServiceImpl)context.getBean("petStore");
However, this could lead to problems if your "petStore" bean is not actually a PetStoreServiceImpl, and to avoid casts (which since the advent of Generics are being seen as a bit dirty), you can use the above method to infer the type (and let's spring check whether the bean you're expecting is really of the right class, so hence you've got:
PetStoreServiceImpl service = context.getBean("petStore", PetStoreServiceImpl.class);
Hope that helps.
EDIT:
Personally, I would avoid calling context.getBean() to lookup methods as it goes against the idea of dependency injection. Really, the component that uses the petstore bean should have a property, which can then be injected with the correct component.
private PetStoreService petStoreService;
// setter omitted for brevity
public void someotherMethod() {
// no need for calling getBean()
petStoreService.somePetstoreMethod();
}
Then you can hook up the beans in the application context:
You could also do away with the configuration via XML and use annotation to wire up your beans:
#Autowired
private PetStoreService petStoreService;
As long as you've got
in your spring context, the "petStore" bean defined in your application context will automatically be injected. If you've got more than one bean with the type "PetStoreService", then you'd need to add a qualifier:
#Autowired
#Qualifier("petStore")
private PetStoreService petStoreService;
There's no requirement to specify the class in the getBean() method. It's just a question of safety. Note there's also a getBean() that takes only a class so that you can just look up beans by type instead of needing to know the name.

Apply dynamic properties to a bean at runtime

Assume I have a bean DialogBox, with properties for height and width:
public class DialogBox {
int x;
int y;
...
}
In my applicationContext.xml I would define properties as reasonable defaults:
<bean id="dialogbox" class="DialogBox">
<property name="x" value="100"/>
<property name="y" value="100"/>
</bean>
We have multiple clients that use the dialogBox bean, and each wants a custom value for x and y. One route we have discusses is having multiple properties files, one for each client, and have the client id map to the proper file, for example client 123 would map to dialogbox_123.properties:
dialogbox_123.properties:
x=200
y=400
Then at runtime when the bean is requested, spring would look to see if a custom properties file exists for the client, and use those properties, otherwise use the defaults. I am aware of the PropertyOverrideConfigurer, but AFAIK this only works when the context is started so will not work for our purposes. Is there an existing facility in spring to achieve this, or can someone recommend another way?
Use FactoryBean (as already suggested) to customize instantiation.
set scope="prototype" on the bean, so that each time an instance is required, a new one should be created.
In case you want to inject the prototype bean into a singleton bean, use lookup-method (Search for lookup-method here)
I'm not sure if this would fit your case though. Another suggestion would be:
In #PostConstruct methods of your various "clients" set the properties as desired on the already injected dialog window. Like:
public class MyDialogClient {
#Autowired
private Dialog dialog;
#PostConstruct
public void init() {
dialog.setWidth(150); //or read from properties file
dialog.setHeight(200);
}
...
}
Again, in this case, you can play with the scope atrribute.
Take a look at the Spring OSGi Compendium services, they've got a property manager called "managed-properties", which allows you not only to update the properties at runtime, but while the application is running if you select the "container-managed" update strategy.
If I understood the question, you can use a FactoryBean to customize bean creation logic in Spring.

Resources