User Tools

Site Tools


programming:java:java_ee

Table of Contents

Java EEJava Enterprise Edition
Java SEJava Standart Edition
SOAPSimplke Object Transfair Protocol
ACC Application Client Container
EJB Enterprise Java Bean
DD Deployment Descriptor
POJO Plain Old Java Object
IoCInversion of COntrol
JSFJava Server Faces
JSPJava Server Pages
JSFJava Server Faces
JPAJava Persistance API
JMSJava Messaging Service
JDBC Java Database COnnectivity
JNDI Java Naming and DIrectory Service
RMI Remote Method Invocation

Lib

Introduction into JEE https://docs.oracle.com/javaee/6/tutorial/doc/gfirp.html
Introduction into Hibernate - JPA implementation delivered with JBoss Application Server http://docs.jboss.org/hibernate/core/3.3/reference/en/html/index.html

APIs

Java Transaction API

This service offers a transaction demarcation API used by the container and the application. It also provides an interface between the transaction manager and a resource manager at the Service Provider Interface (SPI) level.

Java Persistence API

JPA - Standard API for object-relational mapping (ORM). With its Java Persistence Query Language (JPQL), you can query objects stored in the underlying database.

Hibernate implements JPA.

Validation

Bean Validation provides class and method level constraint declaration and validation facilities.

Java Message Service

JMS - Java Message Service : This allows components to communicate asynchronously through messages. It supports reliable point-to-point (P2P) messaging as well as the publish-subscribe (pub-sub) model.

Java Database Connectivity

JDBC is an application programming interface (API) for the programming language Java, that defines how a client may access a database. It is part of the Java Standard Edition platform. For different Databases there are different implementations: for PostGreSQL, Oracle etc.

Java Naming and Directory Interface

JNDI - This API, included in Java SE, is used to access naming and directory systems. Your application uses it to associate (bind) names to objects and then to find these objects (lookup) in a directory. You can look up data sources, JMS factories, EJBs, and other resources. Omnipresent in your code until J2EE 1.4, JNDI is used in a more transparent way through injection.

Article: http://www.javaworld.com/article/2074186/jndi/j2ee-or-j2se--jndi-works-with-both.html

The Syntax of JNDI Path is the following:

namespace java:/, java:global/ - the prefix of the ressource path, to make the ressource name unique for a given server
ressource path everything after the namespace : java:global/MyBean

Some Details about JNDI Syntax:

JavaMail

Many applications require the ability to send e-mails, which can be implemented through use of the JavaMail API.

JavaBeans Activation Framework

The JAF API, included in Java SE, provides a framework for handling data in different MIME types. It is used by JavaMail.

XML process ing

Most Java EE components can be deployed with optional XML deployment descriptors, and applications often have to manipulate XML documents. The Java API for XML Processing (JAXP) provides support for parsing documents with SAX and DOM APIs, as well as for XSLT. The Streaming API for XML (StAX) provides a pull-parsing API for XML.

JSON processing

New in Java EE 7 the Java API for JSON Processing (JSON-P) allows applications to parse, generate, transform, and query JSON.

Java EE Connector Architecture

Connectors allow you to access EIS (enterprise information systems) from a Java EE component. These could be databases, mainframes, or enterprise resource planning (ERP) programs.

Security services

Java Authentication and Authorization Service (JAAS) enables services to authenticate and enforce access controls upon users. The Java Authorization Service Provider Contract for Containers (JACC) defines a contract between a Java EE application server and an authorization service provider, allowing custom authorization service providers to be plugged into any Java EE product. Java Authentication Service Provider Interface for Containers (JASPIC) defines a standard interface by which authentication modules may be integrated with containers so that these modules may establish the authentication identities used by containers.

Web services

Java EE provides support for SOAP and RESTful web services. The Java API for XML Web Services (JAX-WS), replacing the Java API for XML-based RPC (JAX-RPC), provides support for web services using the SOAP/HTTP protocol. The Java API for RESTful Web Services (JAX-RS) provides support for web services using the REST style.

Jax-RS - allows to implement REST Services easily.
Jax-RS vs Servlet

PRO:

  • They allow some additional annotations:
    • @Produces(MediaType.APPLICATION_JSON)
    • @Path(“aachen/”)
  • They allow some multiple GET/POST/PUT methods per class.

CONTRA:

  • They are slowlier, than simple Servlets

Dependency Injection

Since Java EE 5, some resources (data sources, JMS factories, persistence units, EJBs . . .) can be injected in managed components. Java EE 7 goes further by using CDI as well as the DI (Dependency Injection for Java) specifications.

Management

Java EE defines APIs for managing containers and servers using a special management enterprise bean. The Java Management Extensions (JMX) API is also used to provide some management support. Deployment: The Java EE Deployment Specification defines a contract between deployment tools and Java EE products to standardize application deployment.

Web Spec Zoo

There are many technologies which are using each other.

JSP

Since JSF 2.0, JSP has been deprecated as view technology in favor of Facelets.

JSP is a Java view technology running on the server machine which allows you to write template text in (the client side languages like HTML, CSS, JavaScript and so on). JSP supports taglibs, which are backed by pieces of Java code that let you control the page flow or output dynamically. A well known taglib is JSTL. JSP also supports Expression Language, which can be used to access backend data (via attributes available in page, request, session and application scopes), mostly in combination with taglibs.

When a JSP is requested for the first time or when the webapp starts up, the servlet container will compile it into a class extending HttpServlet and use it during the webapp's lifetime. You can find the generated source code in the server's work directory. In for example Tomcat, it's the /work directory. On a JSP request, the servlet container will execute the compiled JSP class and send the generated output (usually just HTML/CSS/JS) through the webserver over network to the client side, which in turn displays it in the web browser.

Servlets

Servlet is an Java application programming interface (API) running on the server machine, which intercepts requests made by the client and generates/sends a response. A well known example is the HttpServlet which provides methods to hook on HTTP requests using the popular HTTP methods such as GET and POST. You can configure HttpServlets to listen on a certain HTTP URL pattern, which is configurable in web.xml, or more recently with Java EE 6, with @WebServlet annotation.

When a Servlet is first requested or during webapp startup, the servlet container will create an instance of it and keep it in memory during the webapp's lifetime. The same instance will be reused for every incoming request whose URL matches the servlet's URL pattern. You can access the request data by HttpServletRequest and handle the response by HttpServletResponse. Both objects are available as method arguments inside any of the overridden methods of HttpServlet, such as doGet() and doPost().

JSF

JSF is a replacement for JSP

JSF (Java Server Faces) is a component based MVC framework which is built on top of the Servlet API, and provides components via taglibs which can be used in JSP or any other Java based view technology such as Facelets. Facelets is much more suited to JSF than JSP. It namely provides great templating capabilities such as composite components, while JSP basically only offers the <jsp:include> for templating, so that you're forced to create custom components with raw Java code (which is a bit opaque and a lot of tedious work in JSF) when you want to replace a repeated group of components with a single component. Since JSF 2.0, JSP has been deprecated as view technology in favor of Facelets.

As being a MVC (Model-View-Controller) framework, JSF provides the FacesServlet as the sole request-response Controller. It takes all the standard and tedious HTTP request/response work from your hands, such as gathering user input, validating/converting them, putting them in model objects, invoking actions and rendering the response.

This way you end up with basically a JSP or Facelets (XHTML) page for View and a Javabean class as Model. The JSF components are been used to bind the view with the model (such as your ASP.NET web control does) and the FacesServlet uses the JSF component tree to do all the work.

Facelets

Facelets are an alternative view technology based on pure XML templates (no scriptlets) which was introduced with Version 2 of the JSF standard. They can only be used in a JSF application.

TOOLS

Generate Beans from Database in Eclipse

Glossar

Deployment describtor

Deployment describtor is a file, which may be added to the application. It may contain metadata. It is optional. Its data may be added via annotations.

application.xml Java EE META-INF
application-client.xml Java EE META-INF
beans.xml CDI META-INF or WEB-INF
ra.xml JCA META-INF
ejb-jar.xml EJB META-INF or WEB-INF
faces-config.xml JSF WEB -INF
persistence.xml JPA META-INF
validation.xml Bean Validation META-INF or WEB-INF
web.xml Servlet WEB-INF
web-fragment.xml Servlet WEB-INF
webservices.xml SOAP Web Services META-INF or WEB-INF

Services provided by containers

Bean Discovery

Beans. At deployment time, CDI checks all of your application’s jar and war files and each time it finds a beans.xml deployment descriptor it manages all the POJOs, which then become CDI Beans.

Without a beans.xml file in the class path (under the META-INF or WEB-INF directory), CDI will not be able to use injection, interception, decoration, and so forth.

If your web application contains several jar files and you want to have CDI enabled across the entire application, each jar will need its own beans.xml to trigger CDI and bean discovery for each jar.

Packaging

To be deployed in a container, components have first to be packaged in a standard formatted archive. EAR, JAR, WAR. Goncalves, Antonio (2013-06-26). Beginning Java EE 7 (p. 6). Apress. Kindle Edition.

Application client module

An application client module contains Java classes and other resource files packaged in a jar file. This jar file can be executed in a Java SE environment or in an application client container. Like any other archive format, the jar file contains an optional META-INF directory for meta information describing the archive. The META-INF/MANIFEST.MF file is used to define extension- and package-related data. If deployed in an ACC, the deployment descriptor can optionally be located at META-INF/application-client.xml.

EJB MOdule

An EJB module contains one or more session and/or message-driven beans (MDBs) packaged in a jar file (often called an EJB jar file). It contains an optional META-INF/ejb-jar.xml deployment descriptor and can be deployed only in an EJB container.

web application module

A web application module contains servlets, JSPs, JSF pages, and web services, as well as any other web-related files (HTML and XHTML pages, Cascading Style Sheets (CSS), Java-Scripts, images, videos, and so on). Since Java EE 6, a web application module can also contain EJB Lite beans (a subset of the EJB API described in Chapter 7). All these artifacts are packaged in a jar file with a .war extension (commonly referred to as a war file, or a Web Archive). The optional web deployment descriptor is defined in the WEB-INF/web.xml file. If the war contains EJB Lite beans, an optional deployment descriptor can be set at WEB-INF/ejb-jar.xml. Java.class files are placed under the WEB-INF/classes directory and dependent jar files in the WEB-INF/lib directory.

enterprise module

An enterprise module can contain zero or more web application modules, zero or more EJB modules, and other common or external libraries. All this is packaged into an enterprise archive (a jar file with an .ear extension) so that the deployment of these various modules happens simultaneously and coherently. The optional enterprise module deployment descriptor is defined in the META-INF/application.xml file. The special lib directory is used to share common libraries between the modules.

CDI Context Dependency Injection

Classes define Depnedencies via Injection Points by using Interfaces or classes
If there are unambigouties - the applicaiton wont deploy.
To resolve unambiguties - use Qualifiers or @Default annotation.

Qualifiers

Qualifiers are applied at 2 different places:

  • at classes, implementing injection-points-interfaces.
  • at injection Points, to choose between implementations

Declare Qualifier

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.inject.Qualifier;


/**
 * The most unusual annotation is - @Qualifier
 */
@Qualifier 
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD})
public @interface NumberCalculation2002{ 
}

IMplement Injection Point INterface “NumberGenerator”.
It will be the default IMplementation.
It will be an IMplementation qualified with @NumberCalculation2016

@Default
@NumberCalculation2016
@Stateless
public class ISBNGenerator implements NumberGenerator {

	@Override
	public String generateNumber() {
		return "13-84356-" + Math.abs(new Random().nextInt());
	}
}

Inject implementations.

	@Inject
	@NumberCalculation2002
	private NumberGenerator numberGeneratorOld;
	
	@Inject
	@NumberCalculation2016
	private NumberGenerator numberGeneratorNew;
	
	// @Default annotated implementation will be injected
	@Inject
	private NumberGenerator numberGeneratorDefault;

Producers

Define some numbers and name them, by using Quialifier-annotations.


import java.util.Random;

import javax.enterprise.inject.Produces;

import de.exp.cdibean.stateless.qualifier.NumberCalculation2016Middle;
import de.exp.cdibean.stateless.qualifier.NumberCalculation2016Prefix;
import de.exp.cdibean.stateless.qualifier.NumberCalculation2016Random;

/**
 * This is a Producer class.
 * It only defines some injectable numbers.
 * The numbers are injected by type and name.
 * 
 * @NumberCalculation2016Prefix, @NumberCalculation2016Middle, @NumberCalculation2016Random
 * are Qualifiers - names to distinguish which String needs to be injected.
 */
public class NumberProducer {

	@Produces @NumberCalculation2016Prefix
	private String prefix13DIgits = "13-";
	
	@Produces @NumberCalculation2016Middle
	private double middleDigits = 12345;
	
	@Produces @NumberCalculation2016Random
	private int random(){
		return Math.abs(new Random().nextInt());
	}
}

Use the numbers, created by Producers. The INjections is resolved by

  • Variable type
  • QUalifier (@NumberCalculation2016Prefix, @NumberCalculation2016Middle, @NumberCalculation2016Random)

// @Stateless annotation is not needed!

@Default
public class ISBNGeneratorWithProducer implements NumberGenerator {

	/**
	 * Injecting those variables is possible, because there are @Produces annotations in NumberProducer.class
	 */
	
	@Inject @NumberCalculation2016Prefix
	String prefix;
	
	@Inject @NumberCalculation2016Middle
	double middle;
	
	@Inject @NumberCalculation2016Random
	int random;
	
	@Override
	public String generateNumber() {
		return prefix + middle + random;
	}
}

InjectionPoint environment

The environment of an InjectionPoint may be retrieved by defining the InjectionPoint.class as Producer-methods parameter.

It provides infos about:

  • InjectionPoint Bean
  • InjectionPoint Field

	@Produces 
	@TempFile
	private FileOutputStream getFileInputStream(InjectionPoint injectionPoint){
		String beantype = injectionPoint.getBean().getBeanClass().getSimpleName();

Destructors

A Destructor is a method in same class as Producer method, with an argument equal to the producers result. It is called, after Context destruction to clean up Producers' value.

	/**
	 * Producer method - creates a FileOutputStream
	 * 
	 * @param injectionPoint - contains infos about the environment: InjectionPoint, Bean containing the InjectionPoint etc.  
	 * 
	 * @TempFile will be used at InjectionPoints, so say, that this concrete FileOutputStream is needed
	 * 
	 * @return
	 */
	@Produces 
	@TempFile
	private FileOutputStream getFileInputStream(InjectionPoint injectionPoint){
		String beantype = injectionPoint.getBean().getBeanClass().getSimpleName();
		String name = UUID.randomUUID().toString();
		
		File file = new File("d:\\Temp\\"+beantype+name);
		FileOutputStream f = null;
		try {
			f = new FileOutputStream(file);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		return f;
	}
	
	/**
	 * Destructor method - closes FileOutputStream, opened by Producer method.
	 * Destructor is triggered, when the associated Context is destoyed by the Application.
	 * E.g. if the injectionPoint is within a RESTful service - the Destruction will happen directly after the service returned it's value. 
	 * 
	 * The Qualifier MUST be the same for disposal method to work.
	 */
	private void disposeFileInputStream(@Disposes @TempFile FileOutputStream f) throws IOException{
		f.close();
	}

creating JEE-Projects with Eclipse-IDE deploying on WildFly-Applicaiton Server

Creating Basic Projects in Eclipse

Creating a Web Application

Defining the Application

You have first to define some informations about the Web-Application itselfe first.

  1. You can do it by subclassing javax.ws.rs.core.Application and using annotations on it
  2. or you can define it in XML. The Jax-RS implementation will then create an instance

Details

Option1: Subclassing javax.ws.rs.core.Application

Just create a subclass of javax.ws.rs.core.Application and annotate it with @ApplicationPath

import javax.ws.rs.ApplicationPath;

/**
 * Read: https://docs.jboss.org/author/display/AS7/JAX-RS+Reference+Guide
 * 
 *  ACHTUNG:  
 *  /jaxrs/ 
 *  not /jaxrs/* as you would wright in web.xml. Appending * is not necessary.
 */

@ApplicationPath("/jaxrs/")
public class TheApplication extends javax.ws.rs.core.Application {
	/* this represents the Web-applicaiton itselfe,	
	 * which contains servlets etc.
	 */
	
}

Option2: define Applicaiton in web.xml

Add the following to your web.xml. Where /jaxrs/* is the path segment to your Servlets in this web Application.

  <servlet-mapping>
    <servlet-name>javax.ws.rs.core.Application</servlet-name>
    <url-pattern>/jaxrs/*</url-pattern>
  </servlet-mapping>

Defining the Servlet

TO define a Servlet which would respond on @GET implement this class.

import java.util.HashMap;
import java.util.Map;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("GPS/mine")
public class MyGpsCoordinates {

	@GET
	@Produces(MediaType.APPLICATION_JSON)
	public Map<String, String> getMyGpsCoordinates(){
		Map<String, String> m = new HashMap<>();
		m.put("y", "47.177546");
		m.put("x", "8.430578");
		return m;
	}
}

Responding on POST is possible via annotating a method via @POST

	@POST
	@Consumes("text/plain")
	public void postClichedMessage(String message) {
	    // Store the message
	}

Which URL use to call the web-app in browser?

The URL is a composite of

  1. the address of the Server + http Port
  2. Web Projects' Context Root
  3. url-pattern in web.xml or child of javax.ws.rs.core.Application
  4. the Path, defined in the @Path annotation

The Result in my case is:

http://localhost:8080/ Hochzeitsportalweb/ jaxrs/ System/properties
the address of the Server + http Port

Find out which Port your WildFly provides the HTTP data: http://asasa.paywyw.com/wiki/doku.php?id=jboss&#socket_bindings_-_ports
The default HTTP Prt is 8080

Context Root

Available via Project Settings.

url-pattern in web.xml or child of javax.ws.rs.core.Application

In web.xml there you should find the definition of url-pattern

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
  <display-name>Hochzeitsportalweb</display-name>
  <servlet>
    <description>JAX-RS Tools Generated - Do not modify</description>
    <servlet-name>javax.ws.rs.core.Application</servlet-name>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>javax.ws.rs.core.Application</servlet-name>
    <url-pattern>/jaxrs/*</url-pattern>
  </servlet-mapping>
  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>/faces/*</url-pattern>
  </servlet-mapping>
</web-app>

or if you defined your Application in an own subclass of javax.ws.rs.core.Application and used annotations:

@ApplicationPath("/jaxrs/")
public class TheApplication extends javax.ws.rs.core.Application {
	/* this represents the Web-applicaiton itselfe,	
	 * which contains servlets etc.
	 */
}

Path

The Class, which is responsible for handling get Requests is annotated by @Path


import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

// where to expose this service?
@Path("System/properties")
public class SystemProperties {

	// provide some information on "GET" requests
	@GET
	@Produces(MediaType.APPLICATION_JSON)
	public Map<String, String> getSystemProperties() {
		Map<String, String> result = new HashMap<>();
		Properties props = System.getProperties();

		for (Map.Entry<Object, Object> entry : props.entrySet()) {
			result.put((String) entry.getKey(), (String) entry.getValue());
		}

		return result;
	}
	
	@POST
	@Consumes("text/plain")
	public void postClichedMessage(String message) {
	    // Store the message
	}

}

Persistency

Deploy DB Driver to JBoss

JBoss does NOT have drivers to every DB by default - you have to upload the JNDI Driver, and reference it later, when adding a new DataSource. Deploy the JNDI Driver for your Database (here PostGreSQL) by using admin console.

Here the driver is a file named postgresql-9.4.1207.jre6.jar

Adding DB to JBoss Datasources

Important data:

JNDI Name java:/PostgresDS Used to reference the DB from the JEE application. You can find it standalone.sql:
<datasource jta="false" jndi-name="java:/PostgresDS" pool-name="PostgresDS" enabled="true" use-ccm="false">
Connection URL Used to connect to the DB via http://squirrel-sql.sourceforge.net/
Method1 : Via Admin Console

You can introduce your DataBase to the WildFly, by using the Admin Console:

Method2 : Via standalone.xml
<subsystem xmlns="urn:jboss:domain:datasources:4.0">
	<datasources>
		<datasource jta="false" jndi-name="java:/PostgresDS" pool-name="PostgresDS" enabled="true" use-ccm="false">
			<connection-url>jdbc:postgresql://localhost:5432/hochzeitsportaldb</connection-url>
			<driver-class>org.postgresql.Driver</driver-class>
			<driver>postgresql-9.4.1207.jre6.jar</driver>
			<security>
				<user-name>phppgadmin</user-name>
				<password>YOURPASSWORDHERE</password>
			</security>
			<validation>
				<valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLValidConnectionChecker"/>
				<background-validation>true</background-validation>
				<exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLExceptionSorter"/>
			</validation>
		</datasource>

Modify the persistence.xml

Your JEE Application (here a web-application) has a file named ..src\META-INF\persistence.xml. It contains the DataBase Data.

Modify it as following:

  • add the DB by JNDI Name from standalone.xml (the jndi-name you can find in standalone.xml)
  • add Entity classes to the persistance.xml (here it is de.hochzeitsportal.entity.Foto)
  • choose the hibernate dialect, depending on your DB (here its org.hibernate.dialect.PostgreSQLDialect because of PostreSQL)

This class Foto is an https://docs.oracle.com/javaee/6/tutorial/doc/bnbqa.html and has to be registered in persistance.xml as all Entities has to be.

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Foto implements Serializable {
	
	private static final long serialVersionUID = 1L;
	
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	String id;
	
	@Column(name="pathPreviewFoto")
	String pathPreviewFoto;
	
	@Column(name="pathFullSizeFoto")
	String pathFullSizeFoto;
	
	@Column(name="priority")
	int priority;

	public Foto() {
		super();
	}
   
}

All available dialects are listed here:

This is the resulting persistence.xml for now.

<?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="Hochzeitsportalweb" transaction-type="JTA">
		<jta-data-source>java:/PostgresDS</jta-data-source>
		<class>de.hochzeitsportal.entity.Foto</class>
		<properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
            <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
       </properties>
	</persistence-unit>
</persistence>
  1. TODO write about JTA
  2. TODO about create-drop

Java EE Introduction

Java EE Container managed components

Managed CDI Beans

Managed Context Dependency Injection (CDI) Beans.

What is treated as a CDI bean by the container?

  • it is not a non static inner class
  • It is a concrete class (not derived / inherited), or is annotated @Decorator, and
  • It has a default constructor with no parameters, or it declares a constructor annotated @Inject.

What is available?

  • can inject references to other beans (@Inject),
  • has its life cycle managed by the container (@PostConstruct, @PreDestroy),
  • and can get its method invocation intercepted (here @Transactional is an interceptor binding).
Servlets
SOAP web services
RESTful web services

Transaction Management

DB transactions encapsulate a set of DB operations.
The begin with connection creation and
end with a commit or rollback

Container-Managed Transactions

In CMT container manages start / finish of transaction. The transaction scope of a method is defined by annotations.

possible method annotations:

  • Required
  • RequiresNew
  • Mandatory
  • NotSupported
  • Supports
  • Never

The explanations are here:

Example:

import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;

@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER)
public class DepartmentBean implements DepartmentBeanRemote {

    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public void createDepartment() {
    }
}

Bean-Managed Transactions

In bean-managed transaction demarcation, the code in the session or message-driven bean explicitly marks the boundaries of the transaction.

Scopes

Scopes are a part of JSF - Java Server Faces. The may be used to preserve the Bean in Context.

Bean
  • @SessionScoped, @ApplicationScoped, @RequestScoped, ConversationScoped annotation choose the scope
  • @Named annotation makes the bean reachable from *.jsp. When using annotations - you don't have to register the beans within faces-config.xml anymore

import java.io.Serializable;
import java.util.UUID;

import javax.enterprise.context.SessionScoped;
import javax.inject.Named;

/**
 * - no public methods in non @Dependent (default) scoped beans
 * - must be passivation capable
 * - @javax.inject.Named must be added to the bean to be able to resolve the bean via java-faces. Or it wont be discovered. Further registration in faces.config is not necessary
 */
@Named
@SessionScoped
public class UUIDContainerSessionScoped implements Serializable {
	private static final long serialVersionUID = -866171745569996844L;
	final String uuid = UUID.randomUUID().toString();
	
	public String getUuid() {
		return uuid;
	}
}

bean.xml

Must be available

jsp

The @Named Bean is referenced from a jsp via #{uUIDContainerSessionScoped .uuid}.

JSF is available in JBoss. But Eclipse won't know it. So you have to add JSF implementation to the project, e.g. via Maven.

  
	<!-- JSF implementation, even if the JBoss app server already has this libs.  -->
	<dependency>
		<groupId>javax.faces</groupId>
		<artifactId>jsf-impl</artifactId>
		<version>1.2_15</version>
	</dependency>
	<dependency>
		<groupId>javax.faces</groupId>
		<artifactId>jsf-api</artifactId>
		<version>2.1</version>
	</dependency>

The JSF Page is located under WebContent\YourPage.jsp.
It is requested as: http://localhost:8080/YOURPROJECT/faces/YourPage.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="f"  uri="http://java.sun.com/jsf/core"%>
<%@ taglib prefix="h"  uri="http://java.sun.com/jsf/html"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<f:view>

    <h:outputLabel value="Application: "></h:outputLabel> 
    <h:outputLabel value="#{uUIDContainerSessionScoped .uuid}"></h:outputLabel>
    <br>
    </f:view>
</body>
</html>

Interceptors

The container may execute some code, before EVERY method in the container. The place, where you define the executed code is called interceptor.

Related annotations:

@AroundInvoke
@AroundConstruct
@Interceptors(MyInterceptor1.class)
@ExcludeClassInterceptors
@PostConstruct
@PreDestroy
@InterceptorBinding
@Interceptor
@Priority(200)
Enable Interceptos

In WebContent\WEB-INF\beans.xml the interceptors have to be enabled before use.

Registration of Interceptor implemented in org.agoncal.book.javaee7.chapter02.LoggingInterceptor

<beans 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/beans_1_1.xsd" version="1.1" bean-discovery-mode="all">     
	<interceptors>     
		<class>org.agoncal.book.javaee7.chapter02.LoggingInterceptor</class>   
	</interceptors>
</beans>

Interceptors

Interceptors are methods, which are triggered by special hooks.
The execution context is available for them.

Hooks

  • invocation of a method inside of intercepted class
  • creation (@PostConstruct) and destruction (@PreDestroy) of objects. These interceptors are called “Life-Cycle Interceptors”.

Interceptors

The following things can be intercepted

Class construction

public class MyInterceptedClass{
...
  @AroundConstruct   
  private void init( InvocationContext ic ) throws Exception {     
       logger.fine("Entering constructor");     
       try {       
         ic.proceed();     
       } finally {       
         logger.fine("Exiting constructor");     
       }   
}

Any method invocation in class MyInterceptedClass

public class MyInterceptedClass{
...
	@AroundInvoke
	public Object logMethod(InvocationContext ic) throws Exception {
		logger.entering(ic.getTarget().toString(), ic.getMethod().getName());
		try {
			return ic.proceed();
		} finally {
			logger.exiting(ic.getTarget().toString(), ic.getMethod().getName());
		}
	}

LifeCycle annotation to intercept object-creation and destruction

public class MyInterceptor{
...
	@PostConstruct
	public void prePostConstruct(InvocationContext c) throws Exception{
        ...
        }

	@PreDestroy
	public void prePredestroy(InvocationContext c) throws Exception{
        ...
        }
        
// now apply the interceptor
@Transactional 
@Interceptors(MyInterceptor.class) 
public class CustomerService {

  // interceptor will be triggered first
  @PostConstruct
  void onPostConstruct(){..

  // interceptor will be triggered first
  @PreDestroy
  void onPreDestroy(){..
          

Interceptors in an own class

You can put the Intercepting methods into an own class and reference it via an annotation:

public class LoggingInterceptor {     
 @Inject   
 private Logger logger;

 @AroundConstruct  
 ...

 @AroundInvoke
 ...
}

// Reference the interceptor via @Interceptors annotation.
// You can annotate classes
@Transactional 
@Interceptors({LoggingInterceptor.class, AnotherInterceptor.class})
public class CustomerService {     

 // you can annotate methods
 @Interceptors({LoggingInterceptor.class, AnotherInterceptor.class})
 public void createCustomer(Customer customer) {     
  em.persist(customer);
}

Interceptor Bindings

Is an tool for loose coupling.

Enabling CDI is Required to use Interceptor bindings.
Because this feature is implemented in CDI Spec, which extended the Interceptor spec.

Define own, interceptor annotation @Loggable

Define annotation

@InterceptorBinding 
@Target({METHOD, TYPE}) 
@Retention(RUNTIME) 
public @interface Loggable { }

Associate @Loggable with 2 Interceptors LoggingInterceptor.class, LoggingInterceptor2.class
When @Loggable is applied to an intercepted class - LoggingInterceptor will be executed prior to LoggingInterceptor2, because it's priority is smaller.

@Interceptor 
@Loggable 
@Priority(100)
public class LoggingInterceptor {...}

@Interceptor 
@Loggable 
@Priority(200)
public class LoggingInterceptor {...}

Apply @Loggable to a method or class

@Loggable
public class CustomerService {    

 @Loggable
 public void createCustomer(Customer customer) {   

Priorization to define order of Interception binding

Predefined prorities are defined here: javax.interceptor.Interceptor

PLATFORM_BEFORE = 0: Start of range for early interceptors defined by the Java EE platform,
LIBRARY_BEFORE = 1000: Start of range for early interceptors defined by extension libraries,
APPLICATION = 2000: Start of range for interceptors defined by applications,
LIBRARY_AFTER = 3000: Start of range for late interceptors defined by extension libraries, and
PLATFORM_AFTER = 4000: Start of range for late interceptors defined by the Java EE platform.

Decorators

There is always a @Default version of an injectable bean.
You can modify this injectable bean, by implementing a decorator.

Important:

  • Enable your Decorator implementation in beans.xml
  • Extend your decoratable interface (here NumberGenerator.class)
  • Inject the original, mark it by @Delegate

Enabling a decorator implementation de.exp.decorator.NumberGeneratorDecorator.class in beans.xml

<beans ..>
    ...
    <decorators>
    	<class>de.exp.decorator.NumberGeneratorDecorator</class>
    </decorators>
</beans>

Decorator

import javax.decorator.Decorator;
import javax.decorator.Delegate;
import javax.inject.Inject;

import de.exp.cdibean.stateless.NumberGenerator;

/**
 * Check, how the output is decorated: http://localhost:8080/ExpWebProject/jaxrs/books/isbn/
 *
 */
@Decorator
public class NumberGeneratorDecorator implements NumberGenerator {

	/*
	 * @Delegate - markup is important here. It says, that the decorated method go's here
	 * @Default - annotated NumberGenerator.class implementation will be injected here
	 */
	@Delegate
	@Inject
	NumberGenerator numberGenerator;
	
	@Override
	public String generateNumber() {
		String originalNumber = numberGenerator.generateNumber();
		
		// decorate here
		return getClass().getSimpleName() + "-" + originalNumber;
	}
}

Events

Producers send events. Observers receive events.

Producer


public class ...

	@AddedQualifier
	@IsNewerThan(date=1458493052)
	@Inject
	Event<Date> eventPushTime;
	
	@RemovedQualifier
	@Inject
	Event<Date> eventPopTime;
	
	public void push(){
		eventPushTime.fire(new Date());
	}
	
	public void pop(){
		eventPopTime.fire(dao.timeFifoQueue.peekLast());	
	}

Observer

	public void push(@Observes @AddedQualifier @IsNewerThan(date=1458493052) Date date){ 
...

Optionally the events may be marked by symantically valuable Qualifiers.
The Qualifiers must be added to the Producers Event-Injection point and to Receiver's @Observes parameter
Optionally members (parameters) may be added to the Qualifiers.

@Qualifier 
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
public @interface AddedQualifier{ 
}

@Qualifier 
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
public @interface RemovedQualifier{ 
}

@Qualifier 
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
public @interface IsNewerThan {
	/**
	 * Last date as long
	 * @return
	 */
	public long date();
}

Bean validation

Example

Annotation
Apply @Constraint with the validating class, to tell, that its a constraint.

@Constraint(validatedBy = { URLValidator.class })
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface URL {
	String message()

	default "Malformed URL";
	Class<?>[] groups() default {};
	Class<? extends Payload>[] payload() default {};
	String protocol() default "";
	String host() default "";
	int port() default -1;
}

Validator.
This one Validates @URL. (generic parameter)
This one os triggered, when @URL annotates a String. (generic parameter)

public class URLValidator implements ConstraintValidator<URL, String> {

  private String protocol;
  private String host;
  private int port;

  public void initialize(URL url) {
    this.protocol = url.protocol();
    this.host = url.host();
    this.port = url.port();
  }

  public boolean isValid(String value, ConstraintValidatorContext context) {
  ...
  }
}

Big Example

You can apply annotations to

  • Variables
  • Classes
  • Method parameters (input)
  • Methods (output)

@NotNull 
@Pattern(regexp = "[C,D,M][A-Z][0-9]*")   
private String orderId;

@ClassNameValidator
class Order{

}

public Order( @Past Date creationDate) {
     this.creationDate = creationDate;   }

public @NotNull Double calculateTotalAmount( @GreaterThanZero Double changeRate) { ... }

Existing constraint annotations
Annotation composition

You can aply existing constraints to your own,
ifg existing constraints are annotated by ANNOTATION_TYPE

@NotNull
@Size(min = 7)
@Pattern(regexp = "")
@Constraint(validatedBy = {})
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface Email {
	String message() default "Email address doesn't look good";

	Class<?>[] groups() default {};

	Class<? extends Payload>[] payload() default {};
}

Multiple annotation at the same point

You can apply same annotation multiple times as following:

	@Pattern.List({
		@Pattern(regexp = "^1.*"), 
		@Pattern(regexp = ".*9$"), 
	})
	String var;

Herer @Pattern defines an inner annotation @Pattern.List member, which owns an array of Patterns.
A validator would request the list of Patterns and apply the PatternValidator to each of them.

 */
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {})
public @interface Pattern {
   
        ...


	/**
	 * Defines several <code>@Pattern</code> annotations on the same element
	 * @see Pattern
	 *
	 * @author Emmanuel Bernard
	 */
	@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
	@Retention(RUNTIME)
	@Documented
	@interface List {
		Pattern[] value();
	}
}

Locale

HQL

Converting JPA Query to String

javax.persistence.Query query = getEm().createQuery("select e from " + entityClass.getName() + " e");
        
// QueryImpl(select e from de.ivu.fare.core.domain.MengeMandantBean e)
query.unwrap(QueryImpl.class).getHibernateQuery().getQueryString();

Executing Queries

package my.example;

import java.nio.file.Path;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;
import javax.ejb.Schedule;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.inject.Inject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


@Stateless
public class ReoccuringQueryExecutor {

    private static final Logger LOG = LoggerFactory.getLogger(ReoccuringQueryExecutor.class);

    private static boolean scanning = false;
    private Object lock = new Object();

    @Inject
    private CrudService crudService;


    @Schedule(second = "*/5", minute = "*", hour = "*", persistent = false)
    public void scanFS() {

        synchronized (lock) {
            if (scanning) {
                return;
            }
            scanning = true;
        }

        try {
            executeQuery();

        } catch (Exception e) {
            String message = null;
            LOG.warn(message);

        } finally {
            synchronized (lock) {
                scanning = false;
            }
        }
    }
    /**  You can debug execute the query here     */
    private void executeQuery(){
        CollectorService collectorService = NamingAdapter.get(CollectorService.class, ModuleIds.SALES_MODULE_ID);

        // Execute the query here
        Session session = ((HasHibernateSession) ctx.getTarget()).getSession();
        
        Query query = session.createQuery("update Stock set stockName = :stockName" +
                " where stockCode = :stockCode");
        query.setParameter("stockName", "DIALOG1");
        query.setParameter("stockCode", "7277");
        int result = query.executeUpdate();

		
    }
}


programming/java/java_ee.txt · Last modified: 2023/11/01 07:31 by skipidar