Injecting a component in an aspect in a non-spring environment - spring

We have an aspect, named BusinessRuleAspect, in our code base that is used on the client side and on the server side of the project. On the server side we have spring, and the component is injected from the application context:
<bean id="businessRuleAspect" class="com.fugro.gwf.domain.rules.aspects.BusinessRuleAspect"
factory-method="aspectOf">
<property name="businessRuleManager" ref="businessRuleManager" />
</bean>
The question: on the client side we don't have spring, what is the best way of injecting the businessRuleManager component in the aspect in such a case?

Without understanding the exact internals of what you are doing (or perhaps rather why), what you can do is something like the following in your aspect. (Not the cleanest option, but at least a starting point)
If BusinessRuleManager is a singleton, how do you instantiate it/retrieve it from elsewhere in the non-Spring application? Or is it used only within the aspect?
after(PersistentObject persistentObject) :
persistentObjectPropertySetter(persistentObject)
{
if(businessRuleManager!=null)
businessRuleManager = BusinessRuleManager.getInstance();
if(businessRuleManager!=null)
{
businessRuleManager.execute(persistentObject,
thisJoinPoint.getSignature().getName());
}
}
And in your BusinessRuleManager:
class BusinessRuleManager{
.......
static private BusinessRuleManager instance;
static public BusinessRuleManager getInstance(){
if( instance == null )
instance = new BusinessRuleManager();
return instance;
}
.......
}
This should allow you to use the mix of Spring injection as well as a non-spring container.

In reply to your question: "If BusinessRuleManager is a singleton, how do you instantiate it/retrieve it from elsewhere in the non-Spring application?".
Here is the very concrete code that does it:
BusinessRuleManager businessRuleManager = ContextInjectionFactory.make(BusinessRuleManagerImpl.class, context);
context.set(BusinessRuleManager.class, businessRuleManager);
This construct puts an instance of our manager in the eclipse RCP context, ready to be injected in all kinds of other eclipse RCP components. This means that, borrowing your code we would get something like:
after(PersistentObject persistentObject) : persistentObjectPropertySetter(persistentObject) {
if(businessRuleManager==null) {
Bundle bundle = FrameworkUtil.getBundle(BusinessRuleManager.class);
BundleContext bundleContext = bundle.getBundleContext();
IEclipseContext eclipseCtx = EclipseContextFactory.getServiceContext(bundleContext);
businessRuleManager = eclipseCtx.get(BusinessRuleManager.class);
}
if(businessRuleManager!=null) {
businessRuleManager.execute(persistentObject, thisJoinPoint.getSignature().getName());
}
}
I tried to get it working, but failed miserably. The main problem is that the aspect lives in a domain module, which is shared between server and client. It's very difficult (and maybe even not desirable) to use the client side dependency injection framework ("RCP E4") in the shared code base of domain.

Related

What is the correct way in Spring WS to configure own replacement of DefaultMethodEndpointAdapter?

We have the situation we need to read the parameters sent to the Spring Ws endpoint before the endpoint method is reached. For this purpose we made a descendant of the class
org.springframework.ws.server.endpoint.adapter.DefaultMethodEndpointAdapter, for example in this way:
public class MyMethodEndpointAdapter extends DefaultMethodEndpointAdapter {
#Override
protected Object[] getMethodArguments(
MessageContext aMessageContext, MethodEndpoint aMethodEndpoint) throws Exception {
Object[] locResult = super.getMethodArguments(aMessageContext, aMethodEndpoint);
MethodParameter[] parameters = aMethodEndpoint.getMethodParameters()
Object locPayloadObject = null;
for (int i = 0; i < parameters.length; i++) {
if (parameters[i].hasParameterAnnotation(RequestPayload.class)) {
locPayloadObject = locResult[i];
break;
}
}
// ... some custom code here dealing with resolved request payload object
}
}
The solution works well, but the real issue here is the configuration. We use the XML configurations to make the things more transparent and manageable, so we defined in the configuration file for web service following settings:
<bean id="defaultMethodEndpointAdapter"
class="somepackage.MyMethodEndpointAdapter"/>
but still after specifying it in this way, the original implementation DefaultMethodEndpointAdapter is instantiated too. Then there are two adapters which are checked and it depends on the order of the configuration loading, which one gets instantiated first - and which one then gets the request when the correct handling instance is evaluated. Even the definition of the bean with name instead of Id
<bean name="defaultMethodEndpointAdapter"
class="somepackage.MyMethodEndpointAdapter"/>
did not help.
Going through with debugger I found out, there is generated the bean name for instantiation of the singletons, named org.springframework.ws.server.endpoint.adapter.DefaultMethodEndpointAdapter#0 which is used by the instantiated default instance. So, finally, after specification of the bean definition like
<bean id="defaultMethodEndpointAdapter"
name="org.springframework.ws.server.endpoint.adapter.DefaultMethodEndpointAdapter#0"
class="somepackage.MyMethodEndpointAdapter"/>
We were able to bring Spring to the situation, only one (our) adapter is instantiated and we get the expected behavior.
But this seems to be ugly to us, the dynamically generated name
org.springframework.ws.server.endpoint.adapter.DefaultMethodEndpointAdapter#0 seems to be a unstable way how to reference the replaced adapter implementation.
Is there some better way how to do it to bring Spring to the situation not to instantiate the default adapter at all?

Spring prototype following prototype design pattern

Spring provides bean scope as "Prototype". Means whenever bean is required in application, Spring container will create a fresh/new instance of bean.
Does is follow prototype design pattern also?
Does it create object only once and in subsequent request calls clone() method on created object to create new object?
Also if someone can provide example of prototype in JDK, Spring, Hibernate or any J2EE framework.
No spring does not use cloning to create prototype scoped instances.
Below is the code snippet taken from AbstractBeanFactory.doGetBean() function:
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
#Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
The createBean method call boils down to below code:
BeanUtils.instantiateClass(constructorToUse);
Spring does not use the Prototype Pattern, it uses reflection.
Plus, in order to use clone() it would have to subclass somehow a bean, because clone() is protected, so it does not use clone() either.
Here is a code fragment from
org.springframework.beans.factory.support.SimpleInstantiationStrategy
where you can see the use of java.lang.reflect.Constructor and java.lang.Class reflection method:
public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {
if (beanDefinition.getMethodOverrides().isEmpty()) {
Constructor<?> constructorToUse;
synchronized (beanDefinition.constructorArgumentLock) {
constructorToUse = (Constructor<?>) beanDefinition.resolvedConstructorOrFactoryMethod;
...
constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
...
}
...
}
...
}
So the term prototype is used to suggest that at every call to getBean, you'll get a new instance with the same properties. This is more than a simple call to a constructor however, because you'll get a bean with all dependencies wired and other properties set, so in a sense it is a prototype. Or at least it fits the concept very well.
I have not dug into Spring source code, but I think Beans with prototype scope in Spring are not created using clone() method because it is not mandatory to implement the Cloneable interface for those beans.
Moreover, suppose it is creating them using clone(). It would then be dangerous if someone is expecting deep copy instead of shallow copy.
You can always test it and find the answer.
No. Spring scopes such as prototype or singletone do not follow strictly design patterns. The naming of scopes was used to intuitively suggest behavior container provides.
This way you can have a "singleton" pattern within the container and create another object outside of the container. Similarly "prototype" pattern does not have to implement "clone" functionality.
You may want to look into this link as well: Singleton design pattern vs Singleton beans in Spring container
More elaborate explanations here:
https://springframework.guru/gang-of-four-design-patterns/prototype-pattern/

Persistence in an OSGi environment using Datanucleus JDO and blueprints

I am trying to do persistence in an OSGi environment (Karaf running Felix) with as much modularity as possible. I chose JDO for its added features (mainly fetch groups) instead of JPA. The implementation being Datanucleus. I use Maven to build the whole project.
As I didn't have any prior experience with JDO or OSGi it was quite a challenge to make either of them work. I am presently able to do JDO persistence in a Java SE environment (unit tests work without a problem) and I know how to provide services in an OSGi environment using the blueprint container. But I am not able to make those two things work together. I am having classloading issues.
I was not able to build even a simple application that would be able to do JDO persistence on Karaf (I tried following this tutorial but it uses Spring DM and I was unable to rewrite it to use OSGi blueprint instead).
What I am most confused about is:
What value should I set the datanucleus.primaryClassLoader property to?
What class loader to pass as an argument to the JDOHelper.getPersistenceManagerFactory method?
What packages to explicitly import using the maven-bundle-plugin? (looks like at least javax.jdo, org.datanucleus.api.jdo and org.osgi.framework might be required)
What do the other bundles need besides a reference to PersistenceManagerFactory?
Additionally:
Is it possible to separate the persistence info from the value classes? If I understand it correctly, that would only be possible if using runtime enhancement which would be very complicated if at all doable.
Is it possible to define interdependent persistence capable classes in multiple bundles? Such as having Users defined in one bundle and their Addresses in another?
I would be extremely grateful for an example of a simple multi-bundle project that takes care of persistence using only Datanucleus, JDO API and OSGi blueprint.
Thank you
I can only provide some basic hints about getting JDO/datanucleus to work on top of Karaf.
As pointed in the tutorial, you'll need to extend the LocalPersistenceManagerFactoryBean, implementing as well the BundleContextAware interface.
The key point here is classloading: the LocalPersistenceManagerFactoryBean expects all classes to be loaded by one single classloader, which isn't the case in a OSGi runtime.
In order to get it working you'll need to:
Explicitly import the org.datanucleus.api.jdo in your manifest file.
The datanucleus.primaryClassLoader property could be set to the same classloader you'll pass to the JDOHelper.getPersistenceManagerFactory method. The classloader is the one used by the org.datanucleus.api.jdo bundle (see example below)
You'll need to set the datanucleus.plugin.pluginRegistryClassName property to org.datanucleus.plugin.OSGiPluginRegistry.
When stopping/uninstalling your bundle, you'll have to refresh the javax.jdo bundle for avoiding errors when re-creating the persistence manager factory (check this question on the subject)
Sample custom LocalPersistenceManagerFactoryBean:
public class OSGiLocalPersistenceManagerFactoryBean
extends LocalPersistenceManagerFactoryBean implements BundleContextAware {
public static final String JDO_BUNDLE_NAME = "org.datanucleus.api.jdo";
public static final String JDO_PMF_CLASS_NAME = "org.datanucleus.api.jdo.JDOPersistenceManagerFactory";
private BundleContext bundleContext;
#Override
protected PersistenceManagerFactory newPersistenceManagerFactory(String name) {
return JDOHelper.getPersistenceManagerFactory(name, getClassLoader());
}
#Override
protected PersistenceManagerFactory newPersistenceManagerFactory(Map props) {
ClassLoader classLoader = getClassLoader();
props.put("datanucleus.primaryClassLoader", classLoader);
if (FrameworkUtil.getBundle(this.getClass()) != null) { // running in OSGi
props.put("datanucleus.plugin.pluginRegistryClassName", "org.datanucleus.plugin.OSGiPluginRegistry");
}
PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory(props, classLoader);
return pmf;
}
private ClassLoader getClassLoader() {
ClassLoader classLoader = null;
Bundle thisBundle = FrameworkUtil.getBundle(this.getClass());
if (thisBundle != null) { // on OSGi runtime
Bundle[] bundles = bundleContext.getBundles();
for (Bundle bundle : bundles) {
if (JDO_BUNDLE_NAME.equals(bundle.getSymbolicName())) {
try {
classLoader = bundle.loadClass(JDO_PMF_CLASS_NAME).getClassLoader();
} catch (ClassNotFoundException e) {
// do something fancy here ...
}
break;
}
}
} else { // on Java runtime
classLoader = this.getClass().getClassLoader();
}
return classLoader;
}
#Override
public void setBundleContext(BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
}

How to 'get' the spring prototype beans cleanly?

I would like my other classes to interact with my domain's interfaces rather than implementation, and i would like to avoid hardcoding the implementation in the code, such as this example :
public void addToMyList(String s, int i) {
DomainModel model = new DefaultDomainModelImpl(); // it's hardcoding the implementation here
model.setName(s).setAge(i);
myList.add(model);
}
If i use spring container, with the prototype scope, i can use something like :
// <bean id="myDomainBean" scope="prototype" class="my.package.domain.MyDomainImpl" />
DomainModel myDomainModel = springContext.getBean("myDomainBean");
But i would like to avoid accessing springContext explicitly in my code.
I wonder what's the clean way to do this ?
Im currently thinking of creating a factory implementation for each domain implementation, and autowire the factory to create the beans, but that means different implementations of my domain will have different implementations of the factory also.
Please share your opinions, thank you !
Im currently thinking of creating a factory implementation for each domain implementation, and autowire the factory to create the beans, but that means different implementations of my domain will have different implementations of the factory also.
That is not 100% correct. You can have a factory that take the Interface (class) of the Domain objects that needs to be create. You can inject that factory in you class.
So you will get all the requriements you asked for:
no hard coded new
the domain object code has no dependence to spring
you only have one factory class and one factory method.
example
#Inject
MyStrangeSpringHiddingFactory myStrangeSpringHiddingFactory;
DomainModel myDomainModel = this.myStrangeSpringHiddingFactory.
createInstanceOf(DomainModel.class);
class MyStrangeSpringHiddingFactory implements MyStrangeSpringHiddingFactory {
#Inject
ApplicationContext springContext:
public <T> createInstanceOf(Class<T> clazz) {
return springContext.getBean(clazz);
}
}
This are only my thoughts, because I do not know your use case: Do you really need such in abstraction? Do you really have a domain model where a domain class have several subclasses that need a factory.

Grails Dependency Injection Outside of Services?

I have a Grails application that needs to run a strategy that will likely be swapped out over time. I know Spring underlies Grails, so I was wondering if I had access to Spring's IoC container so that I could externalize the actual dependency in an xml file (note: I have never actually done this, but just know of it, so I may be missing something). My goal is to be able to do something like the following:
class SchemaUpdateService {
public int calculateSomething(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
IStrategy strat = (IStrategy) ctx.getBean("mystrat");
}
}
And then map the appropriate implementation in the beans.xml file. I assume this is supported in Grails. Does anyone have any documentation on how this would work? Do I really just need the Spring IoC library and it will just work? Thanks!
You define your beans in resources.xml or resources.groovy. The grails documentation is very clear about how to access the Spring application context.
You can access the application context from any Grails artefact using
ApplicationContext ctx = grailsApplication.mainContext
You can then use this to retrieve whichever beans you're interested in:
IStrategy strat = (IStrategy) ctx.getBean("mystrat")
In classes that don't have access to grailsApplication, you could use a helper such as the following to access the application context and the beans therein
class SpringUtils {
static getBean(String name) {
applicationContext.getBean(name)
}
static <T> T getBean(String name, Class<T> requiredType) {
applicationContext.getBean(name, requiredType)
}
static ApplicationContext getApplicationContext() {
ApplicationHolder.application.mainContext
}
}
However, this should only be necessary if you need to retrieve different implementations of the same bean at runtime. If the required bean is known at compile-time, just wire the beans together in resources.xml or resources.groovy
First of all, you want to define your strategy in your grails-app/conf/spring/resources.groovy:
beans = {
myStrat(com.yourcompany.StrategyImpl) {
someProperty = someValue
}
}
Then, you simply def the a property with the same name into your service:
class SomeGrailsService {
def myStrat
def someMethod() {
return myStrat.doSomething()
}
}
In any Grails artefact (such as services and domain classes), Grails will automatically give the myStrat property the correct value. But don't forget, in a unit test you'll have to give it a value manually as the auto-wiring does not happen in unit tests.
Outside of a Grails artefact, you can use something like:
def myStrat = ApplicationHolder.application.mainContext.myStrat
In Grails 2.0, Graeme et al are deprecating the use of the *Holder classes (such as ApplicationHolder and ConfigurationHolder), so I'm not quite sure what the Grails 2.0 approach would be...

Resources