- GUI
- Windows API tutorial
- Introduction to Windows API
- Windows API main functions
- System functions in Windows API
- Strings in Windows API
- Date & time in Windows API
- A window in Windows API
- First steps in UI
- Windows API menus
- Windows API dialogs
- Windows API controls I
- Windows API controls II
- Windows API controls III
- Advanced controls in Windows API
- Custom controls in Windows API
- The GDI in Windows API
- PyQt4 tutorial
- PyQt5 tutorial
- Qt4 tutorial
- Introduction to Qt4 toolkit
- Qt4 utility classes
- Strings in Qt4
- Date and time in Qt4
- Working with files and directories in Qt4
- First programs in Qt4
- Menus and toolbars in Qt4
- Layout management in Qt4
- Events and signals in Qt4
- Qt4 Widgets
- Qt4 Widgets II
- Painting in Qt4
- Custom widget in Qt4
- The Breakout game in Qt4
- Qt5 tutorial
- Introduction to Qt5 toolkit
- Strings in Qt5
- Date and time in Qt5
- Containers in Qt5
- Working with files and directories in Qt5
- First programs in Qt5
- Menus and toolbars in Qt5
- Layout management in Qt5
- Events and signals in Qt5
- Qt5 Widgets
- Qt5 Widgets II
- Painting in Qt5
- Custom widget in Qt5
- Snake in Qt5
- The Breakout game in Qt5
- PySide tutorial
- Tkinter tutorial
- Tcl/Tk tutorial
- Qt Quick tutorial
- Java Swing tutorial
- JavaFX tutorial
- Java SWT tutorial
- wxWidgets tutorial
- Introduction to wxWidgets
- wxWidgets helper classes
- First programs in wxWidgets
- Menus and toolbars in wxWidgets
- Layout management in wxWidgets
- Events in wxWidgets
- Dialogs in wxWidgets
- wxWidgets widgets
- wxWidgets widgets II
- Drag and Drop in wxWidgets
- Device Contexts in wxWidgets
- Custom widgets in wxWidgets
- The Tetris game in wxWidgets
- wxPython tutorial
- Introduction to wxPython
- First Steps
- Menus and toolbars
- Layout management in wxPython
- Events in wxPython
- wxPython dialogs
- Widgets
- Advanced widgets in wxPython
- Drag and drop in wxPython
- Internationalisation
- Application skeletons in wxPython
- The GDI
- Mapping modes
- Creating custom widgets
- Tips and Tricks
- wxPython Gripts
- The Tetris game in wxPython
- C# Winforms Mono tutorial
- Java Gnome tutorial
- Introduction to Java Gnome
- First steps in Java Gnome
- Layout management in Java Gnome
- Layout management II in Java Gnome
- Menus in Java Gnome
- Toolbars in Java Gnome
- Events in Java Gnome
- Widgets in Java Gnome
- Widgets II in Java Gnome
- Advanced widgets in Java Gnome
- Dialogs in Java Gnome
- Pango in Java Gnome
- Drawing with Cairo in Java Gnome
- Drawing with Cairo II
- Nibbles in Java Gnome
- QtJambi tutorial
- GTK+ tutorial
- Ruby GTK tutorial
- GTK# tutorial
- Visual Basic GTK# tutorial
- PyGTK tutorial
- Introduction to PyGTK
- First steps in PyGTK
- Layout management in PyGTK
- Menus in PyGTK
- Toolbars in PyGTK
- Signals & events in PyGTK
- Widgets in PyGTK
- Widgets II in PyGTK
- Advanced widgets in PyGTK
- Dialogs in PyGTK
- Pango
- Pango II
- Drawing with Cairo in PyGTK
- Drawing with Cairo II
- Snake game in PyGTK
- Custom widget in PyGTK
- PHP GTK tutorial
- C# Qyoto tutorial
- Ruby Qt tutorial
- Visual Basic Qyoto tutorial
- Mono IronPython Winforms tutorial
- Introduction
- First steps in IronPython Mono Winforms
- Layout management
- Menus and toolbars
- Basic Controls in Mono Winforms
- Basic Controls II in Mono Winforms
- Advanced Controls in Mono Winforms
- Dialogs
- Drag & drop in Mono Winforms
- Painting
- Painting II in IronPython Mono Winforms
- Snake in IronPython Mono Winforms
- The Tetris game in IronPython Mono Winforms
- FreeBASIC GTK tutorial
- Jython Swing tutorial
- JRuby Swing tutorial
- Visual Basic Winforms tutorial
- JavaScript GTK tutorial
- Ruby HTTPClient tutorial
- Ruby Faraday tutorial
- Ruby Net::HTTP tutorial
- Java 2D games tutorial
- Java 2D tutorial
- Cairo graphics tutorial
- PyCairo tutorial
- HTML5 canvas tutorial
- Python tutorial
- Python language
- Interactive Python
- Python lexical structure
- Python data types
- Strings in Python
- Python lists
- Python dictionaries
- Python operators
- Keywords in Python
- Functions in Python
- Files in Python
- Object-oriented programming in Python
- Modules
- Packages in Python
- Exceptions in Python
- Iterators and Generators
- Introspection in Python
- Ruby tutorial
- PHP tutorial
- Visual Basic tutorial
- Visual Basic
- Visual Basic lexical structure
- Basics
- Visual Basic data types
- Strings in Visual Basic
- Operators
- Flow control
- Visual Basic arrays
- Procedures & functions in Visual Basic
- Organizing code in Visual Basic
- Object-oriented programming
- Object-oriented programming II in Visual Basic
- Collections in Visual Basic
- Input & output
- Tcl tutorial
- C# tutorial
- Java tutorial
- AWK tutorial
- Jetty tutorial
- Tomcat Derby tutorial
- Jtwig tutorial
- Android tutorial
- Introduction to Android development
- First Android application
- Android Button widgets
- Android Intents
- Layout management in Android
- Android Spinner widget
- SeekBar widget
- Android ProgressBar widget
- Android ListView widget
- Android Pickers
- Android menus
- Dialogs
- Drawing in Android
- Java EE 5 tutorials
- Introduction
- Installing Java
- Installing NetBeans 6
- Java Application Servers
- Resin CGIServlet
- JavaServer Pages, (JSPs)
- Implicit objects in JSPs
- Shopping cart
- JSP & MySQL Database
- Java Servlets
- Sending email in a Servlet
- Creating a captcha in a Servlet
- DataSource & DriverManager
- Java Beans
- Custom JSP tags
- Object relational mapping with iBATIS
- Jsoup tutorial
- MySQL tutorial
- MySQL quick tutorial
- MySQL storage engines
- MySQL data types
- Creating, altering and dropping tables in MySQL
- MySQL expressions
- Inserting, updating, and deleting data in MySQL
- The SELECT statement in MySQL
- MySQL subqueries
- MySQL constraints
- Exporting and importing data in MySQL
- Joining tables in MySQL
- MySQL functions
- Views in MySQL
- Transactions in MySQL
- MySQL stored routines
- MySQL Python tutorial
- MySQL Perl tutorial
- MySQL C API programming tutorial
- MySQL Visual Basic tutorial
- MySQL PHP tutorial
- MySQL Java tutorial
- MySQL Ruby tutorial
- MySQL C# tutorial
- SQLite tutorial
- SQLite C tutorial
- SQLite PHP tutorial
- SQLite Python tutorial
- SQLite Perl tutorial
- SQLite Ruby tutorial
- SQLite C# tutorial
- SQLite Visual Basic tutorial
- PostgreSQL C tutorial
- PostgreSQL Python tutorial
- PostgreSQL Ruby tutorial
- PostgreSQL PHP tutorial
- PostgreSQL Java tutorial
- Apache Derby tutorial
- SQLAlchemy tutorial
- MongoDB PHP tutorial
- MongoDB Java tutorial
- MongoDB JavaScript tutorial
- MongoDB Ruby tutorial
- Spring JdbcTemplate tutorial
- JDBI tutorial
Introduction to EJBs
In this tutorial, we learn how to use Enterprise JavaBeans. We use GlassFish, NetBeans, Derby, and Maven.
Enterprise JavaBean (EJB) is a server-side component that encapsulates the business logic of an application. EJBs are run in an EJB container, which is responsible for various system-level services, including transaction management, security, and concurrency control. EJBs are part of the Java EE specification.
GlassFish is the reference implementation of Java EE and it includes Enterprise JavaBeans container. We will run our examples in GlassFish. Apache Derby is an open source relational database implemented entirely in Java. Oracle distributes the same binaries under the name Java DB.
First EJB
We create a new web application in NetBeans. The project will be called MyFirstEJB
. From the Server and Settings page, we select GlassFish server and change the context to myfirstejb
.

In this dialog we select the application server, Java EE version, and context path.
index.html
<!DOCTYPE html> <html> <head> <title>Test page</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> <p>Test page</p> </body> </html>
This is our index.html
page. It will be returned if we access the root page of the application.
We right-click on the application icon and select a new EJB of Session Bean type. We call the bean MyFirstBean
, type in com.zetcode.ejb
package, and choose a stateless session type.

Stateless session bean does not maintain a conversational state with the client. When a client invokes the methods of a stateless bean, the bean's instance variables may contain a state specific to that client but only for the duration of the invocation. When the method is finished, the client-specific state is lost.
FirstBean.java
package com.zetcode.ejb; import javax.ejb.Stateless; @Stateless public class FirstBean { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public String sayHello() { StringBuilder sb = new StringBuilder("Hello "); sb.append(this.getName()).append("!"); return sb.toString(); } }
MyFirstBean
is a stateless session bean. A stateless session bean is created with the @Stateless
decoration. It has a no-interface view
, where local business interfaces are not used and all public methods of the bean class are automatically exposed to the caller.
public String sayHello() { StringBuilder sb = new StringBuilder("Hello "); sb.append(this.getName()).append("!"); return sb.toString(); }
The MyFirstBean's
job is to construct a greeting to the caller.
Next, we create a new servlet by right-clicking on the project icon and selecting a Servlet file type from the Web category. We call the servlet Greet
and type in the com.zetcode.web
package. We change the URL pattern to /greet
.

In the new servlet dialog, we provide the servlet name and its package.
Greet.java
package com.zetcode.web; import com.zetcode.ejb.FirstBean; import java.io.IOException; import java.io.PrintWriter; import javax.ejb.EJB; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet(name = "Greet", urlPatterns = {"/greet"}) public class Greet extends HttpServlet { @EJB private FirstBean firstBean; @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/plain;charset=UTF-8"); firstBean.setName(request.getParameter("name")); String msg = firstBean.createMessage(); try (PrintWriter out = response.getWriter()) { out.println(msg); } } }
The Greet
servlet reads a name parameter from the URL sent by the client, calls EJB's createMessage()
business method and returns a response in plain text.
@EJB private FirstBean firstBean;
The @EJB
annotation injects the EJB into the servelt.
response.setContentType("text/plain;charset=UTF-8");
The servelt response is in plain text in UTF-8 charset.
firstBean.setName(request.getParameter("name"));
We retrieve the name
parameter from the request and set it to the EJB.
String msg = firstBean.createMessage();
We call the createMessage()
business method.

We build the application and deploy it to the GlassFish server. To build the application, right-click on the project icon and select Build; to deploy the application, right-click on the project icon and select Deploy.
$ curl localhost:8080/myfirstejb/greet?name=Jan Hello Jan!
With the curl
tool, we connect to the Greet
servlet of the myfirstejb
web application and pass it a parameter. The web application responds with a greeting.
$ curl localhost:8080/myfirstejb/ <!DOCTYPE html> <html> <head> <title>Test page</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> <p>Test page</p> </body> </html>
Accessing the root page, the application returns the HTML test page.
Persisting data with Entity beans
In the second example, we create a web application that will read and save cars. The car objects will be saved in the Derby database.
We create a new Java web application with a car-app
name. Then we create a new Car
entity. Entity class file type is located in the persistence category. The package will be com.zetcode.persistence
. The primary key type is Long
and the create persistence unit option is checked.
In the next page, we change the persistence unit name to carpu
, and select the default EclipseLink
persistence provider. We select the jdbc/sample
data source, and have the Create
table generation strategy selected. The jdbc/sample
data source refers to the sample
database which is located in .netbeans-derby
subdirectory of user's home directory by default.

In this view we provide the persistence unit name, persistence provider, data source, and table generation strategy.
Entity bean
Entity Bean is a type of Enterprise JavaBean that represents a business entity object existing in a persistent storage. An entity bean is identified by a primary key. Unlike session beans, which live during the lifetime of a client session, entity beans survive even EJB container crashes.
Car.java
package com.zetcode.persistence; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name="Cars") public class Car implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name="Id") private Long id; @Column(name="Name") private String name; @Column(name="Price") private int price; public Car() { } public Car(String name, int price) { this.name = name; this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } }
Car
is an EJB entity bean. It is a business object to be stored in the Derby database.
@Entity @Table(name="Cars") public class Car implements Serializable {
Entity beans are decorated with the @Entity
annotation. The entity maps to the Cars
table.
@Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name="Id") private Long id;
Each entity has a unique object identifier. This unique identifier, or primary key, enables clients to locate a particular entity instance. The @Id
declares the identifier property of this entity bean, the @GeneratedValue
annotation is used to specify how the primary key is generated, and the @Column
maps the identifier to the Id
column of the database table.
public Car() { }
A no-argument constructor is required by persistence frameworks.
EJB
We create a local, stateless ManageCarBean
enterprise bean. This time the EJB is having a local interface view.
ManageCarBeanLocal.java
package com.zetcode.ejb; import javax.ejb.Local; import com.zetcode.persistence.Car; @Local public interface ManageCarBeanLocal { void saveCar(Car car); void setPrice(int price); void setName(String name); Car getCar(Long id); }
The interface defines the methods to be used by the clients of the EJB. A client can access a session bean only through the methods defined in the bean's business interface.
@Local public interface ManageCarBeanLocal {
The @Local
decoration designates that the interface is a local business interface.
ManageCarBean.java
package com.zetcode.ejb; import javax.ejb.Stateless; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import com.zetcode.persistence.Car; @Stateless public class ManageCarBean implements ManageCarBeanLocal { private String name; private int price; @PersistenceContext(unitName = "carpu") private EntityManager em; public String getName() { return name; } @Override public void setName(String name) { this.name = name; } public int getPrice() { return price; } @Override public void setPrice(int price) { this.price = price; } @Override public void saveCar(Car car) { em.persist(car); } @Override public Car getCar(Long id) { Car car = em.find(Car.class, id); return car; } }
ManageCarBean
reads and saves car objects.
@PersistenceContext(unitName = "carpu") private EntityManager em;
The EntityManager
is created by the container using the information in the persistence.xml
. The @PersistenceContext
annotation injects the entity manager into the bean. The manager is mapped to the carpu
persistence unit. Entity manager is used to interact with the data via the persistence context.
@Override public void saveCar(Car car) { em.persist(car); }
The saveCar()
method saves a car object into the database; in our case it is Derby.
@Override public Car getCar(Long id) { Car car = em.find(Car.class, id); return car; }
The getCar()
method finds a car by its ID.
persistence.xml
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> <persistence-unit name="carpu" transaction-type="JTA"> <jta-data-source>jdbc/sample</jta-data-source> <exclude-unlisted-classes>false</exclude-unlisted-classes> <properties> <property name="eclipselink.ddl-generation" value="create-tables" /> </properties> </persistence-unit> </persistence>
The persistence.xml
file is a configuration file that contains information about the database that we use in our application. The jdbc/sample
is a built-in datasource shipped with the GlassFish server. In our application, we save our data in the Derby's pre-created sample
database. The eclipselink.ddl-generation
property automatically causes the Cars
table to be created if it does not exist.

We can use NetBeans Derby tool to connect and manage our data in the database. The tool is located in the Services window.
Servlets
We create two servlets: SaveCar
and ReadCar
. We place them into the com.zetcode.web
package. Servlets are created from the NetBeans Web category. Both servlets respond in plain text.

We also include Apache Common Lang JARs for helper methods. The library can be downloaded from the project website .
ValidateParameter.java
package com.zetcode.util; import org.apache.commons.lang3.math.NumberUtils; public class ValidateParameter { private static final int MAX_PRICE_CAR = 10_000_000; public static boolean validateName(String param) { return !(null == param || "".equals(param) || NumberUtils.isNumber(param)); } public static boolean validateId(String param) { return !(null == param || "".equals(param) || !NumberUtils.isNumber(param)); } public static boolean validatePrice(String param) { if (null == param || "".equals(param) || !NumberUtils.isNumber(param)) { return false; } int price = Integer.valueOf(param); return !(price < 0 || price > MAX_PRICE_CAR); } }
A ValidateParameter
class is used to validate the request parameters. Parameters may not be null
or empty, and ID and price values must be numbers. In addition, the price must be within a reasonable range. We use the Apache Common Lang's NumberUtils.isNumber()
to check for a numeric value.
SaveCar.java
package com.zetcode.web; import java.io.IOException; import java.io.PrintWriter; import javax.ejb.EJB; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.zetcode.ejb.ManageCarBeanLocal; import com.zetcode.persistence.Car; import com.zetcode.util.ValidateParameter; @WebServlet(name = "SaveCar", urlPatterns = {"/save"}) public class SaveCar extends HttpServlet { @EJB private ManageCarBeanLocal manageCarBean; @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String sname = request.getParameter("name"); String sprice = request.getParameter("price"); String message; if (ValidateParameter.validateName(sname) && ValidateParameter.validatePrice(sprice)) { message = String.format("%s car is saved", sname); int price = Integer.valueOf(sprice); Car car = new Car(sname, price); manageCarBean.saveCar(car); } else { message = "Wrong parameters"; } response.setContentType("text/plain;charset=UTF-8"); try (PrintWriter out = response.getWriter()) { out.println(message); } } }
The purpose of the SaveCar
servlet is to call the appropriate EJB to save the car. The data for the car object are read from the URL sent by the client.
@WebServlet(name = "SaveCar", urlPatterns = {"/save"})
The @WebServlet
annotation maps the SaveCar
servlet to the /save
path.
@EJB private ManageCarBeanLocal manageCarBean;
A ManageCarBeanLocal
enterprise bean is injected into the servlet.
String sname = request.getParameter("name"); String sprice = request.getParameter("price");
The parameters are read from the request.
if (ValidateParameter.validateName(sname) && ValidateParameter.validatePrice(sprice)) {
The parameters are being validated.
Car car = new Car(sname, price); manageCarBean.saveCar(car);
A new car object is created and saved to the database. To save the car object, we utilize the ManageCarBean's
saveCar()
method.
ReadCar.java
package com.zetcode.web; import com.zetcode.ejb.ManageCarBeanLocal; import java.io.IOException; import java.io.PrintWriter; import javax.ejb.EJB; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.zetcode.persistence.Car; import com.zetcode.util.ValidateParameter; @WebServlet(name = "ReadCar", urlPatterns = {"/read"}) public class ReadCar extends HttpServlet { @EJB private ManageCarBeanLocal manageCarBean; @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/plain;charset=UTF-8"); String message; String pid = request.getParameter("id"); if (ValidateParameter.validateId(pid)) { Long carId = Long.valueOf(pid); Car rcar = manageCarBean.getCar(carId); if (null != rcar) { message = String.format("Name: %s, Price: %d", rcar.getName(), rcar.getPrice()); } else { message = "Cannot find car with this ID"; } } else { message = "Wrong parameters"; } try (PrintWriter out = response.getWriter()) { out.println(message); } } }
The ReadCar
servlet calls the ManageCarBean
enterprise bean to read data from the database; it selects a car object based on the provided ID.
String sid = request.getParameter("id");
An ID is read from the URL.
Long carId = Long.valueOf(pid); Car rcar = manageCarBean.getCar(carId); if (null != rcar) { message = String.format("Name: %s, Price: %d", rcar.getName(), rcar.getPrice()); } else { message = "Cannot find car with this ID"; }
The ManageCarBean's
readCar()
method is used to retrieve the car object.
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <session-config> <session-timeout> 30 </session-timeout> </session-config> <error-page> <error-code>404</error-code> <location>/error404.txt</location> </error-page> <error-page> <location>/error.txt</location> </error-page> </web-app>
In the web.xml
file, we provide two error pages. The error.txt
is a default error page for all errors and the error404.txt
is for 404 errors, which are triggered when the client requests a non-existing resource. Note that error404.txt
must go before error.txt
.

We place the two text files inside web pages.
error.txt
Error has occurred, check the GlassFish log file
This is the generic error page.
error404.txt
404 : Page was not found
This is the error page for 404 errors.
Deployment
It's time to deploy the application. The application is deployed by right-clicking on the web project and selecting the Deploy command. Note that when we clean the project, the application is undeployed. The deploy command also starts the selected application server if it is not already running.
$ ./asadmin list-applications MyFirstEJB <ejb, web> car-app <ejb, web> Command list-applications executed successfully.
The GlassFish's asadmin
tool can be used to determine the currently deployed applications.
NetBeans automatically starts the Derby server when GlassFish starts. This can be turned off in the GlassFish server settings.

In the NetBeans' Services tab, we expand the Servers node and select the GlassFish properties. There we can see the Start Registered Derby Server option.
$ curl localhost:8080/car-app/doread 404 : Page was not found
If we try to reach a non-existing resource, we get the custom 404 error message.
$ curl "localhost:8080/car-app/save?name=Volvo&price=29000" Volvo car is saved
A Volvo car is saved into the database. Note the usage of double quotes for the URL.
$ curl "localhost:8080/car-app/save?name=Bentley&price=299000000" Wrong parameters
The validator catches an unrealistically high car price.
$ curl localhost:8080/car-app/read?id=401 Name: Volvo, Price: 29000
We read a car from the database.
Building the project with Maven
NetBeans saves us a lot of tedious work during development. But it is beneficial to build the project manually with Maven.
mvn archetype:generate -DgroupId=com.zetcode -DartifactId=car-app -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false
We create a new Maven project. We use the maven-archetype-webapp
type.
$ tree . └── car-app ├── pom.xml └── src └── main ├── resources └── webapp ├── index.jsp └── WEB-INF └── web.xml 6 directories, 3 files
The tree
command shows us the created project structure.
$ mkdir -p src/main/java/com/zetcode/ejb $ mkdir src/main/java/com/zetcode/persistence $ mkdir src/main/java/com/zetcode/web $ mkdir src/main/java/com/zetcode/util $ mkdir src/main/resources/META-INF
We create the directories.
After copying the application source files, the project structure looks like this:
$ tree . ├── pom.xml └── src └── main ├── java │ └── com │ └── zetcode │ ├── ejb │ │ ├── ManageCarBean.java │ │ └── ManageCarBeanLocal.java │ ├── persistence │ │ └── Car.java │ ├── util │ │ └── ValidateParameter.java │ └── web │ ├── ReadCar.java │ └── SaveCar.java ├── resources │ └── META-INF │ └── persistence.xml └── webapp ├── index.jsp └── WEB-INF └── web.xml
Don't forget to copy the web.xml
file; Maven creates an empty web.xml
file for us.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.zetcode</groupId> <artifactId>car-app</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>car-app Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>eclipselink</artifactId> <version>2.5.0</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.0</version> </dependency> <dependency> <groupId>javax</groupId> <artifactId>javaee-web-api</artifactId> <version>7.0</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.5.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> <finalName>car-app</finalName> </build> </project>
The pom.xml
is a file that contains information about the project and configuration details used by Maven to build the project. We provide the dependencies for the Eclipse link persistence provider, Apache commons lang library, and the Java EE Web API. We instruct Maven to use Java 8. The final build file is called car-app.war
and is located in the target
subdirectory.
$ mvn package
The project is built with the mvn package
command.
$ ./asadmin start-domain
From inside the GlassFish's bin directory, we start the GlassFish server.
$ ./asadmin start-database --db-home ~/.netbeans-derby
The Derby server is started. NetBeans creates the Derby system home in the .netbeans-derby
directory, which is located in the user's home directory. There we can find the sample
database that we have worked with earlier.
$ ~/bin/glassfish-4.1.1/glassfish/bin/asadmin deploy target/car-app.war
We deploy the application. We see a warning saying Table/View 'CARS' already exists in Schema 'APP'
. This is the consequence of the eclipselink.ddl-generation
property, which was set to create_tables
. We can ignore the warning.
$ curl localhost:8080/car-app/read?id=401 Name: Volvo, Price: 29000
We retrieve a car that was created earlier.
In this tutorial, we have created Enterprise JavaBeans for some simple business logic. We have used NetBeans, Derby, and Maven for our examples. ZetCode has the following related tutorials: Derby tutorial , Java tutorial , and Stripes tutorial .
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论