I have some legacy code that put objects as http session attributes using code like this:
MyObject object = new MyObject();
Map<String, Object> sessionMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
sessionMap.put("attrname", object);
The old facelets accessed the code using
@ManagedProperty("#{attrname}")
private MyObject object;
Is there any way using CDI (@Inject
) to inject this session attribute to a Bean?
In new code that uses CDI what's the better way to create and inject objects that need to be created in a controlled way.
Get hold of it in a session scoped managed bean with a @Produces
@Named
on the getter.
@SessionScoped
public class MyObjectProducer implements Serializable {
private MyObject myObject;
@Produces
@Named("attrname")
public MyObject getMyObject() {
return myObject;
}
public void setMyObject(MyObject myObject) {
this.myObject = myObject;
}
}
When you set it somehow via e.g. myObjectProducer.setMyObject(myObject)
elsewhere (or perhaps a CDI @Observes
event), then you can inject it anywhere using @Inject @Named
.
@Inject
@Named("attrname")
private MyObject myObject;
And yes, it's still available via #{attrname}
in EL the usual way. And no, it won't be auto-created when not set, it'll remain null
until you actually set it as a property of the producer class.
Alternatively, if you really intend to keep the legacy way of setting the instance via ExternalContext#getSessionMap()
(e.g. because it's third party and you can thus not change it), then you can alternatively also let the producer return it directly from the session map:
@SessionScoped
public class MyObjectProducer implements Serializable {
@Produces
@Named("attrname")
public MyObject getMyObject() {
return (MyObject) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("attrname");
}
}
This however isn't guaranteed to work when injected in a non-JSF artifact, such as an arbitrary @WebServlet
, as the FacesContext#getCurrentInstance()
would obviously return null
.
This is the way to go, for both non-jsf and jsf artifacts.
@Qualifier
@Retention(RUNTIME)
@Target({TYPE,METHOD,FIELD,PARAMETER});
public @interface SessionAttribute {
@NonBinding
String value() default "";
}
@ApplicationScope
public class SessionAttributeService {
//Dont worry, this is a proxy, and CDI will ensure that the right one called at the right time.
@Inject
private HttpServletRequest servletRequest;
@Produces
@SessionAttribute
@RequestScope
public String sessionAttribute(final InjectionPoint ip){
final SessionAttribute sa = ip.getAnnotated().getAnnotation(SessionAttribute.class);
final HttpSession session = servletRequest.getSession();
return session.getAttribute(sa.value());
}
}
And use case:
@RequestScope
public class MyServiceBean {
@Inject
@SessionAttribute("theAttribute")
private String attribute;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With