Here are some tips on how to tackle assignment 1 regarding distributed transactions over two JEE containers using EJB 3.0 and the GlassFish open source JEE server from Sun which we are using so far.
Your first step should be to analyse the existing project structure and to identify the function and source code location where a transfer between two accounts takes place.
This part of the source you will need to change. Several options on how to do this depending on how flexible you want be. In the one extreme case, you hard-code one account to be always the remote one (probably will not get maximum marks on the 'Design' component of the assignment). In the other, you extend the GUI and the parameters of the function and let the user enter a, say, BSB code per account. Something in between would be to have a business rule that, say, each account, whose id is in a certain range (e.g. below 1000), is located on the remote server. If you do this last approach, make sure to edit account numbers and the customer-account-relation accordingly in one of your two back-end databases.
Important: Duke's Bank assumes an US-style online banking scenario where end-users are typically only allowed to transfer money between accounts owned by the same user, but not to any other account...
For the purpose of this assignment, it is fine to assume that the same(!) user has accounts handled by two separate Duke's Bank instances. It is fine if you restrict this further to just remote Savings or Checkings accounts.
After you have decided on your application logic on where and how to decide whether a local or a remote Bank is accessed, you need to get hold of the remote application server. That is the most difficult thing of this assignment with the given application server. See Tip 3 for it.
Once you have a remote object reference, you must decide which object and method on it to invoke. There are again some choices, some more elegant than others. Rule of thumb: Try to avoid fine-grained remote entity bean access. This step also usually will involve additional exception / error handling because some new things can now go wrong which the original code does not cater for.
Finally, transaction semantic: You have to take care of two things here: That a transaction with the right boundaries is used in the first place; and that the data stores - both the local and the remote - are configured to be able to participate in a 2-Phase-Commit protocol (Tip: XA interface...)
There are two principle ways on how to bind to a remote EJB from within a Java application server. Unfortunately, both have some hiccups or run into bugs with the current version of the GlassFish application server...
This is the preferred approach for EJB 3.0 (which we are using), BUT it will run into a GlassFish bug at the end of a 2PC commit... (at least up to there it should work ;})
import javax.ejb.EJB;
@EJB(mappedName="corbaname:iiop:REMOTE-HOST:3700#RemoteObjectType")) RemoteObjectType remoteBank;The Java application server will now automatically look up this remote object and create a stub object to the remote server under the name remoteBank in your program. You can thereafter just normally use the remoteBank object according to its interface specification. Note: No manual new() or lookup() call is needed anymore.
The second approach is to do this remote object lookup manually. There are some code snippets on the Internet which explain various variants of it. However, they all assume that you access a JEE container object from a standalone Java application. In our case however, we try to call from one GlassFish JEE server to another - and again we seem to run into some limitations of that current version...
import java.util.Properties; import javax.naming.Context; import javax.naming.InitialContext;
try
{
Properties p = new Properties();
p.setProperty("java.naming.factory.initial", "com.sun.enterprise.naming.SerialInitContextFactory");
p.setProperty("java.naming.factory.url.pkgs", "com.sun.enterprise.naming");
p.setProperty("java.naming.factory.state", "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
p.setProperty("org.omg.CORBA.ORBInitialHost", REMOTE-HOST);
p.setProperty("org.omg.CORBA.ORBInitialPort", "3700");
InitialContext ctx = new InitialContext(p);
RemoteObjectType remoteBank = (RemoteObjectType) ctx.lookup(RemoteObjectType);
}
catch ( required exceptions... ) { ... }
After that, you should be able to use remoteBank as normal. However: When we tried it on our own GlassFish installation ,we always got returned a lookup from the local JNDI, as if the properties for the ORB call were ignored... I tend to count this also as a GlassFish bug, but have not found a corresponding bug description yet... if anyone has success with this method (2), please drop us an email ;)
See also the official FAQ for the GlassFish JEE container that we are using...
But note that it never really talks about JEE - to - JEE communication, but always assumes standalone Java program to JEE server...
Two JEE application servers can communicate via remote procedure call over IIOP (Inter ORB Protocol); bot the JNDI lookups on remote servers and the invocations of methods on remote servers use this IIOP protocol, which means that one port serves both cases. The standard IIOP for GlassFish port is 3700.
If you try things on you own computer, be sure that this port is not blocked...
In Netbeans, open you project and navigate to the Sources of the 'request' module; open the configuration tab and edit the ejb-jar.xml file:
It will look something like this:
<sun-ejb-jar> <enterprise-beans/> </sun-ejb-jar>
Replace the empty
part with this:<enterprise-beans>
<ejb>
<ejb-name>TxControllerBean</ejb-name>
<jndi-name>My Super New Name</jndi-name>
</ejb>
</enterprise-beans>
Make sure that your two containers can run a 2-Phase-Commit protocol over the involved data sources. The Derby instances that come with our installation are by default not configured to accept 2PC via XA... You need to configure them in the application server correctly (correct type and correct driver!).
Make sure you have configured the very same java application user name in each JEE application that should talk to each other - with the same password! So in our case, for example, following the notes from tutorials in week 2 etc, there should be a user 200 with the same password configured in both application servers that are communicating with each other.
Also make sure that there is no OS-level security enabled for the IIOP connection. That is actually the default, so should not be changed! IIOP security should be kept disabled.