I want to have a bean Foo in host A which is injected, by the #EJB annotation to a bean Bar in host B.
Both these hosts are separate stand-alone instances of Glassfish-v3.
When reading the Glassfish docs I found a lot of info, some of it sounded a bit contradicting.
I understood that every bean has a global jndi named assigned to it and understood how it is constructed, What is the syntax for portable global JNDI names?. I also understood that the the declaration of Foo in Bar should be something of this sort (assuming FooRemote is the remote business interface of Foo and fooejb is the its module): #EJB(lookup=java:global/fooejb/FooRemote) FooRemote foo, this is based on this.
What I can't understand is where I tell host A and host B to get to know each other.
I saw a lot of examples for application clients and application servers but I wasn't able to find an example for such a scenario.
In this question a sun-web.xml and Global-JNDI is mentioned but I think that it's not EJB3.1 (since it's not Portable JNDI) and I don't understand where this sun-web.xml should reside (I'd like to avoid it if I can).
It is mainly different in two ways:
There is no -Dorg.omg.CORBA.ORBInitialHost= param option (as far as I can see)
Any solution should of course allow the inclusion of a third host C which both A and B communicate with for different purposes.
I have a strong feeling I'm missing something basic here and I'd really appreciate pointers to what I'm missing.
BTW, I'd like to avoid as much as possible from descriptor files and such and leave most info on annotations and only the host ip's to config in the server.
Edit:
I think another interesting aspect of this question is how load-balancing is used in this aspect, i.e. let's say I have A1 and A2 servers which are the same, how will load-balancing occur with respect to routing the request from B to either A1 or A2
Edit2:
I think this might be unrelated to ejb 3.1 but related to the basis on how to enable two application servers to see each other's jndi registry. I think this is unrelated to ejb 3.1 as it seems a similar problem exists in the 3.0 with the Global not portable jndi.
I would imagine some configuration in each app server would allow me to configure which other "neighbours" it should query for jndi remote beans.
Hope that gives a clue to someone out there.
Thanks,
Ittai
With regards to EJB Load balancing you might like to take a look at this blog:
http://www.techpost.info/2010/12/ejb-load-balancer_7304.html
As stated in one of the pages you link to, when using a cluster then you don't need extra configuration to get this to work. If you need load balancing etc. I'd imagine it is easier to set up a cluster up than doing it manually.
sun-web.xml goes right next to web.xml in WEB-INF if you deploy it as a web project in .war file.
I would think you should be able to get it right using:
http://glassfish.java.net/javaee5/ejb/EJB_FAQ.html#cross-appserverremoteref and http://glassfish.java.net/javaee5/ejb/EJB_FAQ.html#mappingRemoteejbdependency
I would have thought there must be an easy way to configure a EJB connector or Resource adaptor in glassfish itself using the administration console or editing the server.xml. But I can't find such a thing now.
We are using remote EJBs and it works fine.
First you'll need the EJB on "Host A" wich implements an interface whose class is present on both hosts.
//For host A + B
public interface FooClass {
public void theMethod();
}
//Only for host A
#Stateless
public class FooClassImpl implements FooClass {
public void theMethod(){//Code goes here}
}
Then you'll need to create (on Host B) a glassfish-web.xml in your WEB-INF directory, where you specify where a remote EJB is located:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app error-url="">
<ejb-ref>
<ejb-ref-name>RemoteEJBName</ejb-ref-name>
<jndi-name>corbaname:iiop:<servername or IP>:3700#java:global/<projectname>/FooClassImpl!com.test.foo.FooClass</jndi-name>
</ejb-ref>
</glassfish-web-app>
At the injection point on Host B you'll need to inject the EJB like this:
#EJB(name = "RemoteEJBName")
private FooClass theFooClassInstance;
I hope this will do the trick.
Related
I am trying to do a lookup from one deployment to another deployment, using exactle the same bean implementations. It is basically a consumer/producer setup with the same beans in both deployments on both machines.
ear
ejb-api
com.example.bean
ConsumerBean
ProducerBean
ejb-jar
com.example.bean
ConsumerBeanRemote
ProducerBeanRemote
The ProducerBeanRemote should look up the ConsumerBeanRemote and call its public method.
Our machines are communicating like this:
(Machine A) ProducerBeanRemote --> (Machine B) ConsumerBeanRemote
(Machine A) ProducerBeanRemote --> (Machine C) ConsumerBeanRemote
(Machine A) ProducerBeanRemote --> (Machine D) ConsumerBeanRemote
You get the idea...
So the problem is, it doesn't work. I tried to do a manual lookup using the jboss-as-ejb-client libraries, which didn't work because JBoss locks the EJB selector while starting its container (AND I bet the spec has something to say about manual lookups in a Java EE environment). The next thing I tried was doing a lookup using the feature from Spring, to no avail.
We are using the JBoss Application Server 7.1.1.Final.
I bet there has to be a way to accomplish my setup and I would greatly appreciate any help from the community.
UPDATE:
To connect from ProducerBeanRemote to ConsumerBeanRemote, we need the possibility to specify the remote InitialContext at runtime via configuration.
Properties properties = new Properties();
properties.put("remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED", "false");
properties.put("remote.connections", "default");
properties.put("remote.connection.default.host", "remote-host");
properties.put("remote.connection.default.port", "4447");
properties.put("remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS", "false");
EJBClientConfiguration ejbClientConfiguration = new PropertiesBasedEJBClientConfiguration(properties);
ContextSelector<EJBClientContext> ejbClientContextSelector = new ConfigBasedEJBClientContextSelector(ejbClientConfiguration);
EJBClientContext.setSelector(ejbClientContextSelector);
StatelessEJBLocator<T> locator = new StatelessEJBLocator<>(viewType, appName, moduleName, beanName, distinctName);
return EJBClient.createProxy(locator);
The resulting exception is
java.lang.SecurityException: EJB client context selector may not be changed at org.jboss.ejb.client.EJBClientContext.setSelector(EJBClientContext.java:181)
We understand that this exception is thrown because of https://issues.jboss.org/browse/AS7-2998, so the question remains: How can we remotely call the same beans in a clean and configurable way?
Nearly the same question as described here: JNDI lookup from one server to many configurable servers
It seems to be impossible to get a reliant connection between multiple servers via EJB, so we ended up using JMS for our server to server communication. Maybe thats an option for you, too.
You didn't tell me much about your setup or any errors you're getting so I can't really help you troubleshoot them. I just struggled through getting a remote ejb client to work as well and these resources were absolutely invaluable:
https://docs.jboss.org/author/display/AS72/EJB+invocations+from+a+remote+client+using+JNDI
https://docs.jboss.org/author/display/AS71/Remote+EJB+invocations+via+JNDI+-+EJB+client+API+or+remote-naming+project
http://blog.jonasbandi.net/2013/08/jboss-remote-ejb-invocation-unexpected.html#comment-form
http://www.mastertheboss.com/jboss-as-7/jboss-as-7-remote-ejb-client-tutorial/page-2
Good luck!
The setup is possible. There is no need to reengineer the whole code using JMS.
It is possible to call remote ejb beans on different JBOSSAS7 servers from a single POJO client using your own custom Selector for the EJBClientContext. With the code mentioned, you are able to register different scopes for different servers
See an example from the jboss developers here
https://community.jboss.org/thread/223419?tstart=0
https://github.com/wfink/jboss-as-quickstart/blob/ejb-clients/ejb-clients/jboss-api/src/main/java/org/jboss/as/quickstarts/ejb/clients/selector/CustomScopeEJBClientContextSelector.java
I would be very much thankful to clear me some question about this new EJB3.0 and above version:
1) if suppose I need ejbCreate, ejbActivate and all other events so how can I get it from the new EJB3.0 and above ver.
2) I always have problem to find particular xml file to alocate a JNDI name according to variety of Application Servers so is there any way that I can give JNDI name without xml file and can also be use a portable name that in every Application Server it can be findable of EJB deployed on app server remotely
3)Can any buddy tell me, i have hosting plan of Java/Linux which supports
i) Tomcat - 5.5.xSupport
ii)JDK - 1.6.x Support
iii)JSP/servlet - 2.0 Support
can it be possible that EJB 3.1 be deployed because some where i have got that tomcat is not able to deploy EJB so please give me some advice help...
Thank You...!!!
please Help me...!!!
1) if suppose i need ejbCreate, ejbActivate and all other events so
how can i get it from the new EJB3.0 and above ver.
In EJB 3 and above, the EJB lifecycle is handled through life cycle annotations, such as: #PostConstruct and #PreDestroy.
2) i always have problem to find perticular xml file to alocate a JNDI
name according to variety of Application Servers so is there any way
that i can give JNDI name without xml file and can also be use a
portable name that in every Application Server it can be findable of
EJB deployed on app server remotly
The #Stateless and #Stateful annotations have two attributes that might solve this issue (name and mappedName). Yet
The mapped name is product-dependent and often installation-dependent.
Hope it helps you.
1) ejbCreate, ejbActivate etc. are related to EJB 2.x, if you need similar functionality in EJB 3.x, you should decorate your methods with annotations #PostActivate, #PrePassivate etc. Method signature should follow certain rules, example for #PostActivate:
The method annotated with #PostActivate must follow these
requirements:
The return type of the method must be void.
The method must not throw a checked exception.
The method may be public, protected, package private or private.
The method must not be static.
The method must not be final.
This annotation does not have any attributes.
2) It seems that you're referring to name and mappedName attributes of #Stateless and #Stateful annotations. For more details see official documentation. From my experience mappedName is better, but it's application-server-specific, e.g. on Glassfish it works perfectly. Example:
#Stateless(mappedName="ejb/myBean")
public class MyFirstBean {
..
}
Since no one answered Question 3 ..
3)Can any buddy tell me, i have hosting plan of Java/Linux which supports i) Tomcat - > 5.5.xSupport ii)JDK - 1.6.x Support iii)JSP/servlet - 2.0 Support
No, you are going to need a server that supports Java EE. Read How to deploy EJB based application on Tomcat
We have developed a JEE5 web application (WAR) and running it in production under WebLogic 11g (10.3.5).
Now the same application should be deployed as separate applications for different customers (different URLs, different data) on the same WebLogic.
I managed the first part by setting different context roots after deployment for each of them.
But I have yet to make them use different datasources - and since I want to avoid customer specific builds, the persistence.xml is the same for all applications, thus also the persistence unit name.
What is the best setup for this scenario? Am I forced making separate builds and by that different WARs or do I have to separate Managed Servers or Domains wihtin the server or is there a better way to solve it?
I know this thread is very old,but replying so that it may help someone with the same question stumbling on this thread.
The latest weblogic 12.2.1 comes with Multi-tenancy(add-on I guess) which can let you run same applications in a single domain.
Edit: Weblogic 12.2.1 introduced concept called Partitions. Partitions are both config and run-time subdivision of a weblogic Domain. In a single weblogic domain you can create multiple partitions. Each partition will have one or more resource groups. Resource groups are the logical grouping of weblogic resorces like data sources,jms,Java EE apps ,etc. For example to achieve what the original posts asked for , we create a Resource Group template with the web-application and the datasource as the resources. In the Data source configuration we can provide a place holder variable instead of actual URL as DB URL. Then we can create two partitions that refers to this Resource Group Template(Each partition will now have a separate web application and data source) . Each partition will override the DB URL property there by creating two data sources with same JNDI name.In each Partition we create virtual host/port so that the client can use that to access the application running in the respective partitions.
A better and more detailed information on this can be found in https://blogs.oracle.com/WebLogicServer/entry/domain_partitions_for_multi_tenancy
ServletContextListener.contextInitialized can look at the ServletContext and figure out which deployment is which
in web.xml, define a servlet context listener:
<listener>
<listener-class>com.path.YourServletContextListener</listener-class>
</listener>
and then in YourServletContextListener.java, add a contextInitialized method like this:
public void contextInitialized(ServletContextEvent sce)
{
ServletContext sc = sce.getServletContext();
String name = sc.getContextPath();
...
}
my thought is that you can use that name to select from multiple data sources that you have configured. depending on how you've been deployed, you'll make a different database connection and have the correct application's data.
It seems to me from what I saw in the Oracle documentation, that having several domains is the only way to separate data sources with the same persistence unit name - which is bad, since this basically means running two WLS in parallel.
For this reason I decided to go with building individual WAR files (which I tried to avoid initially), to include customer-specific persistence.xml files and specifying customer-specific datasources in the WLS.
we are developing a set of components that can be used by our applications which currently run on Jboss 4.2.3.GA.
However, since JBoss 4 is quite old now, we'd like to migrate to JBoss 5+ (most likely JBoss 6.1).
In that case, we have a problems with our components containing stateless session beans annotated with the JBoss specific #PoolClass annotion, which has been renamed to #Pool as of JBoss 5.
As you can see, using that annotation in the components introduces a dependency not only on the application server but on specific versions as well. Thus I'd like to get rid of that annotation and use configuration via XML.
In that case, I'd like not to have to define a pool class per session bean, since almost all of them use the StrictMaxPool class with the same settings. If any session bean needs a different pool or different setting, it's ok to provide a specific entry, but I'd rather not do that for the majority.
The default pool class is generally defined in ejb3-interceptors-aop.xl. However, that configuration applies to all applications deployed on that server.
What I'd like to do now, is to define a default pool class (with default settings) per application, if possible without adding anything specific to the session beans in our components (like the JBoss specific #AspectDomain annotation).
Is that possible and if yes, how?
I couldn't manage to find any useful information yet, so I'd be glad if someone could point me in the right direction.
Edit: If you have information on how to do that in JBoss 5+, that would be great too, but JBoss 4 is of higher priority for now.
Seems like I found a solution:
There's a problem with JBoss AOP 1.5.6 which is used by JBoss 4.2.3.GA.
Although there's no bug filed it seems there is one preventing the scoped use of pool definitions (it looks like the source of the problem is an inverted if-condition :) ).
Upgrading to JBoss AOP 2.1.8 works like a charm.
Here's what I do:
Put a jboss-aop.xml file into the root of an ejb jar in the ear (we already have one that contains our persistence.xml).
In the jboss-aop.xml create a domain Stateless Bean that extends from the default Stateless Bean domain and inherits all bindings and definitions
Inside the extended domain override the pool class definition.
I know that for JBoss you need a [name]-ds.xml file in the /deploy subdirectory of the appropriate instance.
i dont have any experience with other Java EE containers, but im trying to stick to standards as much as possible.
is there a standard way to define a JDBC datasource and deploy it ? if possible i'd like to include my datasource inside the *.ear file (for instance, an embedded in-memory HSQLDB datasource for demo purposes) ?
if there is no standard way, will other containers at least accept the jboss way ? (/deploy/*-ds.xml)
Is there a standard way to define a JDBC datasource and deploy it?
Yes, there is. It's done via the <data-source> element, which you can put in web.xml, ejb-jar.xml and application.xml. If you don't like XML, you can also use an annotation for this instead: #DataSourceDefinition
Example of a web.xml entry
<data-source>
<name>java:app/myDS</name>
<class-name>org.postgresql.xa.PGXADataSource</class-name>
<server-name>pg.myserver.com</server-name>
<database-name>my_db</database-name>
<user>foo</user>
<password>bla</password>
<transactional>true</transactional>
<isolation-level>TRANSACTION_READ_COMMITTED</isolation-level>
<initial-pool-size>2</initial-pool-size>
<max-pool-size>10</max-pool-size>
<min-pool-size>5</min-pool-size>
<max-statements>0</max-statements>
</data-source>
Further reading:
Introducing the DataSourceDefinition Annotation
The state of #DataSourceDefinition in Java EE
Example application use standard data source
p.s. I'm surprised all other answers say this doesn't exist, while it clearly does, even at the time this question was originally asked.
Is there a standard way to define a JDBC datasource and deploy it ?
No, this is container specific. As Application Component Provider, you're supposed to document the resources you need and the Application deployer and Administrator will configure them.
If there is no standard way, will other containers at least accept the JBoss way?
No, because this is the JBoss way and thus JBoss specific.
With Tomcat, you would have to use the context.xml file.
With Jetty, jetty-env.xml.
With WebSphere, you can create a so called WebSphere Enhanced EAR.
With WebLogic, you can package a JDBC Module in your application.
With GlassFish, you can use the command asadmin add-resources my.xml to add a datasource described in a XML file (example here).
Etc, etc.
Note that there are some projects trying to achieve this goal in a universal way like jndi-resources or Cargo. There are also more complex solution like ControlTier or Chef.
Now, in your case (as I understood you want to use an embedded database that will be bundled with your application), I don't think you should configure a datasource at the application server level. You should just package the jar of your database in your application with a standalone connection pool like c3p0 or DBCP.
Sun's Java EE philosophy defines several roles in the design, development and deployment of an enterprise application. Java EE design accommodates and reflects these separations of concerns.
In particular Sun wants to separate the developer from the administrator of an application, which is a good idea. The developer writes enterprise components in a container-agnostic way. In web.xml, for example, you do declare your DataSources in a standard way:
<resource-ref>
<res-ref-name>jdbc/myDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
This says "this database thing the application needs, make it available to me, whatever database is and whatever container you're running it in, via standard JNDI at 'jdbc/myDB' ". This is as much as the developer can do -- the rest is necessarily container specific and therefore not standardized.
And then how "myDB" is actually configured is up to a different role, the administrator of the container.
So I'm repeating the correct answer above: no. But the reason is, otherwise, you'd be coding your app to a specific type of database on a specific host and port, and the point is that you shouldn't be able to do that, so there's no standard support for that on purpose.