programming:java:java_ee
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revision | |||
programming:java:java_ee [2023/11/01 07:31] – removed - external edit (Unknown date) 127.0.0.1 | programming:java:java_ee [2023/11/01 07:31] (current) – ↷ Page moved from camunda:programming:java:java_ee to programming:java:java_ee skipidar | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | |Java EE|Java Enterprise Edition | | ||
+ | |Java SE|Java Standart Edition | | ||
+ | |SOAP|Simplke Object Transfair Protocol| | ||
+ | |ACC| Application Client Container| | ||
+ | |EJB| Enterprise Java Bean| | ||
+ | |DD| Deployment Descriptor| | ||
+ | |POJO| Plain Old Java Object| | ||
+ | |IoC|Inversion of COntrol| | ||
+ | |JSF|Java Server Faces| | ||
+ | |JSP|Java Server Pages | | ||
+ | |JSF|Java Server Faces| | ||
+ | |JPA|Java Persistance API| | ||
+ | |JMS|Java Messaging Service| | ||
+ | |JDBC |Java Database COnnectivity| | ||
+ | |JNDI |Java Naming and DIrectory Service| | ||
+ | |RMI | Remote Method Invocation| | ||
+ | |||
+ | |||
+ | ===== Lib ===== | ||
+ | |||
+ | |Introduction into JEE |https:// | ||
+ | |Introduction into Hibernate - JPA implementation delivered with JBoss Application Server| http:// | ||
+ | |||
+ | |||
+ | |||
+ | ===== 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: | ||
+ | |||
+ | === 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:// | ||
+ | |||
+ | The Syntax of JNDI Path is the following: | ||
+ | |namespace| **java:/**, **java: | ||
+ | |ressource path| everything after the namespace : java: | ||
+ | |||
+ | Some Details about JNDI Syntax: | ||
+ | * https:// | ||
+ | * http:// | ||
+ | * https:// | ||
+ | * http:// | ||
+ | * https:// | ||
+ | |||
+ | === 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, | ||
+ | |||
+ | === 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(" | ||
+ | * They allow some multiple GET/ | ||
+ | * | ||
+ | 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' | ||
+ | |||
+ | |||
+ | === Servlets === | ||
+ | |||
+ | Servlet is an Java application programming interface (API) running on the server machine, which **intercepts requests made by the client** and **generates/ | ||
+ | |||
+ | 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' | ||
+ | |||
+ | === 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 //< | ||
+ | |||
+ | As being a **MVC (Model-View-Controller) framework**, | ||
+ | |||
+ | 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 === | ||
+ | http:// | ||
+ | |||
+ | |||
+ | ===== 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 | ||
+ | | web.xml | Servlet WEB-INF | | ||
+ | | web-fragment.xml | Servlet WEB-INF | | ||
+ | | webservices.xml | SOAP Web Services META-INF | ||
+ | ===== Services provided by containers ===== | ||
+ | {{http:// | ||
+ | |||
+ | |||
+ | ===== 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, | ||
+ | |||
+ | If your web application contains several jar files and you want to have CDI enabled across the entire application, | ||
+ | |||
+ | |||
+ | ===== 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. | ||
+ | |||
+ | {{http:// | ||
+ | |||
+ | |||
+ | |||
+ | == 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/ | ||
+ | |||
+ | == 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/ | ||
+ | |||
+ | == 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, | ||
+ | |||
+ | == 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/ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== 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 | ||
+ | <sxh java> | ||
+ | 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, | ||
+ | public @interface NumberCalculation2002{ | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | IMplement Injection Point INterface " | ||
+ | It will be the default IMplementation. \\ | ||
+ | It will be an IMplementation qualified with @NumberCalculation2016 | ||
+ | <sxh java> | ||
+ | @Default | ||
+ | @NumberCalculation2016 | ||
+ | @Stateless | ||
+ | public class ISBNGenerator implements NumberGenerator { | ||
+ | |||
+ | @Override | ||
+ | public String generateNumber() { | ||
+ | return " | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Inject implementations. | ||
+ | <sxh java> | ||
+ | @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. | ||
+ | <sxh java> | ||
+ | |||
+ | 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, | ||
+ | * are Qualifiers - names to distinguish which String needs to be injected. | ||
+ | */ | ||
+ | public class NumberProducer { | ||
+ | |||
+ | @Produces @NumberCalculation2016Prefix | ||
+ | private String prefix13DIgits = " | ||
+ | |||
+ | @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, | ||
+ | <sxh java> | ||
+ | // @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 | ||
+ | * | ||
+ | <sxh java> | ||
+ | @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' | ||
+ | |||
+ | <sxh java> | ||
+ | /** | ||
+ | * Producer method - creates a FileOutputStream | ||
+ | * | ||
+ | * @param injectionPoint - contains infos about the environment: | ||
+ | * | ||
+ | * @TempFile will be used at InjectionPoints, | ||
+ | * | ||
+ | * @return | ||
+ | */ | ||
+ | @Produces | ||
+ | @TempFile | ||
+ | private FileOutputStream getFileInputStream(InjectionPoint injectionPoint){ | ||
+ | String beantype = injectionPoint.getBean().getBeanClass().getSimpleName(); | ||
+ | String name = UUID.randomUUID().toString(); | ||
+ | |||
+ | File file = new File(" | ||
+ | FileOutputStream f = null; | ||
+ | try { | ||
+ | f = new FileOutputStream(file); | ||
+ | } catch (FileNotFoundException e) { | ||
+ | e.printStackTrace(); | ||
+ | } | ||
+ | return f; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Destructor method - closes FileOutputStream, | ||
+ | * 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 JEE Projects in Eclipse** : \\ https:// | ||
+ | * Acessing Database : | ||
+ | * providing RESTful Services : | ||
+ | * displaying Dynamic WebPages with Facelets : | ||
+ | ==== Creating a Web Application ==== | ||
+ | |||
+ | |||
+ | === Defining the Application === | ||
+ | |||
+ | You have first to define some informations about the Web-Application itselfe first. | ||
+ | - You can do it by subclassing // | ||
+ | - or you can define it in XML. The Jax-RS implementation will then create an instance | ||
+ | |||
+ | |||
+ | Details | ||
+ | * **JBoss Jax RS implementation reference**: | ||
+ | * **Jax-RS API**, chapter **2.3.2 Servlet**: \\ http:// | ||
+ | |||
+ | == Option1: Subclassing javax.ws.rs.core.Application == | ||
+ | Just create a subclass of **javax.ws.rs.core.Application** and annotate it with **@ApplicationPath** | ||
+ | |||
+ | <sxh java> | ||
+ | import javax.ws.rs.ApplicationPath; | ||
+ | |||
+ | /** | ||
+ | * Read: https:// | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | */ | ||
+ | |||
+ | @ApplicationPath("/ | ||
+ | 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 **/ | ||
+ | |||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | |||
+ | === Defining the Servlet === | ||
+ | TO define a Servlet which would respond on **@GET** implement this class. | ||
+ | |||
+ | <sxh java> | ||
+ | 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(" | ||
+ | public class MyGpsCoordinates { | ||
+ | |||
+ | @GET | ||
+ | @Produces(MediaType.APPLICATION_JSON) | ||
+ | public Map< | ||
+ | Map< | ||
+ | m.put(" | ||
+ | m.put(" | ||
+ | return m; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Responding on POST is possible via annotating a method via **@POST** | ||
+ | |||
+ | <sxh java> | ||
+ | @POST | ||
+ | @Consumes(" | ||
+ | public void postClichedMessage(String message) { | ||
+ | // Store the message | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | === Which URL use to call the web-app in browser? === | ||
+ | |||
+ | The URL is a composite of | ||
+ | - the address of the Server + http Port | ||
+ | - Web Projects' | ||
+ | - url-pattern in **web.xml** or child of **javax.ws.rs.core.Application** | ||
+ | - the Path, defined in the **@Path** annotation | ||
+ | |||
+ | The Result in my case is: | ||
+ | < | ||
+ | http:// | ||
+ | </ | ||
+ | |||
+ | == the address of the Server + http Port == | ||
+ | |||
+ | Find out which Port your WildFly provides the HTTP data: http:// | ||
+ | The default HTTP Prt is **8080** | ||
+ | |||
+ | |||
+ | == Context Root == | ||
+ | Available via Project Settings. | ||
+ | |||
+ | {{http:// | ||
+ | |||
+ | |||
+ | |||
+ | == 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=" | ||
+ | <web-app xmlns: | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | or if you defined your Application in an own subclass of **javax.ws.rs.core.Application** and used annotations: | ||
+ | <sxh java> | ||
+ | @ApplicationPath("/ | ||
+ | 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 | ||
+ | <sxh java> | ||
+ | |||
+ | 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(" | ||
+ | public class SystemProperties { | ||
+ | |||
+ | // provide some information on " | ||
+ | @GET | ||
+ | @Produces(MediaType.APPLICATION_JSON) | ||
+ | public Map< | ||
+ | Map< | ||
+ | Properties props = System.getProperties(); | ||
+ | |||
+ | for (Map.Entry< | ||
+ | result.put((String) entry.getKey(), | ||
+ | } | ||
+ | |||
+ | return result; | ||
+ | } | ||
+ | |||
+ | @POST | ||
+ | @Consumes(" | ||
+ | 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** | ||
+ | |||
+ | {{http:// | ||
+ | |||
+ | === Adding DB to JBoss Datasources === | ||
+ | |||
+ | |||
+ | Important data: | ||
+ | |JNDI Name| java:/ | ||
+ | |Connection URL| |Used to connect to the DB via [[programming: | ||
+ | |||
+ | == Method1 : Via Admin Console == | ||
+ | You can introduce your DataBase to the WildFly, by using the Admin Console: | ||
+ | |||
+ | {{http:// | ||
+ | {{http:// | ||
+ | {{http:// | ||
+ | |||
+ | |||
+ | == Method2 : Via standalone.xml == | ||
+ | |||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | |||
+ | === 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 [[programming: | ||
+ | <sxh java> | ||
+ | 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=" | ||
+ | String pathPreviewFoto; | ||
+ | |||
+ | @Column(name=" | ||
+ | String pathFullSizeFoto; | ||
+ | |||
+ | @Column(name=" | ||
+ | int priority; | ||
+ | |||
+ | public Foto() { | ||
+ | super(); | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | |||
+ | All available dialects are listed here: | ||
+ | * http:// | ||
+ | * https:// | ||
+ | |||
+ | |||
+ | This is the resulting persistence.xml for now. | ||
+ | < | ||
+ | <?xml version=" | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | - TODO write about JTA | ||
+ | - 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**, | ||
+ | * It has a default **constructor with no parameters**, | ||
+ | |||
+ | |||
+ | What is available? | ||
+ | |||
+ | * can **inject** references to other beans (@Inject), | ||
+ | * has its **life cycle** managed by the container (@PostConstruct, | ||
+ | * 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: | ||
+ | * http:// | ||
+ | * http:// | ||
+ | |||
+ | Example: | ||
+ | |||
+ | <sxh java> | ||
+ | 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, | ||
+ | |||
+ | |||
+ | ==== Scopes ==== | ||
+ | Scopes are a part of JSF - Java Server Faces. | ||
+ | The may be used to preserve the Bean in Context. | ||
+ | |||
+ | ==Bean== | ||
+ | * @SessionScoped, | ||
+ | * @Named annotation makes the bean reachable from *.jsp. When using annotations - you don't have to register the beans within faces-config.xml anymore | ||
+ | |||
+ | <sxh java> | ||
+ | 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 **# | ||
+ | |||
+ | 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, | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | The JSF Page is located under **WebContent\YourPage.jsp**. \\ | ||
+ | It is requested as: http:// | ||
+ | |||
+ | < | ||
+ | <%@ page language=" | ||
+ | <%@ taglib prefix=" | ||
+ | <%@ taglib prefix=" | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | <meta http-equiv=" | ||
+ | < | ||
+ | </ | ||
+ | < | ||
+ | < | ||
+ | |||
+ | < | ||
+ | < | ||
+ | <br> | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | |||
+ | ==== Interceptors ==== | ||
+ | |||
+ | The container may execute some code, before EVERY method in the container. | ||
+ | The place, where you define the executed code is called interceptor. | ||
+ | |||
+ | {{http:// | ||
+ | |||
+ | 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=" | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | |||
+ | === 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 " | ||
+ | * | ||
+ | |||
+ | === Interceptors === | ||
+ | |||
+ | == The following things can be intercepted == | ||
+ | |||
+ | Class construction | ||
+ | <sxh java> | ||
+ | public class MyInterceptedClass{ | ||
+ | ... | ||
+ | @AroundConstruct | ||
+ | private void init( InvocationContext ic ) throws Exception { | ||
+ | | ||
+ | try { | ||
+ | | ||
+ | } finally { | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Any method invocation in class MyInterceptedClass | ||
+ | <sxh java> | ||
+ | public class MyInterceptedClass{ | ||
+ | ... | ||
+ | @AroundInvoke | ||
+ | public Object logMethod(InvocationContext ic) throws Exception { | ||
+ | logger.entering(ic.getTarget().toString(), | ||
+ | try { | ||
+ | return ic.proceed(); | ||
+ | } finally { | ||
+ | logger.exiting(ic.getTarget().toString(), | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | LifeCycle annotation to intercept object-creation and destruction | ||
+ | <sxh java> | ||
+ | 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: | ||
+ | |||
+ | <sxh java> | ||
+ | public class LoggingInterceptor { | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | ... | ||
+ | |||
+ | | ||
+ | ... | ||
+ | } | ||
+ | |||
+ | // Reference the interceptor via @Interceptors annotation. | ||
+ | // You can annotate classes | ||
+ | @Transactional | ||
+ | @Interceptors({LoggingInterceptor.class, | ||
+ | public class CustomerService { | ||
+ | |||
+ | // you can annotate methods | ||
+ | | ||
+ | | ||
+ | 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 | ||
+ | <sxh java> | ||
+ | @InterceptorBinding | ||
+ | @Target({METHOD, | ||
+ | @Retention(RUNTIME) | ||
+ | public @interface Loggable { } | ||
+ | </ | ||
+ | |||
+ | Associate @Loggable with 2 Interceptors LoggingInterceptor.class, | ||
+ | When @Loggable is applied to an intercepted class - LoggingInterceptor will be executed prior to LoggingInterceptor2, | ||
+ | |||
+ | <sxh java> | ||
+ | @Interceptor | ||
+ | @Loggable | ||
+ | @Priority(100) | ||
+ | public class LoggingInterceptor {...} | ||
+ | |||
+ | @Interceptor | ||
+ | @Loggable | ||
+ | @Priority(200) | ||
+ | public class LoggingInterceptor {...} | ||
+ | </ | ||
+ | |||
+ | Apply @Loggable to a method or class | ||
+ | <sxh java> | ||
+ | @Loggable | ||
+ | public class CustomerService { | ||
+ | |||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | == 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 ..> | ||
+ | ... | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | |||
+ | Decorator | ||
+ | <sxh> | ||
+ | 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:// | ||
+ | * | ||
+ | */ | ||
+ | @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() + " | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Events ==== | ||
+ | |||
+ | Producers send events. | ||
+ | Observers receive events. | ||
+ | |||
+ | Producer | ||
+ | <sxh java> | ||
+ | |||
+ | public class ... | ||
+ | |||
+ | @AddedQualifier | ||
+ | @IsNewerThan(date=1458493052) | ||
+ | @Inject | ||
+ | Event< | ||
+ | |||
+ | @RemovedQualifier | ||
+ | @Inject | ||
+ | Event< | ||
+ | |||
+ | public void push(){ | ||
+ | eventPushTime.fire(new Date()); | ||
+ | } | ||
+ | |||
+ | public void pop(){ | ||
+ | eventPopTime.fire(dao.timeFifoQueue.peekLast()); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Observer | ||
+ | <sxh java> | ||
+ | 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' | ||
+ | Optionally **members** (parameters) may be added to the Qualifiers. | ||
+ | |||
+ | <sxh> | ||
+ | @Qualifier | ||
+ | @Retention(RetentionPolicy.RUNTIME) | ||
+ | @Target({ElementType.FIELD, | ||
+ | public @interface AddedQualifier{ | ||
+ | } | ||
+ | |||
+ | @Qualifier | ||
+ | @Retention(RetentionPolicy.RUNTIME) | ||
+ | @Target({ElementType.FIELD, | ||
+ | public @interface RemovedQualifier{ | ||
+ | } | ||
+ | |||
+ | @Qualifier | ||
+ | @Retention(RetentionPolicy.RUNTIME) | ||
+ | @Target({ElementType.FIELD, | ||
+ | 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. | ||
+ | <sxh java> | ||
+ | @Constraint(validatedBy = { URLValidator.class }) | ||
+ | @Target({ METHOD, FIELD, ANNOTATION_TYPE, | ||
+ | @Retention(RetentionPolicy.RUNTIME) | ||
+ | public @interface URL { | ||
+ | String message() | ||
+ | |||
+ | default " | ||
+ | Class<?> | ||
+ | Class<? extends Payload> | ||
+ | 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) | ||
+ | |||
+ | <sxh java> | ||
+ | public class URLValidator implements ConstraintValidator< | ||
+ | |||
+ | 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) | ||
+ | |||
+ | <sxh java> | ||
+ | @NotNull | ||
+ | @Pattern(regexp = " | ||
+ | private String orderId; | ||
+ | |||
+ | @ClassNameValidator | ||
+ | class Order{ | ||
+ | |||
+ | } | ||
+ | |||
+ | public Order( @Past Date creationDate) { | ||
+ | | ||
+ | |||
+ | public @NotNull Double calculateTotalAmount( @GreaterThanZero Double changeRate) { ... } | ||
+ | |||
+ | </ | ||
+ | |||
+ | == Existing constraint annotations == | ||
+ | |||
+ | https:// | ||
+ | |||
+ | == Annotation composition == | ||
+ | |||
+ | You can aply existing constraints to your own, \\ | ||
+ | ifg existing constraints are annotated by **ANNOTATION_TYPE** | ||
+ | |||
+ | <sxh java> | ||
+ | @NotNull | ||
+ | @Size(min = 7) | ||
+ | @Pattern(regexp = "" | ||
+ | @Constraint(validatedBy = {}) | ||
+ | @Target({ METHOD, FIELD, ANNOTATION_TYPE, | ||
+ | @Retention(RetentionPolicy.RUNTIME) | ||
+ | public @interface Email { | ||
+ | String message() default "Email address doesn' | ||
+ | |||
+ | Class<?> | ||
+ | |||
+ | Class<? extends Payload> | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | == Multiple annotation at the same point == | ||
+ | |||
+ | You can apply same annotation multiple times as following: | ||
+ | |||
+ | <sxh java> | ||
+ | @Pattern.List({ | ||
+ | @Pattern(regexp = " | ||
+ | @Pattern(regexp = " | ||
+ | }) | ||
+ | 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. | ||
+ | |||
+ | <sxh java> | ||
+ | */ | ||
+ | @Target({ METHOD, FIELD, ANNOTATION_TYPE, | ||
+ | @Retention(RUNTIME) | ||
+ | @Documented | ||
+ | @Constraint(validatedBy = {}) | ||
+ | public @interface Pattern { | ||
+ | |||
+ | ... | ||
+ | |||
+ | |||
+ | /** | ||
+ | * Defines several < | ||
+ | * @see Pattern | ||
+ | * | ||
+ | * @author Emmanuel Bernard | ||
+ | */ | ||
+ | @Target({ METHOD, FIELD, ANNOTATION_TYPE, | ||
+ | @Retention(RUNTIME) | ||
+ | @Documented | ||
+ | @interface List { | ||
+ | Pattern[] value(); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | === Locale === | ||
+ | * Default locale. | ||
+ | * Custom Message Interpolation http:// | ||
+ | * JSF (.xhtml) vs. JSP (faces/ | ||
+ | * adding a .properties and referencing it from xhtml (messages) | ||
+ | * mvn **war:war** und andere plugins? | ||
+ | * brackets around the message() default **{....key...}** | ||
+ | |||
+ | |||
+ | ===== HQL ===== | ||
+ | |||
+ | == Converting JPA Query to String == | ||
+ | |||
+ | <sxh java> | ||
+ | javax.persistence.Query query = getEm().createQuery(" | ||
+ | | ||
+ | // QueryImpl(select e from de.ivu.fare.core.domain.MengeMandantBean e) | ||
+ | query.unwrap(QueryImpl.class).getHibernateQuery().getQueryString(); | ||
+ | </ | ||
+ | |||
+ | == Executing Queries == | ||
+ | |||
+ | <sxh java> | ||
+ | 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 = " | ||
+ | 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, | ||
+ | |||
+ | // Execute the query here | ||
+ | Session session = ((HasHibernateSession) ctx.getTarget()).getSession(); | ||
+ | | ||
+ | Query query = session.createQuery(" | ||
+ | " where stockCode = : | ||
+ | query.setParameter(" | ||
+ | query.setParameter(" | ||
+ | int result = query.executeUpdate(); | ||
+ | |||
+ | |||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | </ |