Turn Managed bean into EJB - java

Is it possible to turn a Managed bean into an Enterprise Managed Bean? Would you give some example?

For turning a POJO bean class into an EJB, add the #Stateless of #Stateful annotation and implement the #Remote or #Local (or both) interfaces. Of course some additional configuration steps will be necessary, but that depends on the particular application server you're using.
Do something along these lines:
#Local
public interface ServiceLocal {
}
#Remote
public interface ServiceRemote {
}
#Stateless
public class ServiceEJB implements ServiceLocal, ServiceRemote {
}

If you have a valid scenario where you want to use an EJB as your backing bean, then yes you can do it. JBoss Seam would help you in this. Check out this for more information.

Related

Demistifying EJB annotations and injection

I'm currently puzzled with the way Glassfish 3.1.2.2 handles EJBs.
I have an OSGi project, which consists of many OSGi bundles (jars). Also, there are a few WARs, including a Tapestry web application.
In one such bundle, let's call it "interfaces.jar", I have an interface defined:
public interface MyInterface() {
public static final String JNDI_NAME = "java:global/MyInterface";
void myMethod();
}
The implementation of that interface is as following, and it's contained in bundle "beans.jar":
#Stateless
#EJB(name = MyInterface.JNDI_NAME, beanInterface = MyInterface)
public class MyBean implements MyInterface() {
void myMethod() {
...
}
}
I am calling it from my Tapestry WAR app via JNDI lookup:
InitialContext.doLookup(MyInterface.JNDI_NAME);
Now, I was reading EJB 3.1 specification, and it says that I can one of the following scenarios:
Interface has #Local annotation; EJB is implementing this interface.
Interface is a plain Java interface without annotation; EJB with #Local annotation is implementing it.
Interface is a plain Java interface without annotation; EJB is implementing it.
Interface is a plain Java interface without annotation; EJB with #Local annotation is not implementing it.
EJB doesn’t have any special annotations.
So, by elimination:
I don't have #Local on interface
I don't have #Local on EJB
Seems somewhat right
I don't have #Local on EJB
I have #EJB annotation on my EJB
So, it seems that it's case 3:
"Because it’s the only implemented interface of the EJB, a container assumes that it must be a local business interface."
Now, a few questions:
Is my interface a local or remote one, since there is no local or remote annotation?
If it is local, I should be able to inject it with #EJB annotation, but it fails?
If it's remote, it is not in compliance with the explanation a few lines above?
If I add either #Local or #Remote, and perform JNDI lookup, I get a naming exception and NPE telling me there is nothing under that JNDI_NAME. How is that possible?
What exactly does #EJB(name = ..., beanInterface = ...) do on bean class and how does it interact with #Local and #Remote annotations?
1.)
First, let's see your example without the "unnecessary" #EJB annotation
#Stateless
public class MyBean implements MyInterface() {
void myMethod() {
...
}
}
You can now see clearly, that the EJB implements only one interface. As you mentioned in the 3rd points, "Interface is a plain Java interface without annotation; EJB is implementing it.", so MyInterface is a Local Business Interface of the MyBean EJB.
2.)
You use wrong JNDI name for the lookup:
#Stateless
public class MyBean implements MyInterface() {
...
The global JNDI name of your EJB:
java:global[/app-name][/module-name]/MyBean[!interface-name]
The interface-name is "MyInterface", but it is optional if there are no other business interfaces for your beans, like here, so you can skip it.
You have to figure out what the application- and module-name is for your bean in case of OSGI.
In a simple EJB application, the application-name is the name of the .ear file, and the module-name is the name of the .war/.jar file. application-name can be skipped if your module is not packaged in an ear.
So for example:
new InitialContext().lookup("java:global/myModuleName/MyBean");
5.)
#Stateless
#EJB(name = "MyInterface", beanInterface = MyInterface.class)
public class MyBean implements MyInterface() {
void myMethod() {
...
}
}
Here the #EJB annotation creates an EJB and put a reference to it into the Environment Naming Context (ENC). So it does nothing with the MyBean EJB, just expand its ENC with a new entry.
So from the business method of the current bean you can lookup for that new entry:
void myMethod() {
new InitialContext().lookup("java:comp/env/MyInterface")
}
You can locate the bean's ENC by "java:comp/env/" JNDI name.
As you can see, the name parameter defines the name of the entry in the ENC.
The beanInterface defines the Business Interface of the created Bean. If the Bean has more business interfaces, then you have to define beanName too, so the container could determine wich Bean you would like to create.
You can read about this topic here:http://thegreyblog.blogspot.hu/2010/09/introduction-to-ejb-30-injection-and.html

can both "LocalBean" and "Remote" be annotated on one bean?

I know it might sound elementary, but i'm wondering the following singleton bean:
#Startup
#Singleton
#LocalBean
public class MyServiceBean {
public String sayHello() { return "Hello"; }
}
Now i think "remote" clients might need use this bean, so I want to add a Remote interface to this bean:
#Remote
public interface MyService {
String sayHello();
}
Can I just make my bean implements the new remote interface?
If "MyServiceBean" implements the "MyService" remote interface, it will become a bean with a "remote-interface-view" ... but after I searched the web, you all said that a bean with annotation "LocalBean" is a "no-interface-view".
Is that able to work? or should I create a Local interface and remove the LocalBean annotation?
deeper thoughts... if "remote-view", "local-view" and "no-interface-view" are 3 types of view which can all exist in one bean....? can i have a bean that implements all of them?
#Local
#Remote
#LocalBean
public class Possible implements PosLoca, PosRemote {}
.... i'm really confused...
Yes, it is possible for a bean to expose multiple views (Remote business, Local business, no-interface).
The component can be the same - you just add another ways of accessing it.
Take a look at EJB 3.1 FR specification:
4.4.2.2 Session bean exposing multiple client views (p. 86).
package com.acme;
#Singleton(name="Shared")
#LocalBean
#Remote(com.acme.SharedRemote.class)
public class SharedBean { ... }
One note - I don't think the example you posted will work out-of-the-box. You're using #Remote and #Local without specifying the interface references. I don't think the container will now which interface is what. Either specify the #Remote(clazz) or annotate the interface itself as #Remote.

#Local interface with many realisation

I have #Local interface
#Local
public interface IRepo
{
and two realisation, but only 1 bean realisation
#Stateless(name = "RepoBean")
public class RepoBean implements IRepo
{
second
public class SimpleRepo implements ILogRepositoryIRepo
{
and inject it ti my Web service using
#EJB(name = "RepoBean")
private IRepo repository;
And it's works well on jboss and on WebLogic. But on GlassFish 3.1.1 I get Error (while deploying)
Cannot resolve reference Local ejb-ref name=RepoBean,Local 3.x interface =com.company.IRepo,ejb-link=null,lookup=,mappedName=,jndi-name=,refType=Session because there are 2 ejbs in the application with interface com.company.IRepo.
But I have only 1 ejb realisation.
Any ideas? May be I can use some deployment-desriptor or something else.
EJB 3.0, Java EE 5
I really didn't understand what you're trying to do, but if you have two beans that implement the same business interface, you'll have to use the 'beanName' attribute as follows:
#EJB(beanName = "RepoBean")
private IRepo repository;
-- UPDATE
Look at this: java.net/node/702013. There is a bug issue to this problem: java.net/jira/browse/GLASSFISH-11684
Seems like this only occurs with EJB-in-WAR packaging. In ejb jar doesn't happen.
Well, Glassfish is more right than JBoss and WebLogic, Business-Bean-Classes should all have their own EJB-Local-Interface.
I Guess WL or JBoss will give you a warning instead of an error.

Cannot find EJB beanName on deploy

Hi #All :) I have a strange problem here. I want to inject UserBean managed entity in a class with the #EJB(beanName="user"). If I don't use the beanName attribute I get the following error message:
org.jboss.as.server.deployment.DeploymentUnitProcessingException: No component found for type 'defaultPackage.UserBean' with name null
If I use it like so #EJB(beanName="user") UserBean user; I get this:
org.jboss.as.server.deployment.DeploymentUnitProcessingException: No component found for type 'defaultPackage.UserBean' with name user
What am I doing wrong ?
Here is the UserBean and how I inject it:
UserBean
// removed imports
#ManagedBean(name="user")
#Local
#SessionScoped
#Entity
#Table(name="t_user")
public class UserBean implements Serializable, UserInterface{
// fields (#Columns, etc.)
// setters / getters
}
UserBeanUser
// more removed imports
#ManagedBean(name="userUsed")
#Stateful
#Local
public class UserOfUserBean implements Serializable, Userable {
private #EJB(beanName="user") UserBean user;
}
The interfaces are empty and are marked as #Local.
I'm sorry, but this is wrong on so many levels that it's hard where to begin.
To start, the #Local annotation is useless on the code you show. It's used to mark an interface as a business interface for an EJB, or point to such an interface.
Then, the entity UserBean should probably not be scoped and a managed bean. These annotations are for letting the bean container manage the life-cyle of a bean, but in case of an entity it's the entity manager that is responsible for that.
It's not clear whether you used the JSF or Java EE ManagedBean annotation here, but the latter is never needed and the first shouldn't be needed as per the above explanation.
Additionally, per the typical conventions consider naming an entity just User and don't let it implement an interface.
UserOfUserBean is even harder to decipher. Is this bean supposed to be a business service or a (JSF) backing bean? If it's a backing bean, you don't need the #Stateful annotation and otherwise you don't need the #ManagedBean one.
Then, the major culprit of your question: the #EJB annotation can't inject non-EJB beans. JPA entities (#Entity) and JSF managed beans (#javax.faces.bean.ManagedBean) are not EJB beans.
Furthermore, the beanName attribute of #EJB does not correspond to the name attribute in #ManagedBean. The bean name is an EJB internal thing used to disambiguate an injection if an interface is implemented by multiple beans and has no relation to either the JSF managed bean name or the Java EE managed bean name. (not applicable to your question, but there is a relation between CDI's #Named and JSF's managed bean name)
Finally, entities nor backing beans need empty interfaces that are marked as #Local.
So, your entity should become something like:
#Entity
#Table(name="t_user")
public class User implements Serializable {
// fields (#Columns, etc.)
// setters / getters
}
And you should forget about injecting the entity the way you did. If you want to make it available in the HTTP session, put it there manually (e.g. after logging in). See this answer for a more elaborate explanation on how to do that: https://stackoverflow.com/a/6355064/472792
Assuming your UserOfUserBean was a backing bean, it would then become something like this with CDI:
#Named(name="userUsed")
public class UserOfUserBean {
#Inject
#LoggedIn // see answer from jan groth
private User user;
}
or with JSF annotations only:
#ManagedBean(name="userUsed") // from javax.faces.bean, not javax.annotation
public class UserOfUserBean {
#ManagedProperty("#{user}")
private User user;
// Mandatory setter for JSF-native injection
public void setUser(User user) {
this.user = user;
}
}
Some additional resources:
Contexts and Dependency Injection in Java EE 6
How do CDI and EJB compare? interact?

How to inject one EJB 3.1 into another EJB

I'm developping simple app where one EJB should be injected into another. I'm developping in IDEA Jetbrains IDE. But after i make #EJB annotation in Ejb local statless class my IDE highlight it with error:
EJB '' with component interface 'ApplicationController' not found.
Can anyone tell Why?
Injection of an EJB reference into another EJB can be done using the #EJB annotation. Here is an example taken from Injection of other EJBs Example from the OpenEJB documentation:
The Code
In this example we develop two simple
session stateless beans (DataReader
and DataStore), and show how we can
use the #EJB annotation in one of
these beans to get the reference to
the other session bean
DataStore session bean
Bean
#Stateless
public class DataStoreImpl implements DataStoreLocal, DataStoreRemote{
public String getData() {
return "42";
}
}
Local business interface
#Local
public interface DataStoreLocal {
public String getData();
}
Remote business interface
#Remote
public interface DataStoreRemote {
public String getData();
}
DataReader session bean
Bean
#Stateless
public class DataReaderImpl implements DataReaderLocal, DataReaderRemote {
#EJB private DataStoreRemote dataStoreRemote;
#EJB private DataStoreLocal dataStoreLocal;
public String readDataFromLocalStore() {
return "LOCAL:"+dataStoreLocal.getData();
}
public String readDataFromRemoteStore() {
return "REMOTE:"+dataStoreRemote.getData();
}
}
Note the usage of the #EJB annotation
on the DataStoreRemote and
DataStoreLocal fields. This is the
minimum required for EJB ref
resolution. If you have two beans that
implement the same business
interfaces, you'll want to the
beanName attribute as follows:
#EJB(beanName = "DataStoreImpl")
private DataStoreRemote dataStoreRemote;
#EJB(beanName = "DataStoreImpl")
private DataStoreLocal dataStoreLocal;
Local business interface
#Local
public interface DataReaderLocal {
public String readDataFromLocalStore();
public String readDataFromRemoteStore();
}
(The remote business interface is not
shown for the sake of brevity).
If it doesn't work as expected, maybe show some code.
I believe it's an IntelliJ IDEA bug. This thread solved the problem for me:
adding a EJB Facet (in project structure > modules) helped

Categories