I'm using Spring and JSF 2 to create a web application. The business objects are kept in the Spring container, and I inject them in the Managed Beans using the @ManagedProperty, like this:
@ManagedBean
@ViewScoped
public class SomeMB implements Serializable {
private static final long serialVersionUID = 1L;
@Getter @Setter
@ManagedProperty("#{someService}")
private SomeService someService;
// ...
The problem is, I keep getting a NotSerializableException
for a class from Spring (ServiceLocatorFactoryBean) that it's being used by the SomeService bean.
If I make it transient
, how could I do the re-injection of it after deserializing?
Or, what would be other ways to solve this problem?
I've been reading several other questions similar here, but couldn't find any that dealt exactly with this problem.
Try @Scope(value = BeanDefinition.SCOPE_SINGLETON, proxyMode = ScopedProxyMode.INTERFACES) on your Spring @Service. This should inject a serializable proxy object into your managed bean that will relocate the service upon access after deserialization.
Well keep this in mind from the Spring manual ( link to spring):
For those to follow - I had a similar problem with an injected ResourceBundle. Using part of BalusC's answer, I did the following:
This way, the EL is evaluated only when the managed bean is deserialized.
Instead of injecting the Spring beans via EL in a
@ManagedProperty
annotation (executed on the ManagedBean initialization), obtain the beans evaluating the EL at runtime.With this approach, this is what the JSF beans should look like:
And the utility class SpringJSFUtil.java that gets the bean via EL:
This eliminates the Spring bean property (at the cost of doing a few more EL evaluations), thus avoiding all the serialization issues of having the property in first place.
The same approach, using OmniFaces:
In my actual code, I use the
evaluateExpressionGet(String expression)
method of an utility class available from OmniFaces. So, for those of you who use it too, this is what my code really look like:Notice that here the method gets the full EL ("#{expression}"), not just the Spring bean name (or you would get a ClassCastException).