NotSerializableException in JSF when using Spring AOP
I'm currently running into a problem using a combination of JSF 2 and Spring 3 AOP.
The application is designed as a classic three-layer architect (Web, Service, Database). Thus, the Spring Service manages the JSF Beans Service Beans, which represents the business logic.
Managed Beans looks like this:
@Named("startPage")
@Scope("view")
public class ManagedBean implements Serializable {
@Inject
private ServiceBeanA serviceBeanA;
public void someMethod() {
serviceBean.doSomeBusinessLogic();
}
Since this Bean is scoped, it implements Serializeable as well as instance variables (in this case ServiceBeanA), as described here: Should JSF Bean support be serializable?
So far, everything is working as expected.
Now Id like to intercept a call to a business method declared in business services. This is how I created an Aspect that does some basic logging and de-caste it in Spring config:
<bean id="aspectLogging" class="my.package.AspectLogging" />
<aop:config>
<aop:aspect ref="aspectLogging">
<aop:pointcut id="serviceMethodInvocation" expression="execution(* my.services.ServiceBeanA.doSomeBusinessLogic())" />
<aop:around pointcut-ref="serviceMethodInvocation" method="performLogging" />
</aop:aspect>
</aop:config>
Aspect:
public class AspectLogging {
public Object performLogging(ProceedingJoinPoint pjp) throws Throwable {
Object toReturn = null;
System.out.println(">>>>"+ pjp.getSignature().toLongString());
toReturn = pjp.proceed();
return toReturn;
}
}
And now the problem arises:
SCHWERWIEGEND: Exiting serializeView - Could not serialize state: org.springframework.aop.aspectj.AspectJPointcutAdvisor
java.io.NotSerializableException: org.springframework.aop.aspectj.AspectJPointcutAdvisor
I found two identical problem descriptions in Springsource (no solution unfortunately)
http://forum.springsource.org/showthread.php?87428-AspectJPointcutAdvisor-not-Serializable http://forum.springsource.org/archive/index.php/t-57602.html
Of course, I just might not be able to use the Aspect orientation, but the same problem can occur with any other third party library.
What I did was markup an instance variable where the business service is temporary.
public class ManagedBean implements Serializable {
@Inject
private transient ServiceBeanA serviceBeanA;
public void someMethod() {
serviceBean.doSomeBusinessLogic();
}
This works fine until the session is restored (deserialized). Of course the variable (serviceBeanA) is null after deserialization. I can set up a web container (like Tomcat) and not serialize sessions, but this app runs in the cloud, so I am not responsible for setting up the servers.
The only idea I came across was to use the basic Java Serialization features by providing
private synchronized void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException
and
private synchronized void writeObject(ObjectOutputStream s) throws IOException
in a managed Bean.
private synchronized void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
s.defaultReadObject();
ApplicationContext context = new ClassPathXmlApplicationContext("services.spring-config.xml", "database.spring-config.xml");
this.ServiceBeanA = (ServiceBeanA) context.getBean("serviceBeanA");
}
private synchronized void writeObject(ObjectOutputStream s) throws IOException {
s.defaultWriteObject();
}
These solutions work, but it seems like a very clunky solution. I have to repeat pretty much the same code in every managed Bean that uses the Service Beans. In addition, managed Beans are tightly coupled to Spring in this way, as they import the Springs application context to restore service variables.
Can anyone think of a better architectural approach? Thanks in advance!
source to share
No one has answered this question yet
Check out similar questions: