HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaspringMinor

Spring autowiring in managed beans with support for serialization - is this safe?

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
springmanagedthiswithserializationbeansforsafeautowiringsupport

Problem

Im trying to solve two problems I see with JSF2 and Spring.
First

  • @Autowired in @ManagedBean does not work



  • Nor does @ViewScoped with @Controller



  • @ManagedProperty is not type safe and requires setter



Second

  • You can not serialize singleton spring beans without hassle



  • Managed beans must be serializable so the container can serialize the session



So I enabled @Autowired in managed beans and fixed serialization with this common base class which all managed beans (at least @SessionScoped and @ViewScoped ones) derive from.

public abstract class Handler implements Serializable {
    private static final long serialVersionUID = 1L;

    @PostConstruct
    private void init() {
        Spring.appCtx.getAutowireCapableBeanFactory().autowireBean(this);
    }

    private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
        ois.defaultReadObject();
        Spring.appCtx.getAutowireCapableBeanFactory().autowireBean(this);
    }
}


Handlers are now implemented like that:

@ManagedBean
@RequestScoped
public class Index extends Handler implements Serializable {
    private static final long serialVersionUID = 1L;

    @Autowired
    SampleService ss;
    
    public String hello() {
        return ss.sayHello();
    }
}


First tests seem fine, but I'm curious if I'm causing any problems I don't know of.

Solution

-
Handler is too generic name for a class. Try to find something more descriptive (which doesn't force readers to check the implementation if they want to know what the class does), SerializationHandler, for example.

-
In Java classes could have only one superclass. If you make it an abstract superclass you can't have another one which might be cumbersome in some cases.


Inheritance is appropriate only in circumstances where the subclass really is a
subtype of the superclass. In other words, a class B should extend a class A only if
an “is-a” relationship exists between the two classes. If you are tempted to have a
class B extend a class A, ask yourself the question: Is every B really an A? If you
cannot truthfully answer yes to this question, B should not extend A. If the answer
is no, it is often the case that B should contain a private instance of A and expose a
smaller and simpler API: A is not an essential part of B, merely a detail of its
implementation.

Source: Effective Java, Second Edition, Item 16: Favor composition over inheritance

I'd use composition with a helper class:

@ManagedBean
@RequestScoped
public class Index implements Serializable {
    private static final long serialVersionUID = 1L;

    @Autowired
    SampleService ss;

    public String hello() {
        return ss.sayHello();
    }

    @PostConstruct
    private void init() {
        WireHelper.wireObject(this);
    }

    private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
        ois.defaultReadObject();
        WireHelper.wireObject(this);
    }
}

public final class WireHelper {
    public static void wireObject(Object object) {
        Spring.appCtx.getAutowireCapableBeanFactory().autowireBean(this);
    }
}


-
If you stay with the original implementation: you don't necessarily need implements Serializable here since Handler already implements that interface:

public class Index extends Handler implements Serializable {
    ...
}

Code Snippets

@ManagedBean
@RequestScoped
public class Index implements Serializable {
    private static final long serialVersionUID = 1L;

    @Autowired
    SampleService ss;

    public String hello() {
        return ss.sayHello();
    }

    @PostConstruct
    private void init() {
        WireHelper.wireObject(this);
    }

    private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
        ois.defaultReadObject();
        WireHelper.wireObject(this);
    }
}

public final class WireHelper {
    public static void wireObject(Object object) {
        Spring.appCtx.getAutowireCapableBeanFactory().autowireBean(this);
    }
}
public class Index extends Handler implements Serializable {
    ...
}

Context

StackExchange Code Review Q#23790, answer score: 6

Revisions (0)

No revisions yet.