Get only in-service CDI managed beans - jsf-2

My goal is to get a collection of all in-service CDI managed beans (of a certain parent class) from within a JSF2 ExceptionHandlerWrapper. Note the exception handler part is significant because the class is not a valid injection target itself. So my assumption (maybe incorrect) is that my only route is programmatic through BeanManager.
Using BeanManager.getBeans, I can successfully get the set of all beans available for injection. My issue is that when using BeanManager.getReference to obtain the contextual instance of the bean, the bean will be created if it does not already exist. So I am looking for an alternative that will only return instantiated beans. The code below is my starting point
public List<Object> getAllWeldBeans() throws NamingException {
//Get the Weld BeanManager
InitialContext initialContext = new InitialContext();
BeanManager bm = (BeanManager) initialContext.lookup("java:comp/BeanManager");
//List all CDI Managed Beans and their EL-accessible name
Set<Bean<?>> beans = bm.getBeans(AbstractBean.class, new AnnotationLiteral<Any>() {});
List<Object> beanInstances = new ArrayList<Object>();
for (Bean bean : beans) {
CreationalContext cc = bm.createCreationalContext(bean);
//Instantiates bean if not already in-service (undesirable)
Object beanInstance = bm.getReference(bean, bean.getBeanClass(), cc);
beanInstances.add(beanInstance);
}
return beanInstances;
}

Here we are...poking through the javadoc I found Context which has two versions of a get() method for bean instances. One of them, when passing in a creational context, has the same behavior as BeanManager.getReference(). However the other just takes a Bean reference and returns either the contextual instance (if available) or else null.
Leveraging that, here is the version of the original method which returns only instantiated beans:
public List<Object> getAllCDIBeans() throws NamingException {
//Get the BeanManager via JNDI
InitialContext initialContext = new InitialContext();
BeanManager bm = (BeanManager) initialContext.lookup("java:comp/BeanManager");
//Get all CDI Managed Bean types
Set<Bean<?>> beans = bm.getBeans(Object.class, new AnnotationLiteral<Any>() {});
List<Object> beanInstances = new ArrayList<Object>();
for (Bean bean : beans) {
CreationalContext cc = bm.createCreationalContext(bean);
//Get a reference to the Context for the scope of the Bean
Context beanScopeContext = bm.getContext(bean.getScope());
//Get a reference to the instantiated bean, or null if none exists
Object beanInstance = beanScopeContext.get(bean);
if(beanInstance != null){
beanInstances.add(beanInstance);
}
}
return beanInstances;
}

Related

Neo4j-spring-data(4.1.1) self relationship (parent-child) is duplicated

I am using spring-data-4.1.1 & Neo4j 2.3.2 with ogm annotations
Below is my entity
#NodeEntity(label = "Component")
public class Component extends BaseEntity {
.........
#Relationship(type = Relation.LINK_TO)
private Set<Link> links = new HashSet<>();
#Relationship(type = Relation.PARENT)
private Set<Component> parents = new HashSet<>();
.........
.........
}
And Link class
#RelationshipEntity(type = Relation.LINK_TO)
public class Link extends BaseEntity {
#Property(name = "isSelfLink")
private boolean isSelfLink;
#StartNode
private Component component;
#EndNode
private Component linkComponent;
}
I've removed getter/setter/hashcode/equals for keeping it clean
Now, here is my code to add two component parent/child and a Link
Component parentcomp = new Component(1, name);
Component childcomp = new Component(2, name);
childcomp.getParents().add(parentcomp);
Link link = new Link();
link.setComponent(parentcomp);
link.setLinkComponent(childcomp);
parentcomp.getLinks().add(link);
componentRepository.save(parentcomp,-1);
Now, as per the logic
object parentcomp property 'parent' should be empty
object childcomp property 'parent' should have parentcomp object
And parentcomp property 'links' should have childcomp
(parentcomp)----LINKS_TO---->(childcomp)
(parentcomp)<----PARENT----(childcomp)
Note: My equirement is such that we need two way relationship..
But, below is the result when I load parent or child entity
object parentcomp property 'parent' has both childcomp,parentcomp instead of empty
object childcomp property 'parent' has both childcomp,parentcomp instead of only parentcomp
This behavior persist until a Neo4j sessions clears out internally. After some time(or after app restart) the mappings shows up correctly.
I tried cleaning up the session using neo4joperations.clear() still problem persists. But if I query
match (c:Component)-[:PARENT]->(p) where c.componentId = {0} return p
results are correct.
I am not sure how to solve this problem...

How to autowire HttpSessionManager Bean in spring?

so I'm using the spring-session project and I want to know if it is possible to autowire the HttpSessionManager bean? I can see in the users example you are getting it from the request together with the SessionRepository:
HttpSessionManager sessionManager =
(HttpSessionManager) req.getAttribute(HttpSessionManager.class.getName());
SessionRepository<Session> repo =
(SessionRepository<Session>) req.getAttribute(SessionRepository.class.getName());
However, I want to access it from a service near the db layer and because I don't think it is a good design practice to pass the request down to the service I tried to autowire it but it doesn't find a bean of this type. The SessionRepository can be autowired fine because I have defined the bean in my configuration. I also tried to get it using the RequestContextHolder but then the getSessionIds methods always returns empty map, so I end up creating a new session all the time. Here's my whole method:
#Override
public Session getCurrentSession() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
HttpSessionManager sessionManager =
(HttpSessionManager) request.getAttribute(HttpSessionManager.class.getName());
final Map<String, String> sessionIds = sessionManager.getSessionIds(request);
if (sessionIds != null) {
for (Map.Entry<String, String> e : sessionIds.entrySet()) {
final Session session = sessionRepository.getSession(e.getValue());
if (session != null) {
return session;
}
}
}
Session session = sessionRepository.createSession();
sessionRepository.save(session);
return session;
}
My guess is that the RequestContextHolder is capturing the HttpServletRequest before the SessionRepositoryFilter is invoked. That means that the request will not yet be wrapped.
By default the EnableRedisHttpSession configuration does not expose CookieHttpSessionStrategy as a Bean. This is necessary in order to allow users to override the SessionStrategy and supporting older versions of Spring (newer versions of Spring support #Conditional). If you wish to expose CookieHttpSessionStrategy as a Bean, then you can add the following to your configuration:
#Bean
public CookieHttpSessionStrategy sessionStragegy() {
return new CookieHttpSessionStrategy();
}
After thinking about it some I may be able to expose it in future versions. I have created gh-spring-session-75 to address it.

How to call Managed bean method in using expression language

I am developing a utility class, using this we need to call a managed bean method which is defined in EL Expression. Is there any examples like how to invoke a managed bean method using EL expression.
Here I don't know the type of Managed bean. but I know EL expression. So I cannot type cast to specific managed bean.
The expression is: #{phaseListenerBean.compListener}
How can my code call the compListener method on phaseListenerBean?
My Utility class. It is avaliable in a Jar file.
`public void beforePhase(PhaseEvent event) {
if(PhaseId.RENDER_RESPONSE.equals(event.getPhaseId())){
SystemListLoaderHelper.populateSelectOneValidValues();
SystemListLoaderHelper.populateSelectManyCheckboxValidValues();
FacesContext context = FacesContext.getCurrentInstance();
ExpressionFactory factory =context.getApplication().getExpressionFactory();
MethodExpression methodExpression = factory.createMethodExpression(
context.getELContext(), "#{phaseListenerBean.callModuleSpecificServiceCalls}",
Void.class.getClass(), null);
methodExpression.invoke(context.getELContext(), null);
// callModuleSpecificServiceCalls();
}
}`
You can try call the bean with the Faces context, for example if you want the bean, you can use:
FacesContext facesContext = FacesContext.getCurrentInstance();
Object o = facesContext.getApplication().evaluateExpressionGet(facesContext,
"#{phaseListenerBean}", Object.class);
And later use reflection to call the method or, You can call the method whith your expression, like this:
FacesContext fc = getContext();
ExpressionFactory factory = getExpressionFactory();
methodExpression = factory.createMethodExpression(
fc.getELContext(), "#{phaseListenerBean.compListener}",
Void.class, (Class<?>) null);
methodExpression.invoke(fc.getELContext(), null);
Please show some code for "compListener" and the utility class. Sorry for my bad english,
Cheers

Setting bean property from validator

Is there a way to set a bean property from a Validator?
In my case, I have a validator which connects to the database and performs some validation.
Upon successful validation, I want to save the object received from database, inside a bean property.
Currently i'm doing this by setting a static property of my bean from the validator.
Here is my validator method
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
//perform validation
if(isValidated) {
Referral ref = database.getReferral(value.toString()); //receive referral object from batabase
RegistrationBean.staticReferral = ref; // Set ref to RegistrationBean's static property
} else {
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_FATAL, "Invalid Referral!", "Referral does not exist!");
throw new ValidatorException(msg);
}
}
and here is my RegistrationBean
#ManagedBean
#ViewScoped
public class RegistrationBean implements Serializable {
//other bean properties
private Referral referral;
public static Referral staticReferral;
public RegistrationBean() {
//default constructor
}
public Referral getReferral() {
this.staticReferral = referral;
return referral;
}
// other getters, setters and methods
}
So the questions in my mind are:
Is there a way to set a bean property directly from a bean? (without
using a static property)
Would there be any concurrency issues (one user may receive other user's selected referral object etc) using the existing approach?
Thanks
Static members in managed beans are shared among all instances (and users of your application). So think at least twice before making a member variable static.
If you make your validator a managed bean, you can inject your target managed bean into your validator. See this answer for details.
In the given example an EJB is injected, but you can inject a JSF managed bean via the #ManagedProperty annotation

Storing context object in Request object, is it disposed of?

I am writing a MVC3 application, using NInject DI and repository pattern. Ninject is set up so that the repositories have a per-request lifetime.
I am putting the context object into the Http Request object, using the following code:
public static MessengerEntities GetContext()
{
if (!HttpContext.Current.Items.Contains("_db_context"))
{
HttpContext.Current.Items.Add("_db_context", new MessengerEntities());
}
return (MessengerEntities)HttpContext.Current.Items["_db_context"];
}
Then each repository calls this procedure to get either an existing or a new context object, e.g.:
public class TestRepository : ITestRepository
{
private MessengerEntities context = ContextHelper.GetContext();
#region ITestRepository Members
private string _testProperty = "blah";
public string testProperty
{
get
{
_testProperty = context.UserLogins.Where(n => n.inactive == null || !n.inactive.Value).ToList().Count.ToString();
return _testProperty;
}
set
{
_testProperty = value;
}
}
#endregion
}
(Later on, I plan to use a generic IRepository pattern, but for now I am just using this test repository.)
My question is: when the Request object is disposed of, will it also dispose of the context object in the Items collection? In other words, will it call Dispose on each object that may be stored in that collection?
I know there are a lot of discussions about this issue here, but they all seem to involve scenarios that are not quite the same as mine, so it's kind of hard to divine the answer.

Resources