ManagedProperty of SessionScope inside a ViewScoped Bean - Transient? - serialization

I have a JSF Beans structure of this sort:
#ManagedBean
#ViewScoped
public class ViewBeany implements Serializable {
....
#ManagedProperty(value='#{sessionBeany})
transient private SessionBeany sessionBeany;
...
public getSessionBeany() { ... };
public setSessionBeany(SessionBeany sessionBeany) { ... };
}
The reason for the transient is that the session bean has some non-Serializable members and cannot be made Serializable.
Will this work?
If not, How can I solve the problem of not being able to serialize SesionBeany but having to keep it as a managed property under a view scoped bean?
Thanks!

This won't work. If the view scoped bean is serialized, all transient fields are skipped. JSF doesn't reinject managed properties after deserialization, so you end up with a view scoped bean without a session scoped bean property which will only cause NPEs.
In this particular construct, your best bet is to introduce lazy loading in the getter and obtain the session bean by the getter instead of by direct field access.
private transient SessionBeany sessionBeany;
public SessionBeany getSessionBeany() { // Method can be private.
if (sessionBeany == null) {
FacesContext context = FacesContext.getCurrentInstance();
sessionBeany = context.getApplication().evaluateExpressionGet(context, "#{sessionBeany}", SessionBeany.class);
}
return sessionBeany;
}

Related

#Conditional annotation causing BeanCreationException on nested beans

I am using Spring 4.x in which I am using #Conditional annotation to control the bean registration.
I have classes defined as given below,
#Controller
class SchoolController{
#Autowired
#Qualifier("studentProcessor")
private StudentProcessor studentProcessor;
//Some code
}
#Component("studentProcessor")
class StudentProcessor{
#Autiwired
private SportService sportService;
//Some code
}
#Component
#Conditional(ServiceCondition.class)
class SportService{
//Some code
}
class ServiceCondition implements Condition{
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//Some condition
}
}
When I start the Tomcat, I get this exception:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'studentProcessor': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.student.service.SportService com.student.processors.StudentProcessor.sportService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.student.service.SportService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Is this the expected behavior?
If not then how do I get rid of this issue?
From your configuration, SportService bean is loaded based on the conditional implementation of ServiceCondition.
So, if the matches method returns false for some reason based on your logic, then SportService is would not be created and will not be available for autowiring.
That being said, StudentProcessor cannot have a concrete #Autowired for SportService.
I am not fully aware of your requirement, but for you to proceed with this configuration, you need to mark autowiring as optional.
#Autiwired
private SportService sportService;
//Some code
to
#Autiwired(required = false)
private SportService sportService;
//Some code
Further, you need to check if the instance is injected or not and then use it.

NInject concrete class information inside a provider

I've an abstract class:
[Configuration]
public abstract class AbstractAddon : IAddon
{
private readonly object configuration;
public AbstractAddon(object configuration)
{
this.configuration = configuration;
}
}
And several implementation of this.
I create a binding by convention as:
public class AddonsModule : Ninject.Modules.NinjectModule
{
public override void Load()
{
this.Bind(b => b.FromAssembliesMatching("*")
.SelectAllClasses()
.InheritedFrom(typeof(UIExtensibility.AbstractAddon))
.BindAllBaseClasses()
.Configure(c => c.InSingletonScope())
);
this.Bind<object>().ToProvider<ConfigurationProvider>().WhenClassHas<UIExtensibility.ConfigurationAttribute>();
}
and ConfigurationProvider is:
private class ConfigurationProvider : IProvider<object>
{
public object Create(IContext context)
{
return "configuration settings";
}
//...
}
Inside the Create method of ConfigurationProvider I thought I might be allowed to access which is the concrete class which is being requested around.
Each concrete class have an attribute PluginInformation I need in order to provide the correct configuration object. However, I don't know how to know which is the concrete class NInject is creating at the moment of the Create method provider is performed. And then, I can't get the PluginInformation attribute I need to link it and provide the correct configuration object.
How could I get access to the concrete class NInject is requesting at the moment of the object provider is performed?
The trouble was that on the first level of the IContext context parameter information, there is only the information according the Type it's providing, in my case: object type.
However IContext comes with the complete parent and plan context. So, at the point of the Create method of the provider is performed, some braches of the resolution are solved, for example: AbstractAddon. Every resolved information is on 'Context' like IContext fields. Moreover, the future steps are on 'Plan' like IContext fields.
So, in order to get the concrete type (inherited classes of AbstractAddon), I need to read the next property: context.Request.ParentContext.Plan.Type.

Update #ViewScoped bean from JAX-RS service

I've got a mishmash of JAX-RS webservices and JSF/CDI beans. Usual display of my #Entitys is from a #ViewScoped JSF bean collecting relevant entities in a #PostConstruct method:
#Named #ViewScoped
public class Manager {
private List<MyEntity> entities; // + getter
private MyEntity instance; // + getter/setter
#PostConstruct
public void init() {
entities = collectEntities();
instance = new MyEntity();
}
public void save() {
instance = persistInstance();
entities.add(instance);
}
// additional methods like collectEntities, persistInstance
}
Normal operation can call manager.save to persist a new entity and display it alongside the old ones.
Now, a JAX-RS service can also create entities that should be in the collection managed by such a scoped bean:
#Path("/myentity")
public class MyEntityService {
#PersistenceContext EntityManager em;
#PUT
public Response save(#FormParam("name") String name) {
MyEntity entity = new MyEntity(name);
em.persist(entity);
return Response.ok(entity.getId()).build();
}
}
The service can be called on a page where there's also a manager instance.
My question is: how can I make the existing manager instance aware of the additional entity, so that a JSF ajax re-render of a manager.entities list will include the entity created by the webservice?
So far, I've tried a CDI event observed by the CDI bean. The event gets fired from the service but is never received by the bean.
As a workaround I can fire a JSF ajax function telling the manager to refresh it's entity list (leveraging <a4j:jsFunction action="#{manager.init()}">, for example). However I'm unsure about the implications: will this expose a timing problem when the user asks for the entity list to be displayed earlier than the initialization can complete (the list isn't shown by default)?
As a total hack I can probably grab the bean from the session in the service and punch my data in. I shudder just thinking about it.
View scope is something that is JSF specific, as a JSF specific CDI context. It is alive only within the scope of the given view. JAX-RS has no specific way that I can think of to access this scope. I don't believe view scope would even have access to the HTTP request.

Cyclic dependency with Castle Windsor IoC for NHibernate ISession

I am using Castle Windsor for my IoC along with NHIbernate in an ASP.NET MVC app. It works great registered as follows (with one exception):
container.Register(Component.For<ISessionFactoryBuilder.().ImplementedBy<SessionFactoryBuilder>().LifestyleSingleton());
// Register the NHibernate session factory as a singleton using custom SessionFactoryBuilder.BuildSessionFactory method.
container.Register(Component.For<ISessionFactory>().UsingFactoryMethod(k => k.Resolve<ISessionFactoryBuilder>().BuildSessionFactory("ApplicationServices")).LifestyleSingleton());
container.Register(Component.For<IInterceptor>().ImplementedBy<ChangeAuditInfoInterceptor>().LifestylePerWebRequest());
container.Register(Component.For<ISession>().UsingFactoryMethod(k => k.Resolve<ISessionFactory>()
.OpenSession(container.Resolve<IInterceptor>())).LifestylePerWebRequest());
All is good except that for my ChangeAuditInterceptor in turn has an IAccountSession service injected which in turn has an NHibernate ISession injected...which leads to the following circular dependency exception:
Dependency cycle has been detected when trying to resolve component
'Late bound NHibernate.ISession'. The resolution tree that resulted in
the cycle is the following: Component 'Late bound NHibernate.ISession'
resolved as dependency of component
'Blah.Core.Services.AccountSession' resolved as dependency of
component 'Blah.Core.Infrastructure.Data.ChangeAuditInfoInterceptor'
resolved as dependency of component
'Blah.Core.Infrastructure.Installers.SessionFactoryBuilder' resolved
as dependency of component 'Late bound NHibernate.ISessionFactory'
resolved as dependency of component 'Late bound NHibernate.ISession'
which is the root component being resolved.
For the past couple years I've usually run with an NHibernateSessionManager which took care of plunking in the IInterceptor without causing this circular dependency issue (as opposed to this usage of a SessionFactoryBuilder which uses Castle Windsor's UsingFactoryMethod functionality).
Any suggestions for how to resolve this circular dependency? Short of starting to hack in the ISession for the AccountSession via some other means (i.e. property injection which skirts around the issue and smells as a result). I've switched the ISession injection to property injection for the AccountSession service and it works fine, but I don't like the implicit contract vs. the constructor explicit contract.
public class AccountSession : IAccountSession
{
private readonly ISession _session;
public AccountSession(ISession session)
{
_session = session;
}
public Account GetCurrentAccount() // Called by a method in ChangeAuditInterceptor
{
...
}
...etc.
Try to add a dependency on Func< ISession > in your interceptor class
public class CustomInterceptor : EmptyInterceptor
{
private readonly Func<ISession> sessionFunc;
private ISession session;
protected ISession Session
{
get
{
return session ?? (session = sessionFunc());
}
}
public CustomInterceptor(Func<ISession> sessionFunc)
{
this.sessionFunc = sessionFunc;
}
}
And registration:
container.Register(Component.For<ISession>().
LifestylePerWebRequest()
.UsingFactoryMethod(container =>
{
var interceptor = container.Resolve<IInterceptor>();
return container.Resolve<ISessionFactory>.OpenSession(interceptor);
}));
container.Register(Component.For<Func<ISession>>()
.LifestylePerWebRequest()
.UsingFactoryMethod(container =>
{
Func<ISession> func = container.Resolve<ISession>;
return func;
}));

CDI injection not done in base class for jax-rs controller

I'm struggling with CDI and class inheritence.
I've a JAX-RS controller declared as :
#Path("/share")
public class ControllerShare extends BaseController {
#Inject
private ServiceShare serviceShare;
#PostConstruct
private void verifInit() throws ExceptionTechnique {
log.warn("Checking CDI injection");
if (serviceShare == null) {
log.error("serviceAccount not initialized. Check your EJB configuration");
throw new ExceptionTechnique("serviceShare not initialized. Check your EJB configuration.");
}
}
...
}
This controller extends a base controller declared as :
public abstract class BaseController {
private Logger log = LoggerFactory.getLogger(ControllerShare.class);
#Context protected HttpServletRequest request;
#Inject private ControlerSession ctrlSession;
public BaseController() {}
#PostConstruct
private void verifInit() throws ExceptionTechnique {
log.warn("Checking CDI injection");
if (ctrlSession == null) {
log.error("controllerSession not initialized. Check your CDI configuration");
throw new ExceptionTechnique("serviceAccount not initialized. Check your CDI configuration.");
}
}
...
}
The problem is that injection is correctly done in ControllerShare (I correctly see "Checking CDI injection"), but is not done in the BaseController class (ctrlSession is null).
I try #Named and others combination without success. Injection is just done in ControllerShare and not in BaseController.
EDIT:
One more thing : curiously the #Context is working fine. My request is set and the value is correct.
Thank's for any explanation and solution.
Actually, this should work according to
http://docs.jboss.org/cdi/spec/1.0/html/inheritance.html
4.2. Inheritance of member-level metadata
Suppose a class X is extended directly or indirectly by the bean class of a managed bean or session bean Y.
If X declares an injected field x then Y inherits x.
On a side note: #PostConstruct however is not inherited if you specify it anew. Therefore, in your sub-class your method must be named differently to have both initializers executed.
If X declares an initializer, non-static observer, #PostConstruct or #PreDestroy method x() then Y inherits x() if and only if neither Y nor any intermediate class that is a subclass of X and a superclass of Y overrides the method x().