5

i am using spring 3 with JSF 2 and i replaced JSF managed beans with spring beans, by adding on top of bean:

@Component("mybean")
@Scope("session")

and in my bean i am autowiring a spring service (which was declared with the annotation @service)

well, everything works fine with the service, but when i tried to stop tomcat 6, i am getting this exception with my spring service

java.io.NotSerializableException

any ideas why i am getting this exception, and how to solve it.

UPDATE:

after making my service implements serializable, sometimes i am getting following exception:

java.lang.IllegalStateException: Cannot deserialize BeanFactory with id org.springframework.web.context.WebApplicationContext:/spring_faces: no factory registered for this id
    at org.springframework.beans.factory.support.DefaultListableBeanFactory$SerializedBeanFactoryReference.readResolve(DefaultListableBeanFactory.java:972)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at java.io.ObjectStreamClass.invokeReadResolve(ObjectStreamClass.java:1061)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1762)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1947)
    at java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:480)
    at org.springframework.aop.support.AbstractBeanFactoryPointcutAdvisor.readObject(AbstractBeanFactoryPointcutAdvisor.java:98)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1849)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
    at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1667)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1323)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1947)
    at java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:480)
    at org.springframework.aop.framework.AdvisedSupport.readObject(AdvisedSupport.java:550)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1849)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1947)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1871)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1947)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1871)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1947)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1871)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1947)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1871)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1947)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1871)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1947)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1871)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
    at org.apache.catalina.session.StandardSession.readObject(StandardSession.java:1496)
    at org.apache.catalina.session.StandardSession.readObjectData(StandardSession.java:998)
    at org.apache.catalina.session.StandardManager.doLoad(StandardManager.java:394)
    at org.apache.catalina.session.StandardManager.load(StandardManager.java:321)
    at org.apache.catalina.session.StandardManager.start(StandardManager.java:648)
    at org.apache.catalina.core.ContainerBase.setManager(ContainerBase.java:446)
    at org.apache.catalina.core.StandardContext.start(StandardContext.java:4631)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1057)
    at org.apache.catalina.core.StandardHost.start(StandardHost.java:840)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1057)
    at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:463)
    at org.apache.catalina.core.StandardService.start(StandardService.java:525)
    at org.apache.catalina.core.StandardServer.start(StandardServer.java:754)
    at org.apache.catalina.startup.Catalina.start(Catalina.java:595)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)

please advise.

Mahmoud Saleh
  • 33,303
  • 119
  • 337
  • 498

4 Answers4

5

Looking at the error, It looks like tomcat is trying to serialize the entire spring context, I think it might be due to the fact that your are implementing Serializable on Service. I was thinking may be you need to do this, I don't know JSF that well but my understanding of scoped beans makes me think, You might need some thing like this

    @Component
    @Scope(proxyMode=ScopedProxyMode.TARGET_CLASS, value="session")
    public class MyBean implements Serializable
    {
       //no need to implement serializable on service
       @Autowired(required=true)
       private MyService service;
    }
Prasanna Talakanti
  • 2,354
  • 1
  • 16
  • 16
  • what does the following means proxyMode=ScopedProxyMode.TARGET_CLASS, and what's the need for required=true in autowiring – Mahmoud Saleh Sep 22 '11 at 09:30
  • when i tried that, i am getting exception: org.springframework.aop.framework.AopConfigException: Cannot proxy target class because CGLIB2 is not available. Add CGLIB to the class path or specify proxy interfaces. – Mahmoud Saleh Sep 22 '11 at 11:07
  • You don't need required is true (just instructing container that this dependency cannot be ignored) it is the default, You need this dependency cglib cglib2.2.2, Either you can use JDK or CGLIB to create proxy's if you put CGLIB in classpath spring use CGLIB to create the prxoy. – Prasanna Talakanti Sep 22 '11 at 12:59
  • ok i will try that, but you didn't tell me, what the code means: proxyMode=ScopedProxyMode.TARGET_CLASS – Mahmoud Saleh Sep 23 '11 at 17:12
  • Read this section 3.4.4.5. from the documentation below http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-factory-scopes-other-injection – Prasanna Talakanti Sep 23 '11 at 17:27
  • well, after adding this dependency, i got two exceptions: java.lang.IllegalStateException: Cannot deserialize BeanFactory with id org.springframework.web.context.WebApplicationContext:/my_app: no factory registered for this id – Mahmoud Saleh Sep 25 '11 at 09:17
  • and : java.lang.NoClassDefFoundError: org/objectweb/asm/Type – Mahmoud Saleh Sep 25 '11 at 09:17
  • oh, fixed it, i was needing the dependency: asm asm 3.3.1 – Mahmoud Saleh Sep 25 '11 at 09:32
4

You get this exception because the class does not implement Serializable. Tomcat serializes currently running HttpSession objects including all its attributes to disk whenever it is about to restart/redeploy, so that they are revived after the cycle. Session scoped objects are stored as attributes of the HttpSession, hence they need to implement Serializable to survive the restart/redeploy as well.

If you would like to make them Serializable, then implement it accordingly:

public class YourSpringService implements Serializable {}

Otherwise, just ignore the exception or turn off serializing sessions to disk in Tomcat's config.

Note that the same story also applies to JSF view/session scoped beans.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • so the issue is that my spring bean (alternative to jsf managed bean) is session scoped and implements Serializable, any spring service used in this bean must implement Serializable too ? – Mahmoud Saleh Sep 21 '11 at 16:06
  • 1
    If you need them to be serializable, then yes. Otherwise mark them transient. I only don't guarantee that Spring will reinject them after reviving, this is beyond my knowledge (I don't do Spring). – BalusC Sep 21 '11 at 16:10
  • I think the issue is @autowired of service, I think if you make the service a transient then service will not be serialized (since you can't really serialize it any way, It is just a prox) – Prasanna Talakanti Sep 21 '11 at 17:29
  • what do you mean guys by making service transient ? – Mahmoud Saleh Sep 21 '11 at 18:09
  • @Jsword: use `transient` keyword. E.g. `private transient Foo foo;`. This skips the property from being serialized. – BalusC Sep 21 '11 at 18:17
  • so you suggest that i shouldn't make the service implements serializable, and make it transient is better ? – Mahmoud Saleh Sep 22 '11 at 09:32
  • when i use transient, i get nullPointerException with the service when i stop and start my server. – Mahmoud Saleh Sep 22 '11 at 11:04
  • to make it work fine i have to make all layers implements serialziable service/dao/entity, and i don't know if that a good behavior or have costs or what ? – Mahmoud Saleh Sep 22 '11 at 11:31
2

Well, finally i was able to make it work fine as follows:

1- The Service:

@Service
@Scope("singleton")
public class PersonService{

}

2- The Spring Managed Bean:

 @Component("person")
   @Scope("session")
   public class PersonBean implements Serializable{

   @Inject
   private PersonService personService;

   }

waiting for your feedback.

Mahmoud Saleh
  • 33,303
  • 119
  • 337
  • 498
1

I had to use readObject() + static ApplicationContext hack to solve the issue:

@Component
@Scope(value = SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class FlashMessages implements Serializable {    

    @Autowired
    transient private SomeBean someBean;

    private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
        ois.defaultReadObject();
        // restore someBean field on deserialization
        SpringUtils.getContext().getAutowireCapableBeanFactory().autowireBean(this);
    }

}

@Component
public class SpringUtils implements ApplicationContextAware {

    static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringUtils.applicationContext = applicationContext;
    }

    public static ApplicationContext getContext() {
        return applicationContext;
    }

}
vladimir83
  • 509
  • 3
  • 10