JavaEE6 Weblogic exercice 2

De $1

Version de 05:00, 22 Nov 2024

cette version.

Revenir à liste des archives.

Voir la version actuelle

Introduction

This time we will look at new features of Java EE6/JPA:
 

  1. Build an Enterprise project, not a "web profile project",
  2. Write an remote EJB and test a standalone remote client (not a Servlet),
  3. Write a bank account management web application that will generate and update the database schema as we update the code of the entity classes,
  4. Use JPA relationships

Create an EAR project, an EJB project and a Dynamic Web/JPA project

An Enterprise Application project (EAR) is a "composite" project, a container that will hold several other projects and deploy all of them at once in a .ear archive.

Typically, an EAR project will be attached with several other subprojects such as:

  • EJB projects,
  • Dynamic web projects (maybe with JPA facets),
  1. So, let's do it. Create a new project of type "enterprise application project" called DemoEAR. For the moment, do not set anything, just click finish. We create this project first as when we will create the subprojects, we will speficy that they belong to this EAR project.
  2. Create an EJB project, call it "DemoEJB", indicate under "EAR Membership" that you want to attach it to the EAR project from step 1, notice that a DemoEJBClient project is automatically added too. More on that later.
  3.  Add a JPA facet to the EJB project you just created, 
  4. Create a Dynamic Web project,  name it "DemoWeb", indicate  under "EAR Membership"  that you want to attach it to the EAR project from step 1, click next until the last screen and check "generate web.xml",

So, you should get 4 projects: DemoEAR, demoEJB, demoEJBClient and demoWeb. You can check that everything is ok by looking at the properties of the DemoEAR projec, then look at "Deployment Assembly", you should see that the 3 other projects are in the assembly.

Add a remote EJB to the dynamic web project

Add a session bean stateless but this tome check the "remote interface" option, and indicate for the name of the bean " DemoSessionEJB" and for the remote interface you should see that the dialog proposes automatically DemoSessionEJBRemote. Add an hello world method to the bean, like we did at the beginning of exercice one, yesterday.

The code should look like that: 

package sessions;

import javax.ejb.LocalBean;
import javax.ejb.Stateless;

/**
* Session Bean implementation class DemoSessionEJB
*/
@Stateless
@LocalBean
public class DemoSessionEJB implements DemoSessionEJBRemote {

public String helloWorld() {
return "hello world !";
}
}

Notice that the bean implements DemoSessionEJBRemote , and that this interface has been automatically added to the DemoEJBClient project. This "generated project" is useful for standalone clients, as we will see now...

Add the helloWord() method to the remote interface, in the file DemoSessionEJBRemote.java, from the DemoEJBClient project. The code should look like that:

package sessions;

import javax.ejb.Remote;

@Remote
public interface DemoSessionEJBRemote {
public String helloWorld();
}

At this stage, save all and deploy the EAR project to weblogic using right click on the server in the server tab of the Java EE perspective, and use the add/remote menu.

It is important to deploy this project as we will need the JNDI name of the EJB we created, and this JNDI name is available from the weblogic admin console.

Look for the JNDI name of the EJB in Weblogic console

 You can do that by looking at the weblogic admin console, on the left, click on "base_domain", then "servers", then in the main page click on the name of your server, then in the main window you should have something like "JNDI tree"... Click on that, a new tab opens in which you can explore the names objects on your server. In the small tree, click on "weblogic" then you will find your application and the EJBs deployed. The "liaison name" of the EJB is the JNDI name. It should look like this: " java:global.DemoEAR.DemoEJB.DemoSessionEJB!sessions.DemoSessionEJBRemote "

We will use this JNDI identifier in the standalone client... 

 

Write a standalone client for this EJB

A standalone client is just a Java project with a java class (with a main) that uses the remote EJB we created. 

The client project is just a Java project. Create a new project of type "Java project", name it "DemoEJBClientStandalone".   

You must add two things in the build path so that the client code can compile and run:

  1. Add the DemoEJBClient project in the build path (the project that contains the EJB remote interface you are going to call),
  2. Add wlfullclient.jar, a jar with all the client libs you need. This jar needs to be built once, using a command line interface. This is the procedure to build this jar: cd in the WEBLOGIC_INSTALL_LIB/server/lib, then run the command "java -jar wljarbuilder.jar". This will take 30s to build the client lib for your installation. At the end, you should find a wlfullclient.jar file. Add it to your build path.
  3. Add a new java class with a main(), name it  StandAloneClient, 
  4. Copy this source code provided below, check that the  JNDI_NAME is the same as the one you saw in the weblogic admin console/jndi tree. 

Then you should have such a source code for the standalone client:
 

package client;

import java.util.Hashtable;import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import sessions.TestRemote;

public class StandAloneClient {
    private static String INITIAL_CONTEXT_NAME = "weblogic.jndi.WLInitialContextFactory";
    private static String PROVIDER_URL = "t3://localhost:7001";
    private static String JNDI_NAME = "java:global.DemoEAR.DemoEJB.DemoSessionEJB!sessions.DemoSessionEJBRemote";

    public static void main(String[] args) throws Exception {
        Context ctx = getInitialContext();
        TestRemote helloEJB = (TestRemote) ctx.lookup(JNDI_NAME);
        System.out.println(helloEJB.helloWorld());
        }

    private static Context getInitialContext() throws NamingException {
        Hashtable env = new Hashtable();
        env.put(Context.INITIAL_CONTEXT_FACTORY, INITIAL_CONTEXT_NAME);
        env.put(Context.PROVIDER_URL, PROVIDER_URL);
        return new InitialContext(env);
    }
}

These info come from the Weblogic documentation (name of INITIAL_CONTEXT_FACTORY, etc.)

Redeploy the EAR project, just to be sure (right click on server, then "add and remove").

Run the standalone client project (as a "Java application").

Normally you should see in the console the "Hello World" message. As you saw, we could call the EJB from any external host, as long as we indicate the right URL for the weblogic server.

Write a bank account management application

This time, we will write a real application. A small bank account manager.

Create an empty MyBank database in javaDB (from Eclipse), connect it to Weblogic

Using the "Data Source Explorer" in Eclipse, use the "New" menu but this time to connect to a database named MyBank that does not exist. Put admin/admin as user/password, and check the "create database if needed" option. Once created Eclipse connects the database, that is, for the moment, empty.

Connect this database to Weblogic 12c, follow the same procedure as we did in Exercice 1.  If you do not remember, just look at the informations in this page:  Weblogic / Java EE6 FAQ and Guides.

In the EJB project, configure persistence.xml for working with MyBank database

  1. Like in Exo1 with the manufacturers, double click on the persistence.xml file, then in the designer, use the "connection" tab at bottom, change "transaction type" to JTA, and enter the JNDI name of the database (it should be "MyBank" or whatever JNDI name you used when you connected the database to weblogic).
  2. Go to the "schema generation" tab and change 

In the DemoEJB Project, create an entity class for an Account

Use the New/JPA entity menu and add an empty entity class to the project. Put it in a package named "entities" and name it Account.

A bank account has a few properties:

  • name: Name of owner,
  • balance,

Remember: a property is defined by getters and setters, so do not forget to generate/write getters and setters for id, name, balance.

This time we will use an auto-generated primary key:

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
int id;

The @GeneratedValue annotation indicates that the PK is auto-generated, using any method, you do not care (AUTO). Other possible values = SEQUENCE, ID, etc. see the JPA course.

You may also add some convenience functions like add(int ammount) or remove(int ammont) methods that will add or remove money from the bank account.

In the end the basic Account.java entity class should look like that:

package entities;

import java.io.Serializable;
import javax.persistence.*;

/**
* Entity implementation class for Entity: Account
*
*/
@Entity
public class Account implements Serializable {
private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
int id;
String name;
int balance;

public Account() {
}

public Account(String name, int balance) {
this.name = name;
this.balance = balance;
}

public void add(int ammount) {
balance += ammount;
}

public void remove(int ammount) {
balance -= ammount;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getBalance() {
return balance;
}

public void setBalance(int balance) {
this.balance = balance;
}
}

Like we did yesterday add a AccountFacade session bean to a package named "sessions" to the DemoEJB project

Create a stateless session bean. Implement some methods for the CRUD operations like we did yesterday with the ManufacturerFacade. It is not important to have all of them but at least a create(String name, int balance) method so that we can create new bank accounts and a getAllAccounts() that does a select *. This is very similar to yesterday's exercice.

Add also a method for creating some test accounts so that we will be able to play with a populated database:

 public Account create(String name, int balance) {
    Account a = new Account(name, balance);
    // insert in database
em.persist(a); return a; } public void createTestData() { create("John Lennon", 150000);
create("Paul Mac Cartney", 950000);
create("Ringo Starr", 20000);
create("Georges Harrisson", 100000); }

Add a singleton EJB that will populate the database at deployment time, when the project is run

package entities;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Singleton;
import javax.ejb.Startup;

import sessions.AccountFacade;

/**
* Session Bean implementation class InitEJB
*/
@Startup
@Singleton
@LocalBean
public class InitEJB {
@EJB
AccountFacade facade;

@PostConstruct
public void init() {
System.out.println("### Initialization of the database, adding some test accounts ###"); facade.createTestData();
}
}

The @Singleton annotation guarantees