10.07.2015 Views

EJB3 Tutorial - Researcher

EJB3 Tutorial - Researcher

EJB3 Tutorial - Researcher

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Creating an EJB 3.x project withEclipse 4.2.1 JEE and JBoss AS 7.1Thomas GschwindInstallationDownload the following and unpack where you would like the tools to reside on yoursystem:• JBoss Application Server from www.jboss.org• Eclipse from www.eclipse.orgStart Eclipse and add the JBoss Tools update site and install them:1. Go to Help -> Install New Software….2. Specify http://download.jboss.org/jbosstools/updates/stable/juno/ as URL andgive it the name “JBoss Tools”.3. Select “JBoss Web and Java EE Development”, press “Next >”, “Next >”,accept the license (if you can live with it) and press “Finish”.4. Accept the fact(again if you can live with it) that some of the software you areabout to install is unsigned.5. Restart Eclipse.After Eclipse restarts, create a new “Server” project (File -> New -> Other… ->Server). Specify JBoss AS 7.1, press “Next >” and indicate the installation directory.All other settings in the wizard can be left at their defaults.Creating the EJB ProjectNext, let us create a sample “EJB Project” (File -> New -> Other… -> EJB Project).Give the project a name (note in the past spaces in the project name triggered a bug inthe tool chain, you may want to avoid them), click “Next >” the standard folderconfiguration is fine, click “Next >” again.In the EJB module settings page, you may want to select “Generate ejb-jar.xmldeployment descriptor” so that you get already a skeleton deployment descriptor ifyou plan to experiment with it. Finally, press Finish to create the project.Our First Session BeanFirst we create our first EJB. We can either use the Wizard provided by Eclipe (File -> New -> Other… -> Session Bean (EJB 3.x)) or directly create the necessary beanfiles.If you use, the wizard, make sure that the package name and class names you provideis consistent with the snippets below. In our small example, we only exhibit a remoteinterface to clients, so we want to select the “Remote” checkbox in the wizard.ch.uzh.ejb.tutorial.CookieServie: The implementation of our service.package ch.uzh.ejb.ex;import javax.annotation.PostConstruct;import javax.annotation.Resource;


import javax.ejb.PostActivate;import javax.ejb.PrePassivate;import javax.ejb.Remote;import javax.ejb.Remove;import javax.ejb.SessionContext;import javax.ejb.Stateful;/*** Session Bean implementation class CookieService*/@Stateful@Remote(CookieServiceRemote.class)public class CookieService implements CookieServiceRemote {@ResourceSessionContext context;private static String[] cookies={"Beam me up, Scotty.","He's dead, Jim.","Live Well and Prosper.","Illogical."};private int i=0;public CookieService() { System.out.println("CookieService.CookieService()"); }// Life-cycle methods@PostConstructpublic void ejbCreate() { System.out.println("CookieService.ejbCreate()"); }@PrePassivatepublic void ejbPassivate() { System.out.println("CookieService.ejbPassivate()"); }@PostActivatepublic void ejbActivate() { System.out.println("CookieService.ejbActivate()"); }@Removepublic void ejbRemove() { System.out.println("CookieService.ejbRemove()"); }}// Business methodspublic String getCookie() {System.out.println("QuoteService.getQuote()");String cookie=cookies[i];i=(i+1)%cookies.length;return cookie;}ch.uzh.ejb.tutorial.CookieServiceRemote: The remote interface of our bean.package ch.uzh.ejb.ex;import javax.ejb.Remote;@Remotepublic interface CookieServiceRemote {// Business methodspublic String getCookie();}public void ejbRemove();Our ClientNext, we need to decide where to create the EJB client. We can either do this in aseparate Java project, or in the same project we are creating the EJBs. For rhistutorial, reusing the project where we develop the EJBs will just do fine.Right-click on the project in Eclipse’s “Project Explorer” and select “Properties”.Next, select “Java Build Path” and add the following external jars to the project:• jboss-as-7.1.1\bin\client\jboss-client.jar: This jar file is needed by all clients.


• jboss-as-7.1.1\modules\org\hibernate\main\hibernate-core-4.0.1.Final.jar: Thisjar file is needed by all clients that receive JPA entities from the applicationserver. We may need this jar file for later extensions of this simple sample.The “Java Build Path” should now look as follows:Note, if you want to develop your client in a separate project, you also need to add theproject containing your EJBs to the build path of your client project.Now, we need to create the CookieService client by creating a Java class with thefollowing implementation.ch.uzh.ejb.tutorial.CookieClient: The implementation of our client.package ch.uzh.ejb.ex;import java.util.Properties;import javax.naming.Context;import javax.naming.InitialContext;import javax.security.auth.login.LoginContext;import javax.security.auth.login.LoginException;import org.jboss.security.auth.callback.UsernamePasswordHandler;public class CookieClient {private static LoginContext loginContext = null;public static void login(String user, String pwd)throws LoginException {UsernamePasswordHandler handler =new UsernamePasswordHandler(user, pwd.toCharArray());loginContext = new LoginContext("CookieService", handler);loginContext.login();}public static void logout() throws LoginException {loginContext.logout();}public static void main(String[] args) throws Exception {Properties p=new Properties();p.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");// // security props// p.put(Context.SECURITY_PRINCIPAL, "tom");// p.put(Context.SECURITY_CREDENTIALS, "passwd");// p.put("jboss.naming.client.ejb.context", true);// p.put(Context.PROVIDER_URL, "remote://127.0.0.1:4447");// p.put("jboss.naming.client.connect.options.org.xnio.Options" +// ".SASL_POLICY_NOPLAINTEXT", "false");// p.put(Context.INITIAL_CONTEXT_FACTORY,// org.jboss.naming.remote.client.InitialContextFactory.class.getName());


Context ctx=new InitialContext(p);// // these parameters are currently ignored by JBoss AS 7.1 at the moment// login("", "");String endpoint = "ejb:/CookieService//CookieService!" +"ch.uzh.ejb.ex.CookieServiceRemote" + "?stateful";CookieServiceRemote quoteService1 = (CookieServiceRemote)ctx.lookup(endpoint);CookieServiceRemote quoteService2 = (CookieServiceRemote)ctx.lookup(endpoint);String cookie = quoteService1.getCookie();if (cookie == null) {System.err.println("No cookie");} else {System.out.println(quoteService1.getCookie());System.out.println(quoteService2.getCookie());}quoteService1.ejbRemove();quoteService2.ejbRemove();// logout();}}Please note that in JBoss AS 7.1, the client needs to use a different endpointdepending on whether it interacts with a stateful or stateless EJB. The difference is“?stateful” at the end of the endpoint URL.Next we need to create a jboss-ejb-client.properties file, where we specify how anEJB client is to interact with the EJB server. This file is necessary for JBoss AS 7.1.Prior versions do not require this file. The file should contain the following lines andbe located in your root source folder. In case the client was developed as part of theEJB project, this is ejbModule. Be careful to not pace it by accident intoejbModule/ch.uzh.ejb.ex.jboss-ejb-client.properties file:endpoint.name=client-endpointremote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=falseremote.connections=defaultremote.connection.default.host=localhostremote.connection.default.port = 4447remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false#remote.connection.default.username=tom#remote.connection.default.password=passwdRunning the Sample ApplicationBefore deploying our bean, we want to start the JBoss application server by rightclicking on “JBoss 7.1 Runtime Server” in the “Servers” view of Eclipse and selecting“Start” from the popup menu. During startup, Eclipse should switch to the serversconsole and the startup messages should appear.Now, we are ready to deploy our session bean by right clicking on the “JBoss 7.1Runtime Server” (probably you have to switch back to the “Servers” view in Eclipse)and selecting “Add and Remove…” and adding the CookieService project to the listof configured projects. Again, Eclipse should switch to the server’s console view andshow the result of the deployment as shown in the following snippet. If an erroroccurs, examine the error message which should (at least with the help of yourfavorite search engine) give you an idea how to fix the error.


Console output after successful deployment:23:06:07,081 INFO[org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSCservice thread 1-1) JNDI bindings for session bean named CookieService in deploymentunit deployment "CookieService.jar" are as follows:tejava:global/CookieService/CookieService!ch.uzh.ejb.ex.CookieServiceRemotejava:app/CookieService/CookieService!ch.uzh.ejb.ex.CookieServiceRemotejava:module/CookieService!ch.uzh.ejb.ex.CookieServiceRemotejava:jboss/exported/CookieService/CookieService!ch.uzh.ejb.ex.CookieServiceRemojava:global/CookieService/CookieServicejava:app/CookieService/CookieServicejava:module/CookieService23:06:07,259 INFO [org.jboss.as.server] (DeploymentScanner-threads - 2) JBAS018559:Deployed "CookieService.jar"Finally, we are able to run the CookieClient by right-clicking its Java file andselecting “Run As” -> “Java Application” from the popup menu. If everything worksout fine, the client should display the output shown I the following code snippet.Output from CookieClient:[…output from EJB client stub omitted…]He’s dead, Jim.Beam me up, Scotty.SecurityNext, we want to add support for the Java Authentication and Authorization Serviceused by EJB to authorize and authenticate clients. First, we need to add to the serverthe information about the methods that require authorization. This is done byextending our CookieService with the annotations shown in the following codesnippet. Please note, that the following sample adds two new business methodswhose signature needs to be added to the remote interface as well.Annotations to add to the CookieService:[…]import javax.annotation.security.DeclareRoles;import javax.annotation.security.RolesAllowed;[…]@SecurityDomain("other")@DeclareRoles("admin, user")public class CookieService implements CookieServiceRemote {[…]@RolesAllowed({"user"})public int getNumberOfCookies() {return 4;}}@RolesAllowed({"admin"})public int getCookieNumber() {return i;}Note that we are using the security domain “other” which is configured as part of theapplication server. In our case this is part of the default configuration that we areusing which is defined in$JBOSSAS_HOME/standalone/configuration/standalone.xml. If we look at thisconfiguration file, we will find the username and password files that are used for


authentication. To manipulate these files, JBoss comes with a script$JBOSSAS_HOME/bin/add-user.{bat,sh} that updates the file for us. On Windows,the batch needs to be executed from within the $JBOSSAS_HOME/bin directory.Let’s add a user tom with the password passwd to the ApplicationRealm with theroles user,admin.Once we have extended our CookieService and added our new user, we need to restartour CookieService on the server. This is accomplished by right clicking on theCookieService below the JBoss 7.1 Runtime server and selecting “Restart” from thepopup menu. Note that changes to the user and password files should be picked upwithout having to restart the application server.Next let’s add a simple call to the getNumberOfCookies method in the client after allof our getCookie invocations and try to execute the client again. This time we shouldget an error that the client is not allowed to invoke the above method. In the serverconsole we should get a similar error. This is because the client is not yet properlyauthenticating to the server.The client code snippet above includes already most of the code we need forauthenticating clients. We only have to remove the comment markers in front of thesecurity properties, and in front of the login and logout statements. Note that thelogin statement takes two parameters username and password. These were valid up toJBoss 6. In JBoss 7 they are currently not honored, instead the username andpassword has to be provided as part of the properties.Next we need to provide the login.config file for the login module from the codesnippet below.etc/client.login:CookieService {org.jboss.security.ClientLoginModule required;};Additionally, the path to this login.config file has to be passed to the client as systemproperty which is most easily done using the -D option of the Java VM as shown inthe figure below. Select “Run” -> “Run Configurations…” and then adapt the runconfiguration that has already been created for our CookieService.


If we now start the client, authentication should succeed and we should be able toinvoke the methods which we are otherwise not allowed to invoke.Login ModulesIf we wanted to use a different login module, such as a module that stores theusername, password information in a database, we would have to add our ownsecurity domain to the JBoss configuration file. This might look somewhat similar tothe following code snippet:A Database Login Module:The above login module is not yet a ready to use login module and most likely needsto be changed. However, it serves as a good starting point for your favorite Internetsearch engine.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!