Off late, I am involved in porting some screens of an application built using Wicket + Spring + Hibernate
to Laszlo + Spring + Hibernate. To suggest that I would have been hesitant about it would not be
very far from truth..mainly because I love wicket.
However, as I checked out some sites built using Laszlo , my interest really grew.
In the past few days, I have playing around with javarpc part of Laszlo – since it gives
one the ability to use the service layer developed as is – all that is required is to build
a pojo which will access the service and return a list of java objects for example.
But as I started developing in OpenLaszlo javarpc approach, I thought I hit a dead
end regarding the approach to take to get my spring managed beans.After all that
was critical to invoke the service layer calls.Keep in mind that my remote pojo
was just really an ordinary java object.
The solution occurred when I was discussing this with my lead and it came to light
that Spring 2.0 has a lot of new features like @Configurable approach. However this
simply uses AspectJ under the hood. Also this approach suited me because
as we all know its all about getting beans injected instead of pulling explicitly.
With this in mind, I decided to implement using AspectJ. AspectJ is really powerful.
One is able to write fine-grained expressions to capture joinpoints.
So this is code that I finally got to use to make my javarpc approach working…
The base handler which stores reference to service – this is what needs to get injected…public abstract class BaseRemoteHandler implements Serializable { private IService service;
private String serviceNameInContextFile;
public IService getService() {
return service;
}
public void setService(IService serive) {
this.service = serive;
}public abstract String getServiceNameInContextFile() ;
public void setServiceNameInContextFile(String serviceNameInContextFile) {
this.serviceNameInContextFile = serviceNameInContextFile;
}}
This is the ACTUAL remote handler – which laszlo will access
public class AttributeRemoteHandler extends BaseRemoteHandler{public AttributeRemoteHandler() {
super();
}@Override
public String getServiceNameInContextFile() {
return “attributeServiceManager”; // The name of service in the context file used by Spring.
}public List getListAtrributes(int start,int count,String column,boolean ascending){
return ((AttributeService)getService()).getSortedAttributes(0, count, column, ascending);
}}
Finally THE aspectj ASPECT – which does the magic required ….
public aspect ServiceInjector {public pointcut instanceIdentifier(): execution(*.new(..));
before(): instanceIdentifier(){
Object thisobject = thisJoinPoint.getThis();
if(thisobject instanceof BaseRemoteHandler){
BaseRemoteHandler basehandler =((BaseRemoteHandler)thisobject);
String managedServiceName = basehandler.getServiceNameInContextFile();
if(managedServiceName == null){
throw new IllegalStateException(“Serive name not implemented in handler “+basehandler.getClass().getName());
}
org.springframework.context.ApplicationContext context =
ApplicationContextFetcher.getContext(); // ApplicationContextFetcher – My Util class to get ApplicationContextObject service = context.getBean(managedServiceName);
basehandler.setService((IService)service);}
}
}
Posted by karthik on February 1, 2008 at 8:17 pm
Nope I think this could be better. Your handlers don’t look clean enough to me. Here are some of the reasons –
1)There is a “String” identifier in there and java is about strong types.
2)There is an explicit cast to get to the spring service in your handlers.
3)The BaseRemoteHandler leaks the implementation details through this method-
public abstract String getServiceNameInContextFile() ;
//Why should the handlers know that its dependencies are coming from Spring?
The handlers could simply be written like this instead –
//place all your handlers in this package
package com.yourcompany.handlers;
class AttributeRemoteHandler {
AttributeService service;
public List getListAtrributes(){
return service.getListAtrributes();
}
public void setAttributeService(AttributeService srvc)[
this.service = srvc;
}
}
public aspect ServiceInjector {
public pointcut instanceIdentifier():
execution(com.yourcompany.handlers.*.new(..));
after(): instanceIdentifier(){
Object thisobject = thisJoinPoint.getThis();
// ApplicationContextFetcher – My Util class to get
ApplicationContext context
=ApplicationContextFetcher.getContext();
context.lookforApiToResolveExistingbeanDependency(thisObject);
}
}
Your handlers will feel a lot more natural that way. If you can’t place all your handlers in the same package, use regex to specify the pointcut.
Posted by karthik on February 1, 2008 at 9:31 pm
To begin with, I’m not too sure if I would be comfortable with a pointcut declaration like this –
public pointcut instanceIdentifier(): execution(*.new(..));
it is intercepting *every* object instantiation – whereas you are interested in only certain classes (as it is clear in the advice).
There is a very high chance that this pointcut will degrade the application performance.
Posted by sbelur on February 2, 2008 at 2:46 pm
Generally, this argument is accepted.
The only reason why i did this was that of ease of impl.
A new handler has to just override the get method and return
the names – which anyone has to know if he enters in ctx files.
So if i have 3/4 service dependecies, I dont have to write
3/4 fields. If there is aspelling error, spring will anyhow thro
exception. May not be best approach tho.
Posted by sbelur on February 2, 2008 at 2:49 pm
>> “To begin with, I’m not too sure if I would be comfortable with a pointcut declaration like this –
public pointcut instanceIdentifier(): execution(*.new(..));”
This was just meant to illustrate the pointcut. In fact
I had implemented the actual stuff using complete packages.
There is an even better way than simply putting package name
We can use . +.new(..) notation
to directly capture subclasses of base handler.
WOW. AspectJ is really cool -:)
-swaroop
Posted by sbelur on February 2, 2008 at 2:52 pm
>> We can use . +.new(..) notation
>> to directly capture subclasses of base handler.
>> WOW. AspectJ is really cool -:)
oops , some text got caught off.
somepackage.baseclass+.new(..)
Posted by Jon on April 9, 2008 at 5:14 pm
You have this line
org.springframework.context.ApplicationContext context =
ApplicationContextFetcher.getContext(); // ApplicationContextFetcher – My Util class to get
Can you post the source for the ApplicationContextFetcher?
Posted by sbelur on April 10, 2008 at 4:50 am
Jon,
I do not have the source with me right now..
This is what I did..
Build a ClasspathXMLApplicationContext and store the reference in a sinlgeton class. Make sure the Context object is built only once. You can even build a FileSystem context object…you can chhose….No big deal…Just implement a singleton class