Head first EJB states that in the case of stateless session beans:
Clients don't share EJBObject, but the same bean can serve multiple
EJBObjects
I don't see any reason why a single EJBObject cannot serve multiple clients.
Furthermore, if what the book states is correct, what is the advantage we get from pooling beans if we have to create one EJBObject per client ?
First of all, one has to understand what an EJBObject is:
The EJBObject interface is extended by all enterprise beans' remote interfaces. An enterprise bean's remote interface provides the remote client view of an EJB object. An enterprise bean's remote interface defines the business methods callable by a remote client.
With that being cleared, consider the following local EJB example:
public class SomeClass {
#EJB
private SomeBean someBean;
...
}
Basically, our EJBObject is nothing more than an attribute of our class SomeClass which references the EJB SomeBean.
What's happening is that, on the container's point of view, he's not really creating and injecting a dedicated instance of the EJB SomeBean. Instead, he's instantiating the EJB SomeBean, storing it in his EJB pool, creating a proxy for this instance and injecting the proxy in on our class SomeClass.
Therefore, for each client, you have a single EJBObject or proxy but, under the hood, as the Head First states, the same bean can serve multiple EJBObjects.
...what is the advantage we get from pooling beans if we have to create one EJBObject per client?
Well, for instance, thread-safety: if you have several instances of SomeClass, calling concurrently the same method of someBean, it is guaranteed that those calls will never be delegated to the same instance since Stateless session instances are dedicated to an EJB object only for the duration of a single method call.
Other advantages of EJB pooling can be found on this answer by Will Hartung. :)
Related
I have the following design. When a client makes a request to the server, the server creates a state that holds all sorts of info. There are various stateless and stateful beans which need to read and write to this state. Refer to this unprofessional diagram:
The ComputationCycle class is where the processing starts and works by phases. During each phase it calls upon other Manager classes (which behave like utility classes) to help in the computation (diagram shows only for 1 phase). The state is being read and written to both from the CC class and the managers, both are stateless.
State holds Employee, Department and Car classes (in some irrelevant data structure) which are stateful. These classes can also call the Manager classes. This is done by a simple #Inject Manager1. The same way CC uses managers.
My problem is how to access the stateful state (and its contained classes) from the stateless classes (and from the Car, Department and Employee classes too, although I think solving one will solve the other). I can't inject a stateful bean into a stateless bean. So after the client makes a request and the computation cycle starts, how do I access the state related to this request?
One solution is to pass the state to every method in the stateless classes, but this is really cumbersome and bloaty because all methods will have an "idiotic" State argument everywhere.
How can I make this design work the way I want it to?
I can't inject a stateful bean into a stateless bean.
You can absolutely inject dependencies this way.
If the stateful bean is #RequestScoped, any call into the stateless bean on that thread that hits a CDI injected contextual reference (iow proxy) will find its way to the right instance of the stateful bean.
As long as you use CDI, you don't need to trouble yourself with trying to stash things away in your own threadlocals.
Buyer beware, ThreadLocal will possibly do what you're wanting, along with a static accessor. However, this class is prone to causing memory leaks if you are not extremely careful to remove each entry at the end of the request. In addition, you seem to be using EJB; I assume they are all in the same JRE. I use ThreadLocal quite a bit in similar situations, and I've had no problems. I use SerletContextListener's to null the static reference to the ThreadLocal when the context shuts down, although that has been problematic on some older Web app servers, so I make sure the ThreadLocal exists before attempting to use it.
EJB can "talk" to each other across servers. It sounds local all your EJB are running in the same context.
Create a class that holds your state.
Extend ThreadLocal--you can do this anonymously--and override initialValue() to return a new instance of your class.
Create a utility class to hold the ThreadLocal as a static field. Don't make it final Create static fetch and remove methods that call ThreadLocal.get() and remove(). Create a static destroy() method that is called when your context shuts down--see ServletContextListener.
I'm kind of a newbie in EJBs,but I've been given an EJB tier to improve.
This tier consists of an EJB wich exposes the operations available:
#Stateless(name = "myejb")
public class Facade implements FacadeRemote
{
#EJB
private EntityAHomeLocal entityAHome;
#EJB
private EntityBHomeLocal entityBHome;
// methods signatures and implementations
}
As you can see this EJB use other local EJBs that manage operations on entities.
#Stateless
public class EntityAHome implements EntityAHomeLocal
{
#PersistenceContext(name="myUnit")
private EntityManager manager;
// methods signatures and implementations
}
I'm having hard time to fully understand the architecture of this tier.
Is this kind of architrcture common ?
Are local stateless EJB managed throught a pool of instances just like remote stateless EJBs ?
Would it still work even if entityAHome and entityBHome were remote EJBs ?
Strictly speaking, the spec only says stateless beans are "typically" pooled (section 4.3.10.2), so the behaviour for local beans is vendor-specific, but in practice I believe all the major vendors do (for example).
Local and remote interfaces are almost entirely interchangeable, but with extra deployment restrictions (i.e. they must be deployed locally, of course), and some calls to local interfaces use pass-by-reference semantics, whereas remote interfaces always use pass-by-value (link).
I can't see anything that would stop that code working with remote interfaces, although I think some of the naming is confusing - a session bean (#Stateless) is different from an entity, and in EJB terminology "home" refers to a kind of factory class, which I don't think is your intention here (?). Also, be aware that switching to #Remote can add a performance overhead, as the second link notes.
What I need is to get new instance of service every time when some consumer needs this service + using CDI. I've read a lot of articles and I can't find the answer to 2 my questions.
If we use factories, why in service consumer we call factory (http://www.rpgnextgen.com/wiki/doku.php?id=component_factory ) and after that we get reference to service. I mean
// get factory
ComponentFactory factory = (ComponentFactory) context.getService(serviceReferences[0]);
// get instance
ComponentInstance instance = factory.newInstance(null);
Is there no way to set factory with certain interface and in service consumer call service when osgi inside calls the factory?
If in service consumer we call factory then why we mark service as component when de facto factory is component?
The problem is that without factory I do #Inject #OsgiService (javase) or#OSGiService (javaee) and I can use different filters and code is very clear. Using component factory I (as I understand) loose this ability.
ComponentFactory exists for consumers that want to use a factory, because they want to control the lifecycle of the individual components. For example, if they want to create an instance of the component for every web request.
If you don't want to use ComponentFactory... then don't.
I need for every consumer new instance of component.
I haven't tried yet, but according to the documentation when using PAX-CDI and an OSGi v6 container then the prototype scope should do what you need:
#OsgiServiceProvider
#PrototypeScoped
public class MyService implements SomeService{
OSGi services in are special types of beans in CDI. Compare them to EJBs, you can use CDI to inject references to the different types of EJBs, but the components will have their own lifecycle. The same goes for OSGi services; their life cycle is not controlled by CDI. CDI just injects references to those services.
This means CDI factories can't be used with OSGi services. Just like you can't use CDI factories with EJBs. There is not really a way to create an OSGi service instance per injection point, so there's no workaround either.
If you require this kind of model: You have to create a factory mechanism yourself.
I have a stateless session bean, but I want to add a reference to another bean in order to do some process. So if I add reference to another bean it shows up at instance level variable like this,
#Stateless
public class AccountFacade extends AbstractFacade<Account> implements AccountFacadeRemote {
#EJB
private BillerFacadeRemote billerFacade;
public AccountFacade() {
super(Account.class);
}
... all other methods...
}
Question
Now, by definition stateless bean should not have any instance level variables. So I am quite confuse about where to put this private BillerFacadeRemote billerFacade;?
Your code is fine.
The #EJB annotation is injecting the bean into your class, and the application server manages its lifetime.
I recommend reading, or skimming the pretty long Java EE tutorial.
"The EJB container typically creates and maintains a pool of stateless session beans, beginning the stateless session bean’s lifecycle. The container performs any dependency injection and then invokes the method annotated #PostConstruct, if it exists. The bean is now ready to have its business methods invoked by a client."
It's okay for a stateless beans to have instance variables that represent dependencies.
In fact, this is even encouraged. Without instance variables you could in many situations just use static method in a utility class instead.
What however is NOT encouraged, is have instance variables representing client observeable state. That is wrong, but dependencies like the entity manager, jms queues, JDBC connections, and thus other services that your stateless service delegates (part of) its work to, is absolutely okay.
Notice that the injections are true instance injections in instance variables. It are not class level (static) injections.
The SessionContext.getBusinessObject() is described in the docs as follows,
Obtain an object that can be used to invoke the current bean through the given business interface.
Parameters:
businessInterface - One of the local business interfaces or remote business interfaces for this session bean.
Returns:
The business object corresponding to the given business interface.
Can't I use the 'this' keyword in Java instead, to accomplish the same ? How are these different ?
The motivation here is that most EJB implementations work on proxies. You wouldn't be too far off in thinking of it as old-school AOP. The business interface is implemented by the EJB container, quite often via a simple java.lang.reflect.Proxy, and this object is handed to everyone in the system who asks for the ejb via #EJB or JNDI lookup.
The proxy is hooked up to the container and all calls on it go directly to the container who will preform security checks, start/stop/suspend transactions, invoke interceptors, etc. etc. and then finally delegate the call to the bean instance -- and of course do any clean up required due to any exceptions thrown -- then finally hand the return value over through the proxy to the caller.
Calling this.foo() directly, or passing 'this' to a caller so they can make direct calls as well, will skip all of that and the container will be effectively cut out of the picture. The 'getBusinessObject(Class)' method allows the bean instance to essentially get a proxy to itself so it can invoke its own methods and make use of the container management services associated with it -- interceptors, transaction management, security enforcement, etc.