JavaEE and CDI: Understanding #Observes - java

I have the archetype org.jboss.weld.archetypes:jboss-javaee6-webapp:1.0.1.CR2 and I try to understand the class MemberListProducer:
#RequestScoped
public class MemberListProducer
{
#Inject #MemberRepository private EntityManager em;
private List<Member> members;
#Produces #Named public List<Member> getMembers() {return members;}
public void onMemberListChanged(#Observes(notifyObserver = Reception.IF_EXISTS)
final Member member){
retrieveAllMembersOrderedByName();
}
#PostConstruct
public void retrieveAllMembersOrderedByName()
{
//Criteria Query to fetch all members
members = em.createQuery(criteria).getResultList();
}
}
The observer is invoked from another class with memberEventSrc.fire(newMember);, this seems clear: Once fired, the MemberListProducer updates the list of members.
But I don't understand why this is done in a #RequestScoped Bean. In my understanding the method retrieveAllMembersOrderedByName is anyway called by each request. Should this #Observes not be better placed in a #ViewScoped or #SessionScoped Bean? Does it have an effect in this case at all?

The use of #Observes there is more of an example than a real, practical use case. Consider the possibility of members changing before you render your response.
I don't think the website would work correctly if you removed it. Think about it like this:
When the request starts, the list of members is created and it contains all the members up to the moment of creation of this request scoped bean. Later, you persist a new member, so this list needs to be updated to render the response.
You think correctly when you say that the list is built for each request, however this happens at the beginning. After you add a member, you need to refresh it, don't you?
If this method weren't there, the response would be outdated (you'd render the list you had before you persisted the new member), and you would need one extra post or get to fetch the new list of members.
#Observes decouples listeners and event sources much like the observer pattern. So if the #Observes isn't there, you would need to explicitly add the new member to the list so that the response is correct.
I hope I understood your question correctly.

It's request scoped because it stores a list of members per request. If you need this list to be stored per-session, then change it.
But it looks wrong - you are discarding the member arguments of the observer method.

Related

CDI: Dynamical injection of a group of classes how to?

I need to dynamically Inject a variable group of classes in my application. The purpose is, as the application grows, only have to add more classes inheriting the same interface. This is easy to do with tradicional java as I just need to search for all classes in a package and perform a loop to instantiate them. I want to do it in CDI. For example:
public MyValidatorInterface {
public boolean validate();
}
#Named
MyValidator1 implements MyValidatorInterface
...
#Named
MyValidator2 implements MyValidatorInterface
...
Now the ugly non real java code just to get the idea of what I want to do:
public MyValidatorFactory {
for (String className: classNames) {
#Inject
MyValidatorInterface<className> myValidatorInstance;
myValidatorInstance.validate();
}
}
I want to loop over all implementations found in classNames list (all will be in the same package BTW) and Inject them dynamically so if next week I add a new validator, MyValidator3, I just have to code the new class and add it to the project. The loop in MyValidatorFactory will find it, inject it and execute the validate() method on the new class too.
I have read about dynamic injection but I can't find a way to loop over a group of class names and inject them just like I used to Instantiate them the old way.
Thanks
What you are describing is what Instance<T> does.
For your sample above, you would do:
`#Inject Instance<MyValidatorInterface> allInstances`
Now, allInstances variable contains all your beans which have the given Type (MyValidatorInterface). You can further narrow down the set by calling select(..) based on qualifiers and/or class of bean. This will again return an Instance but with only a subset of previously fitting beans. Finally, you call get() which retrieves the bean instance for you.
NOTE: if you call get() straight away (without select) in the above case, you will get an exception because you have two beans of given type and CDI cannot determine which one should be used. This is implied by rules of type-safe resolution.
What you most likely want to know is that Instance<T> also implements Iterable so that's how you get to iterate over the beans. You will want to do something like this:
#Inject
Instance<MyValidatorInterface> allInstances;
public void validateAll() {
Iterator<MyValidatorInterface> iterator = allInstances.iterator();
while (iterator.hasNext()) {
iterator.next().callYourValidationMethod();
}}
}

How to use a variable anywhere in the code?

In Java EE how can I use a variable anywhere in code without passing it down as a parameter?
Something similar to a public static variable... but a static variable is always the same for all the requests... What about a "static" variable but for the single request?
Is it possible?
Here is a little example:
I have:
protected void doGet (...)
{
Model m = Model.GetById (...);
}
public class Model
{
private String descrition;
private Market market;
private List<SparePart> spareParts;
public Model GetById ()
{
Model m = new Model ();
// get info from db using the language
this.market = Market.GetById (...);
this.spareParts = SparePart.GetByModel (m);
}
}
public class SparePart
{
private String description;
public List<SparePart> GetByModel (Model mo)
{
// get info from db using the language
}
}
public class Market
{
private String descrition;
public Market GetById (...)
{
// get info from db using the language
}
}
Both make queries to the database and retrieve informations using the language of the client... How can I set the language variable so i don't have to pass it to the methods that use it?
The anguage variable is just an example, it may happen with other variables
There are dozen ways to pass your data through execution flow in JaveEE applications. Let's assume you need to pass data within one application boundary.
Of course you can use public static final constants.
You can use public static variables, but take into account that EE
environment is extremely multithreaded. So use atomic wrappers
(AtomicInteger, etc).
You can use producers
While single request scope (http (rest) -> interseptor(s) -> bean(s)
-> response) you can use ThreadLocal
Of course you can use Stateful or Singleton beans You can use CDI
Events
If you are using Payara Server (for now the only has JCache spec
preview) you can use JCache to share your data among any
application or along the cluster as well
If you need to share your data between servers you can expose your business methods on #Remote interfaces and or share/publish/consume using JMX.
The concrete choice should depend on your App business logic.
You can set and get attributes on your ServletRequest object.
request.setAttribute("someName", someObject);
Object someObject = request.getAttribute("someName");
See the javadoc here.
Alternatively, you could use CDI (or another DI framework) and define one or more #RequestScoped objects that you can then #Inject in the places you need them.
Although not passing parameters is not a good idea in the first place, if you 'MUST' find a solution and if it matches your design, how about using inner classes? That way you declare the class variable as non-static and you can always access it from the inner classes.

How to setup a non-CDI bean from a 3rd party for #Inject into CDI bean

While I've found examples in CDI where you setup #Produces (kinda factory like) or using the CDI javax.enterprise.inject.spi.Unmanaged concepts, they all seem to presume that CDI will be the one creating the instance of the class on its own terms and lifecycle (which makes sense).
However, there are situations where CDI simply cannot create the instance.
Such as a 3rd party library (that isn't using CDI itself) which is creating the object internally and giving it to you.
Now, how can I take these already instantiated objects (which incidentally are final objects with no default constructor), and make them available for my CDI managed beans to then use?
Here's a simplified example.
public class Foo
{
#Inject
private ByteBuffer buf;
public void go()
{
// do something, with buffer
}
}
public void process() {
ByteBuffer buf = ByteBuffer.allocate(500);
// TODO: how to add "buf" to current context?
Foo foo = CDI.current().select(Foo.class,AnyLiteral.INSTANCE).get();
foo.go();
}
Now, I realize that for this specific example, I could eaily just pass in the ByteBuffer, or setup a #Produces for ByteBuffer, or even have Foo make the ByteBuffer itself. (all of which would be easier). I chose ByteBuffer, because it exhibits the same problems I'm facing with the 3rd party library
The instances are valid beans
I have no control over its source
Instances are created by the library
Those instances are final and cannot be wrapped, overridden, or proxied
The use case also has situations where there are nested CDI references that could also use access to this #Inject ByteBuffer buf;.
Ideally it would be keen to have this be a pure CDI api technique, and not something that is weld or implementation specific.
I've devled into custom Scope creation as well, thinking that might be a solution for this, having a sort of #BufferScope that identifies the start() and end() of this instance. But none of the examples and documentation make this very clear with regards to objects that CDI just cannot call newInstance() or produce() on. The object instantiation is out of my hands, but the ability to present it to a CDI Scope is possible, along with even managing the ultimate death / destruction of that instance.
Proxying is not the same as wrapping. A customary workaround is to create a ByteBufferHolder (insert your class here) that adapts the custom builder flow into a bean that understands that it's inside the DI context.
I'm not sure I agree with the original assertion that CDI assumes it is constructing the instances. For example, I use the following in a JSF application to inject the current FacesContext instance....
import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Produces;
import javax.faces.context.FacesContext;
public class FacesContextProducer {
#Produces #RequestScoped FacesContext getFacesContext() {
return FacesContext.getCurrentInstance();
}
}
At nowhere do I create the FacesContext instance. All that is required is that what has been created by the external framework is accessible.
So, if there is an external source from which you are getting instances, as long as you can get the correct one, the #Produces approach should still work?
There is some fundamental misunderstanding here. CDI is not required to construct the bean instances it can serve through producer methods. A Dependent scope will work just fine if the class is not proxyable. You can also make a wrapper class for the object, and put said class instances in whichever scope you need.
You use a producer method, which can be as simple as something like this:
#Produces
#ApplicationScoped
private Foo produceFoo() {
final Foo instance = // acquire one of those instances you're talking about
return instance;
}
If for whatever reason that doesn't work for you, you can alternatively write a portable extension and programmatically add a Bean that does what you want. So something like this in CDI 2.0+ (untested):
private void afterBeanDiscovery(#Observes final AfterBeanDiscovery event) {
final Foo instance = // acquire one of these final instances you're talking about
event.addBean()
.scope(ApplicationScoped.class)
.qualifiers(whateverYouNeed)
.addTransitiveTypeClosure(instance.getClass())
.createWith(cc -> instance) // you may also need .destroyWith()
;
}
Once you have this "producing side" set up, then in any CDI bean anywhere you can do:
#Inject
private Foo foo;

Stripes: Call method of an ActionBean from another ActionBean

I am new on using the Stripes framework and I need some help.
I want to call a method of an ActionBean from another ActionBean.
For example, I have two ActionBean:
#SessionScope
public class SessionActionBean extends AbstractActionBean{
private String property;
public void setUsername(String username) {
this.username = username;
}
}
And
public class TestActionBean extends AbstractActionBean {
...
public Resolution submitTest() {
//TODO Call setUsername is SessionActionBean
}
...
}
How do I call the setUsername of the SessionActionBean from TestActionBean? And if the SessionActionBean was not session scoped?
Thanks in advance
A few things:
If you want to store data in a user's session, #SessionScope isn't really what you want. You'd be better off extending ActionBeanContext and writing some getters and setters that store in context. See http://www.stripesframework.org/display/stripes/State+Management for more details.
If you really really want to use #SessionScope, make sure you read the caveat in the javadoc and make sure that's really what you need.
http://stripes.sourceforge.net/docs/current/javadoc/net/sourceforge/stripes/action/SessionScope.html
Since session scope ActionBeans are not generally encouraged by the
author, very few allowances will be made in Stripes to accommodate
session scope beans.
Finally, actually invoking methods from one action bean to the other is as simple as instantiating the bean and calling the method. It's kind of weird and backwards and the instantiated bean won't inherit Stripes context stuff, but you can do it.
If you'd rather have one #Resolution call another #Resolution, you can do that too: ForwardResolution(Class<? extends ActionBean> beanType).

How Dependency Injection Manually Implemented?

How we can manually inject an object without using the facility of containers. I did something similar through reflection as follows.
Class actionClass = Class.forName("SampleClass");
Object actionObject = actionClass.newInstance();
Method reqMethod = actionClass.getMethod("setRequest", HttpServletRequest.class);
reqMethod.invoke(actionObject,request);
is it the right way to do DI?
My intention is to pass request object to different controller classes dynamically from a dispatcher filter,where we get request and response objects.
I am fearing about the performace of reflection.Is there any replacement for doing DI?
Dependency injection is nothing more than providing a class with its dependencies, rather than have it find them itself (via singletons/lookups etc.). So you can do it in code trivially thus:
DatabaseConnection dc = new DatabaseConnection();
MyDAO dao = new MyDAO(dc);
(pseudocode). Here the MyDAO is being injected with a database connection. If that database connection implements an interface you can easily mock this out during testing.
Well, when you set one object into another object using setter method or through a constructor it also is the dependency injection. Dependency injection only means creating relationship(dependency) in objects.
Using reflection as you did is just another form of it.
Why would you use reflection? Why not simply:
SampleClass action = new SampleClass();
action.setRequest(request);
That does the same thing, but is more readable, allows the compiler to check that the types and methods actually exist, provides you with Javadoc for the Method invoked, enables your IDE to assist in refactorings, ...
And it still is dependency injection, because the action doesn't go looking for its request, but receives the request during initialization.
Edit: Thorbjørn requested I show how that action would be used. It would itself be injected (using a setter) into whatever component uses the action. The component would then use the injected action object.
SampleClass action = new SampleClass();
action.setRequest(request);
Servlet servlet = new ActionBasedServlet();
servlet.setAction(action);
If servlet is intended to live longer than action, i.e. it should use a fresh Action each time it needs one, one can instead setter-inject an ActionFactory into servlet.
In this concrete case, I'd question whether the action really needs to keep a request as part of its state, or can be immutable and simply act on the request passed by the Servlet as method parameter. In that case, the boot-time initialization would do:
SampleClass action = new SampleClass();
Servlet servlet = new ActionBasedServlet();
servlet.setAction(action);
and ActionBasedServlet would define
public void serve(Request req, Response resp) {
foo();
action.act(req, resp);
bar();
}
Dependency Injection implies you get properly initialized references appearing "by magic".
You call the setRequest() method with the request object, but DI frequently also allows for setting the fields without invoking methods.
Guice does not as such require a container, but uses class loader magic started in the main method. Would that be useable for you?
Spring framework is one of the most popular DI implementations. It is also opensource.
You can check out the class org.springframeowrk.beans.BeanUtils, specifically the methods copyProperties (all 4 of them) for examples on how to do this.
For more info you can also see the class hierarchy of org.springframework.beans.factory.BeanFactory for different strategies.

Categories

Resources