diff --git a/docs/chapters/appendix.adoc b/docs/chapters/appendix.adoc index d929f96..2cac0e4 100755 --- a/docs/chapters/appendix.adoc +++ b/docs/chapters/appendix.adoc @@ -13,16 +13,6 @@ ifdef::server-wildfly[] [[appendix-wildfly-netbeans]] === Configure WildFly 8 in NetBeans -==== Configure Update Center - -. If you are using NetBeans development build then skip this section and go to <>. Otherwise in NetBeans, click on `Tools', `Plugins', `Settings', and click on `Add'. -+ -. Specify the name as ``Dev Update Center'' and the URL as ``http://deadlock.netbeans.org/job/nbms-and-javadoc/lastStableBuild/artifact/nbbuild/nbms/updates.xml.gz''. -+ -image::16-netbeans-add-dev-update-center.png[title="NetBeans Update Center"] -+ -and click on btn:[OK]. - [[install-wildfly-plugin]] ==== Install WildFly plugin diff --git a/docs/chapters/batch.adoc b/docs/chapters/batch.adoc index 6d393f6..baa7a2d 100644 --- a/docs/chapters/batch.adoc +++ b/docs/chapters/batch.adoc @@ -241,7 +241,7 @@ Replace contents of the file with the following: [source, xml] ---- @@ -346,32 +346,34 @@ Replace `` section with `content' name such that it looks like: + [source, xml] ---- - -

Movie Sales

- - - - - - - #{s.id} - - - - - - #{s.amount} - - - - - -
+ + +

Movie Sales

+ + + + + + + #{s.id} + + + + + + #{s.amount} + + + + + +
+
---- + This code displays the show identifier and sales from that show in a diff --git a/docs/chapters/introduction.adoc b/docs/chapters/introduction.adoc index 7c19eba..af91d1e 100644 --- a/docs/chapters/introduction.adoc +++ b/docs/chapters/introduction.adoc @@ -38,7 +38,7 @@ http://www.oracle.com/technetwork/java/javase/downloads/index.html[http://www.or * *Application Server*: This lab can use WildFly 8 or GlassFish 4 as the application server. This document provides instructions for ifdef::server-wildfly[WildFly 8.] ifdef::server-glassfish[GlassFish.] -* *IDE*: NetBeans 7.4+, JBoss Developer Studio (Eclipse-based), or IntelliJ IDEA 13 can be used. This document provides instructions for +* *IDE*: NetBeans 8.0+, JBoss Developer Studio (Eclipse-based), or IntelliJ IDEA 13 can be used. This document provides instructions for ifdef::ide-netbeans[] NetBeans 8. + diff --git a/docs/chapters/jaxrs.adoc b/docs/chapters/jaxrs.adoc index d1d30c5..d4e41f2 100644 --- a/docs/chapters/jaxrs.adoc +++ b/docs/chapters/jaxrs.adoc @@ -118,16 +118,18 @@ Replace `` section with `content' name such that it looks like: + [source, xml] ---- - - - - - - - - - - + + + + + + + + + + + + ---- + This code fragment invokes `getMovies` method from `MovieClientBean`, diff --git a/docs/chapters/jms.adoc b/docs/chapters/jms.adoc index 48adb6b..cf6bf89 100644 --- a/docs/chapters/jms.adoc +++ b/docs/chapters/jms.adoc @@ -222,24 +222,26 @@ Replace the `` section with `content' name such that it looks like: + [source, xml] ---- - -

Points

- - Queue size: -

- - - - - - - + + +

Points

+ + Queue size: +

+ + + + + + + + ---- + Click on the yellow bulb to resolve namespace prefix/URI mapping for `h:` diff --git a/docs/chapters/jsf.adoc b/docs/chapters/jsf.adoc index 47ef3bb..7f4fb6e 100644 --- a/docs/chapters/jsf.adoc +++ b/docs/chapters/jsf.adoc @@ -51,22 +51,24 @@ Replace `` section with `content' name such that it looks like: + [source, xml] ---- - -

Pick a movie

- - - - - - -
+ + +

Pick a movie

+ + + + + + +
+
---- + The code builds an HTML form that displays the list of movies as radio @@ -86,8 +88,9 @@ Specify the class name as `Booking' and the package name as + Add `@Named` class-level annotation to make the class EL-injectable. + -Add `@FlowScoped("booking")` to define the scope of bean as the flow. The bean -is automatically activated and passivated as the flow is entered or exited. +Add `@FlowScoped("booking")` to define the scope of bean as the flow. The bean is automatically activated and passivated as the flow is entered or exited. ++ +Add `implements Serializable` to the class as beans with `@FlowScoped` annotation need to be passivation capable, and thus serializable. + Add the following field: + @@ -139,18 +142,20 @@ Replace `` section with `content' name such that it looks like: + [source, xml] ---- - -

Show Timings for #{booking.movieName}

- - - - - - - - - -
+ + +

Show Timings for #{booking.movieName}

+ + + + + + + + + +
+
---- + This code builds an HTML form that displays the chosen movie name and @@ -246,28 +251,30 @@ Replace `' section with `content' name such that it looks like: + [source, xml] ---- - - - -

No theater found, choose a different time

- - Movie name: #{booking.movieName}

- Starts at: #{booking.startTime}

- - - - -

Confirm ?

- - Movie name: #{booking.movieName}

- Starts at: #{booking.startTime}

- Theater: #{booking.theater}

- - - - - - + + + + +

No theater found, choose a different time

+ + Movie name: #{booking.movieName}

+ Starts at: #{booking.startTime}

+ + + + +

Confirm ?

+ + Movie name: #{booking.movieName}

+ Starts at: #{booking.startTime}

+ Theater: #{booking.theater}

+ + + + + + + ---- + The code displays the selected movie, show timing, and theater if @@ -292,15 +299,17 @@ Replace `` section with `content' name such that it looks like: + [source, xml] ---- - -

Reservation Confirmed

- - Movie name: #{booking.movieName}

- Starts at: #{booking.startTime}

- Theater: #{booking.theater}

-

- - + + +

Reservation Confirmed

+ + Movie name: #{booking.movieName}

+ Starts at: #{booking.startTime}

+ Theater: #{booking.theater}

+

+ + + ---- + This code displays the movie name, show timings, and the selected diff --git a/docs/chapters/json.adoc b/docs/chapters/json.adoc index 349b5f8..4140903 100644 --- a/docs/chapters/json.adoc +++ b/docs/chapters/json.adoc @@ -199,29 +199,31 @@ Replace `` section with `content' name such that it looks like: + [source, xml] ---- - -

Add a New Movie

- - - - - - - - - - - - - - -
Movie Id:
Movie Name:
Movie Actors:
- -
-
+ + +

Add a New Movie

+ + + + + + + + + + + + + + +
Movie Id:
Movie Name:
Movie Actors:
+ +
+
+
---- + This code creates a form to accept input of `id`, `name`, and `actors` of a diff --git a/docs/chapters/revision.adoc b/docs/chapters/revision.adoc index 4fc5098..7037523 100644 --- a/docs/chapters/revision.adoc +++ b/docs/chapters/revision.adoc @@ -2,7 +2,8 @@ == Revision History -. Added IntelliJ IDEA specific instructions. (Jan 22, 2014) -. Added macros to generate WildFly and GlassFish-server specific instructions. Also enabled IntelliJ and Eclipse specific macros. (Jan 10, 2014) +. Cleaned up NetBeans instructions and some other typos from DevoxxUK (Jun 25, 2014) +. Added IntelliJ IDEA specific instructions (Jan 22, 2014) +. Added macros to generate WildFly and GlassFish-server specific instructions. Also enabled IntelliJ and Eclipse specific macros (Jan 10, 2014) . Moving the source document from Pages to AsciiDoc (Dec 3, 2013) diff --git a/docs/chapters/solutions.adoc b/docs/chapters/solutions.adoc index c1b1aed..ae2741a 100644 --- a/docs/chapters/solutions.adoc +++ b/docs/chapters/solutions.adoc @@ -2,5 +2,5 @@ == Completed Solutions -The completed solution can be downloaded from https://github.com/javaee-samples/javaee7-hol/blob/master/solution/movieplex7-solution.zip[javaee7-hol]. +The completed solution for this lab can be downloaded from https://github.com/javaee-samples/javaee7-hol/blob/master/solution/movieplex7-solution.zip[javaee7-hol]. diff --git a/docs/chapters/walkthrough.adoc b/docs/chapters/walkthrough.adoc index 4a8de1a..807e162 100644 --- a/docs/chapters/walkthrough.adoc +++ b/docs/chapters/walkthrough.adoc @@ -55,16 +55,16 @@ Web Profile Specification. ================= ifdef::server-glassfish[] GlassFish can be downloaded in two different flavors – Full Platform or Web Profile. + +IMPORTANT: This lab requires Full Platform download. All technologies used in this +lab, except Java Message Service and Batch Applications for the Java +Platform, can be deployed on Web Profile. endif::server-glassfish[] ifdef::server-wildfly[] WildFly can be started in Full Platform or Web Profile. endif::server-wildfly[] -IMPORTANT: This lab requires Full Platform download. All technologies used in this -lab, except Java Message Service and Batch Applications for the Java -Platform, can be deployed on Web Profile. -- - . *Default Data Source*: Expand `Other Sources', `src/main/resources', `META-INF', and double-click on `persistence.xml'. By default, NetBeans opens the file in Design View. Click on `Source' tab diff --git a/docs/chapters/websocket.adoc b/docs/chapters/websocket.adoc index c769fe5..12f1b02 100644 --- a/docs/chapters/websocket.adoc +++ b/docs/chapters/websocket.adoc @@ -105,33 +105,35 @@ In this file, remove sections where name attribute value is Replace `` section with `content' name such that it looks like: + [source,xml] - -
- - - - - - - - -
- Chat Log
- -
- Users
- -
- - -

- -

-
-
- -
+ + +
+ + + + + + + + +
+ Chat Log
+ +
+ Users
+ +
+ + +

+ +

+
+
+ +
+
+ The code builds an HTML form that has two textareas – one to display the chat log and the other to display the list of users currently logged. A @@ -147,7 +149,7 @@ There is an explicit button to disconnect the WebSocket connection. initialization occurs in `websocket.js' included at the bottom of the fragment. + -. Right-click on `chat' in `Web Pages', select `New', `Web' +. Right-click on `chat' in `Web Pages', select `New', `Other', `Web' categories, `JavaScript File' file type. Click on `Next'. + Give the name as `websocket' and click on `Finish'. diff --git a/docs/javaee7-hol.adoc b/docs/javaee7-hol.adoc index b384bd6..bda142c 100644 --- a/docs/javaee7-hol.adoc +++ b/docs/javaee7-hol.adoc @@ -1,6 +1,6 @@ = Java EE 7 Hands-on Lab -Arun Gupta -v2.0, Jan 28, 2014 +Arun Gupta +v2.1, Jun 25, 2014 :doctype: book :toc: :toclevels: 3 diff --git a/docs/javaee7-hol.html b/docs/javaee7-hol.html index 092cf42..883fe06 100644 --- a/docs/javaee7-hol.html +++ b/docs/javaee7-hol.html @@ -2,7 +2,7 @@ - + Java EE 7 Hands-on Lab + - +

2.2. Estimated Time

@@ -813,10 +892,10 @@

2.2. Estimated Time

Here is an approximate time estimate for each section:

- +
--++ @@ -855,6 +934,7 @@

2.2. Estimated Time

+

The listed time for each section is only an estimate and by no means restrict you within that. These sections have been completed in much @@ -911,16 +991,18 @@

3. Walk-through of Sample Application

Maven Coordinates: Expand ‘Project Files’ and double click on ‘pom.xml’. In the ‘pom.xml’, the Java EE 7 API is specified as a <dependency>:

+
+
-
<dependencies>
-    <dependency>
-        <groupId>javax</groupId>
-        <artifactId>javaee-api</artifactId>
-        <version>7.0</version>
-        <scope>provided</scope>
-    </dependency>
-</dependencies>
+
<dependencies>
+    <dependency>
+        <groupId>javax</groupId>
+        <artifactId>javaee-api</artifactId>
+        <version>7.0</version>
+        <scope>provided</scope>
+    </dependency>
+</dependencies>
@@ -955,19 +1037,7 @@

3. Walk-through of Sample Application

WildFly can be started in Full Platform or Web Profile.

-
- - - - - -
-
Important
-
-This lab requires Full Platform download. All technologies used in this -lab, except Java Message Service and Batch Applications for the Java -Platform, can be deployed on Web Profile. -
+
  • @@ -975,6 +1045,8 @@

    3. Walk-through of Sample Application

    ‘src/main/resources’, ‘META-INF’, and double-click on ‘persistence.xml’. By default, NetBeans opens the file in Design View. Click on ‘Source’ tab to view the XML source.

    +
    +
    3.2 persistence xml @@ -986,42 +1058,42 @@

    3. Walk-through of Sample Application

    -
    <?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="movieplex7PU" transaction-type="JTA">
    -        <!--
    +
    <?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="movieplex7PU" transaction-type="JTA">
    +        <!--
                 <jta-data-source>java:comp/DefaultDataSource</jta-data-source>
    -        -->
    -        <properties>
    -            <property
    -                name="javax.persistence.schema-generation.database.action"
    -                value="drop-and-create"/>
    -            <property
    -                name="javax.persistence.schema-generation.create-source"
    -                value="script"/>
    -            <property
    -                name="javax.persistence.schema-generation.drop-source"
    -                value="script"/>
    -            <property
    -                name="javax.persistence.schema-generation.drop-script-source"
    -                value="META-INF/drop.sql"/>
    -            <property
    -                name="javax.persistence.sql-load-script-source"
    -                value="META-INF/load.sql"/>
    -            <property
    -                name="eclipselink.deploy-on-startup"
    -                value="true"/>
    -            <property
    -                name="eclipselink.logging.exceptions"
    -                value="false"/>
    -        </properties>
    -    </persistence-unit>
    -</persistence>
    + --> + <properties> + <property + name="javax.persistence.schema-generation.database.action" + value="drop-and-create"/> + <property + name="javax.persistence.schema-generation.create-source" + value="script"/> + <property + name="javax.persistence.schema-generation.drop-source" + value="script"/> + <property + name="javax.persistence.schema-generation.drop-script-source" + value="META-INF/drop.sql"/> + <property + name="javax.persistence.sql-load-script-source" + value="META-INF/load.sql"/> + <property + name="eclipselink.deploy-on-startup" + value="true"/> + <property + name="eclipselink.logging.exceptions" + value="false"/> + </properties> + </persistence-unit> +</persistence>
    @@ -1036,7 +1108,7 @@

    3. Walk-through of Sample Application

    -
    java:comp/DefaultDataSource
    +
    java:comp/DefaultDataSource
    @@ -1062,6 +1134,8 @@

    3. Walk-through of Sample Application

    This will get resolved when we run the application. Click on ‘OK’ to dismiss the dialog.

    +
    +
  • Schema Generation: JPA 2.1 defines a new set of @@ -1072,16 +1146,18 @@

    3. Walk-through of Sample Application

    or as part of EntityManagerFactory creation. This feature will allow your JPA domain object model to be directly generated in a database. The generated schema may need to be tuned for actual production environment.

    +
    +

    The “persistence.xml” in the application has the following javax.persistence.schema-generation.* properties. Their meaning and possible values are explained:

    - +
    ---+++ @@ -1099,7 +1175,7 @@

    3. Walk-through of Sample Application

    +javax.persistence.schema-generation.drop-source

    @@ -1107,7 +1183,7 @@

    3. Walk-through of Sample Application

    +javax.persistence.schema-generation.drop-script-source

    @@ -1122,6 +1198,7 @@

    3. Walk-through of Sample Application

    javax.persistence.schema-generation.create-source - javax.persistence.schema-generation.drop-source

    Specifies whether the creation or deletion of database artifacts is to occur on the basis of the object/relational mapping metadata, DDL script, or a combination of the two.

    javax.persistence.schema-generation.create-script-source - javax.persistence.schema-generation.drop-script-source

    Specifies a java.IO.Reader configured for reading of the SQL script or a string designating a file URL for the SQL script to create or delete database artifacts.

    +

    Refer to the JPA 2.1 Specification for a complete understanding of these properties.

    @@ -1145,6 +1222,8 @@

    3. Walk-through of Sample Application

    This folder also contains ‘sales.csv’ which carries some comma-separated data, and is used later in the application.

    +
    +
  • JPA entities, Stateless EJBs, and REST endpoints: Expand Source @@ -1152,6 +1231,8 @@

    3. Walk-through of Sample Application

    JPA entities corresponding to the database table definitions. Each JPA entity has several convenient @NamedQuery defined and uses Bean Validation constraints to enforce validation.

    +
    +

    The package org.javaee7.movieplex7.rest contains stateless EJBs corresponding to different JPA entities.

    @@ -1167,11 +1248,11 @@

    3. Walk-through of Sample Application

    The mapping between JPA entity classes, EJB classes, and the URI of the corresponding REST endpoint is shown.

    - +
    ---+++ @@ -1184,39 +1265,44 @@

    3. Walk-through of Sample Application

    - + - + - + - + - +

    Movie

    MovieFacadeREST

    /webresources/movie

    /webresources/movie

    Sales

    SalesFacadeREST

    /webresources/sales

    /webresources/sales

    ShowTiming

    ShowTimingFacadeREST

    /webresources/showtiming

    /webresources/showtiming

    Theater

    TheaterFacadeREST

    /webresources/theater

    /webresources/theater

    Timeslot

    TimeslotFacadeREST

    /webresources/timeslot

    /webresources/timeslot

    +

    Feel free to browse through the code.

    +
    +
  • JSF pages: ‘WEB-INF/template.xhtml’ defines the template of the web page and has a header, left navigation bar, and a main content section. ‘index.xhtml’ uses this template and the EJBs to display the number of movies and theaters.

    +
    +

    Java EE 7 enables CDI discovery of beans by default. No ‘beans.xml’ is required in ‘WEB-INF’. This allows all beans with bean defining @@ -1230,6 +1316,8 @@

    3. Walk-through of Sample Application

    the application and thus allowing other external pages to use it as well.

    +
    +
  • Run the sample: Right-click on the project and select ‘Run’. @@ -1240,6 +1328,8 @@

    3. Walk-through of Sample Application

    localhost:8080/movieplex7 in the default browser configured in NetBeans. Note that this could take a while if you have never built a Maven application on your machine.

    +
    +
    @@ -1274,6 +1364,8 @@

    3. Walk-through of Sample Application

    Figure 12. Application main page
    + + @@ -1338,25 +1430,25 @@

    4. Chat Room (Java API for WebSocket)

    Change the class such that it looks like:

    -
    @ServerEndpoint("/websocket")
    -public class ChatServer {
    -    private static final Set<Session> peers =
    -               Collections.synchronizedSet(new HashSet<Session>());
    +
    @ServerEndpoint("/websocket")
    +public class ChatServer {
    +    private static final Set<Session> peers =
    +               Collections.synchronizedSet(new HashSet<Session>());
     
    -    @OnOpen
    -    public void onOpen(Session peer) {
    +    @OnOpen
    +    public void onOpen(Session peer) {
             peers.add(peer);
         }
     
    -    @OnClose
    -    public void onClose(Session peer) {
    +    @OnClose
    +    public void onClose(Session peer) {
             peers.remove(peer);
         }
     
    -    @OnMessage
    -    public void message(String message, Session client)
    -           throws IOException, EncodeException {
    -        for (Session peer : peers) {
    +    @OnMessage
    +    public void message(String message, Session client)
    +           throws IOException, EncodeException {
    +        for (Session peer : peers) {
                 peer.getBasicRemote().sendText(message);
             }
         }
    @@ -1385,7 +1477,7 @@ 

    4. Chat Room (Java API for WebSocket)

    all clients connected to this endpoint.

    Resolve the imports by right-clicking in the editor and selecting ‘Fix -Imports’ or (Command + Shift + I shortcut on Mac or Ctrl + Shift + I on +Imports’ or (Command+Shift+I shortcut on OSX or Ctrl+Shift+I on Windows).

    @@ -1439,33 +1531,35 @@

    4. Chat Room (Java API for WebSocket)

    -
    <ui:define name="content">
    -    <form action="">
    -        <table>
    -            <tr>
    -                <td>
    -                    Chat Log<br/>
    -                    <textarea readonly="true" rows="6" cols="50" id="chatlog"></textarea>
    -                </td>
    -                <td>
    -                    Users<br/>
    -                    <textarea readonly="true" rows="6" cols="20" id="users"></textarea>
    -                </td>
    -            </tr>
    -            <tr>
    -                <td colspan="2">
    -                    <input id="textField" name="name" value="Duke" type="text"/>
    -                    <input onclick="join();" value="Join" type="button"/>
    -                    <input onclick="send_message();" value="Send" type="button"/><p/>
    -                    <input onclick="disconnect();" value="Disconnect" type="button"/>
    -                </td>
    -            </tr>
    -        </table>
    -    </form>
    -    <div id="output"></div>
    -        <script language="javascript" type="text/javascript"
    -            src="${facesContext.externalContext.requestContextPath}/chat/websocket.js"></script>
    -</ui:define>
    +
    <ui:composition template="../WEB-INF/template.xhtml">
    +    <ui:define name="content">
    +        <form action="">
    +            <table>
    +                <tr>
    +                    <td>
    +                        Chat Log<br/>
    +                        <textarea readonly="true" rows="6" cols="50" id="chatlog"></textarea>
    +                    </td>
    +                    <td>
    +                        Users<br/>
    +                        <textarea readonly="true" rows="6" cols="20" id="users"></textarea>
    +                    </td>
    +                </tr>
    +                <tr>
    +                    <td colspan="2">
    +                        <input id="textField" name="name" value="Duke" type="text"/>
    +                        <input onclick="join();" value="Join" type="button"/>
    +                        <input onclick="send_message();" value="Send" type="button"/><p/>
    +                        <input onclick="disconnect();" value="Disconnect" type="button"/>
    +                    </td>
    +                </tr>
    +            </table>
    +        </form>
    +        <div id="output"></div>
    +            <script language="javascript" type="text/javascript"
    +                src="${facesContext.externalContext.requestContextPath}/chat/websocket.js"></script>
    +    </ui:define>
    +</ui:composition>
    @@ -1486,7 +1580,7 @@

    4. Chat Room (Java API for WebSocket)

  • -

    Right-click on ‘chat’ in ‘Web Pages’, select ‘New’, ‘Web’ +

    Right-click on ‘chat’ in ‘Web Pages’, select ‘New’, ‘Other’, ‘Web’ categories, ‘JavaScript File’ file type. Click on ‘Next’.

    Give the name as ‘websocket’ and click on ‘Finish’.

    @@ -1496,62 +1590,62 @@

    4. Chat Room (Java API for WebSocket)

    Edit the contents of ‘websocket.js’ such that it looks like:

    -
    var wsUri = 'ws://' + document.location.host
    -            + document.location.pathname.substr(0,
    -              document.location.pathname.indexOf("/faces")) +
    -              '/websocket';
    +
    var wsUri = 'ws://' + document.location.host
    +            + document.location.pathname.substr(0,
    +              document.location.pathname.indexOf("/faces")) +
    +              '/websocket';
     console.log(wsUri);
     
    -var websocket = new WebSocket(wsUri);
    -var textField = document.getElementById("textField");
    -var users = document.getElementById("users");
    -var chatlog = document.getElementById("chatlog");
    -var username;
    +var websocket = new WebSocket(wsUri);
    +var textField = document.getElementById("textField");
    +var users = document.getElementById("users");
    +var chatlog = document.getElementById("chatlog");
    +var username;
     
    -websocket.onopen = function(evt) { onOpen(evt); };
    -websocket.onmessage = function(evt) { onMessage(evt); };
    -websocket.onerror = function(evt) { onError(evt); };
    -websocket.onclose = function(evt) { onClose(evt); };
    +websocket.onopen = function(evt) { onOpen(evt); };
    +websocket.onmessage = function(evt) { onMessage(evt); };
    +websocket.onerror = function(evt) { onError(evt); };
    +websocket.onclose = function(evt) { onClose(evt); };
     
    -var output = document.getElementById("output");
    +var output = document.getElementById("output");
     
    -function join() {
    +function join() {
         username = textField.value;
    -    websocket.send(username + " joined");
    +    websocket.send(username + " joined");
     }
     
    -function send_message() {
    -    websocket.send(username + ": " + textField.value);
    +function send_message() {
    +    websocket.send(username + ": " + textField.value);
     }
     
    -function onOpen() {
    -    writeToScreen("CONNECTED");
    +function onOpen() {
    +    writeToScreen("CONNECTED");
     }
     
    -function onClose() {
    -    writeToScreen("DISCONNECTED");
    +function onClose() {
    +    writeToScreen("DISCONNECTED");
     }
     
    -function onMessage(evt) {
    -    writeToScreen("RECEIVED: " + evt.data);
    -    if (evt.data.indexOf("joined") !== -1) {
    -        users.innerHTML += evt.data.substring(0, evt.data.indexOf(" joined")) + "\n";
    -    } else {
    -        chatlog.innerHTML += evt.data + "\n";
    +function onMessage(evt) {
    +    writeToScreen("RECEIVED: " + evt.data);
    +    if (evt.data.indexOf("joined") !== -1) {
    +        users.innerHTML += evt.data.substring(0, evt.data.indexOf(" joined")) + "\n";
    +    } else {
    +        chatlog.innerHTML += evt.data + "\n";
         }
     }
     
    -function onError(evt) {
    -    writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
    +function onError(evt) {
    +    writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
     }
     
    -function disconnect() {
    +function disconnect() {
         websocket.close();
     }
     
    -function writeToScreen(message) {
    -    var pre = document.createElement("p");
    -    pre.style.wordWrap = "break-word";
    +function writeToScreen(message) {
    +    var pre = document.createElement("p");
    +    pre.style.wordWrap = "break-word";
         pre.innerHTML = message;
         output.appendChild(pre);
     }
    @@ -1564,10 +1658,10 @@

    4. Chat Room (Java API for WebSocket)

    registered for lifecycle events using onXXX messages. The listeners registered in this script are explained in the table.

    -
  • +
    --++ @@ -1594,6 +1688,7 @@

    4. Chat Room (Java API for WebSocket)

    +

    Any relevant data is passed along as parameter to the function. Each method prints the status on the browser using writeToScreen utility @@ -1609,7 +1704,7 @@

    4. Chat Room (Java API for WebSocket)

    Edit ‘WEB-INF/template.xhtml’ and change:

    -
    <h:outputLink value="item2.xhtml">Item 2</h:outputLink>
    +
    <h:outputLink value="item2.xhtml">Item 2</h:outputLink>
    @@ -1617,10 +1712,10 @@

    4. Chat Room (Java API for WebSocket)

    -
    <h:outputLink
    -    value="${facesContext.externalContext.requestContextPath}/faces/chat/chatroom.xhtml">
    +
    <h:outputLink
    +    value="${facesContext.externalContext.requestContextPath}/faces/chat/chatroom.xhtml">
         Chat Room
    -</h:outputLink>
    +</h:outputLink>
    @@ -1777,7 +1872,7 @@

    5. Ticket Sales (Batch Applications for the Java Platform)

    ‘AbstractItemReader’ by changing the class definition and add:

    -
    extends AbstractItemReader
    +
    extends AbstractItemReader
    @@ -1800,14 +1895,14 @@

    5. Ticket Sales (Batch Applications for the Java Platform)

    Override open() method to initialize the reader by adding the following code:

    -
    private BufferedReader reader;
    +
    private BufferedReader reader;
     
    -public void open(Serializable checkpoint) throws Exception {
    -    reader = new BufferedReader(
    -        new InputStreamReader(
    -        Thread.currentThread()
    +public void open(Serializable checkpoint) throws Exception {
    +    reader = new BufferedReader(
    +        new InputStreamReader(
    +        Thread.currentThread()
                 .getContextClassLoader()
    -            .getResourceAsStream("META-INF/sales.csv")));
    +            .getResourceAsStream("META-INF/sales.csv")));
     }
    @@ -1820,7 +1915,7 @@

    5. Ticket Sales (Batch Applications for the Java Platform)

    -
    1,500.00
    +
    1,500.00
     2,660.00
     3,80.00
     4,470.00
    @@ -1839,15 +1934,15 @@ 

    5. Ticket Sales (Batch Applications for the Java Platform)

    Override the following method from the abstract class:

    -
    @Override
    -public String readItem() {
    -    String string = null;
    -    try {
    +
    @Override
    +public String readItem() {
    +    String string = null;
    +    try {
             string = reader.readLine();
    -    } catch (IOException ex) {
    +    } catch (IOException ex) {
             ex.printStackTrace();
         }
    -    return string;
    +    return string;
     }
    @@ -1866,7 +1961,7 @@

    5. Ticket Sales (Batch Applications for the Java Platform)

    class definition and add:

    -
    implements ItemProcessor
    +
    implements ItemProcessor
    @@ -1888,14 +1983,14 @@

    5. Ticket Sales (Batch Applications for the Java Platform)

    Add implementation of the abstract method from the interface as:

    -
    @Override
    -public Sales processItem(Object s) {
    -    Sales sales = new Sales();
    -    StringTokenizer tokens = new StringTokenizer((String)s, ",");
    -    sales.setId(Integer.parseInt(tokens.nextToken()));
    -    sales.setAmount(Float.parseFloat(tokens.nextToken()));
    +
    @Override
    +public Sales processItem(Object s) {
    +    Sales sales = new Sales();
    +    StringTokenizer tokens = new StringTokenizer((String)s, ",");
    +    sales.setId(Integer.parseInt(tokens.nextToken()));
    +    sales.setAmount(Float.parseFloat(tokens.nextToken()));
     
    -    return sales;
    +    return sales;
     }
    @@ -1922,7 +2017,7 @@

    5. Ticket Sales (Batch Applications for the Java Platform)

    class definition and add:

    -
    extends AbstractItemWriter
    +
    extends AbstractItemWriter
    @@ -1943,7 +2038,7 @@

    5. Ticket Sales (Batch Applications for the Java Platform)

    Inject EntityManager as:

    -
    @PersistenceContext EntityManager em;
    +
    @PersistenceContext EntityManager em;
    @@ -1951,10 +2046,10 @@

    5. Ticket Sales (Batch Applications for the Java Platform)

    -
    @Override
    -@Transactional
    -public void writeItems(List list) {
    -    for (Sales s : (List<Sales>)list) {
    +
    @Override
    +@Transactional
    +public void writeItems(List list) {
    +    for (Sales s : (List<Sales>)list) {
             em.persist(s);
         }
     }
    @@ -2017,20 +2112,20 @@

    5. Ticket Sales (Batch Applications for the Java Platform)

    -
    <job id="endOfDaySales"
    -    xmlns="http://xmlns.jcp.org/xml/ns/javaee[http://xmlns.jcp.org/xml/ns/javaee]"
    -    version="1.0">
    -    <step id="populateSales">
    -        <chunk item-count="3" skip-limit="5">
    -            <reader ref="salesReader"/>
    -            <processor ref="salesProcessor"/>
    -            <writer ref="salesWriter"/>
    -            <skippable-exception-classes>
    -                <include class="java.lang.NumberFormatException"/>
    -            </skippable-exception-classes>
    -        </chunk>
    -    </step>
    -</job>
    +
    <job id="endOfDaySales"
    +    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    +    version="1.0">
    +    <step id="populateSales">
    +        <chunk item-count="3" skip-limit="5">
    +            <reader ref="salesReader"/>
    +            <processor ref="salesProcessor"/>
    +            <writer ref="salesWriter"/>
    +            <skippable-exception-classes>
    +                <include class="java.lang.NumberFormatException"/>
    +            </skippable-exception-classes>
    +        </chunk>
    +    </step>
    +</job>
    @@ -2066,12 +2161,12 @@

    5. Ticket Sales (Batch Applications for the Java Platform)

    -
    public void runJob() {
    -    try {
    +
    public void runJob() {
    +    try {
             JobOperator jo = BatchRuntime.getJobOperator();
    -        long jobId = jo.start("eod-sales", new Properties());
    -        System.out.println("Started job: with id: " + jobId);
    -    } catch (JobStartException ex) {
    +        long jobId = jo.start("eod-sales", new Properties());
    +        System.out.println("Started job: with id: " + jobId);
    +    } catch (JobStartException ex) {
             ex.printStackTrace();
         }
     }
    @@ -2102,7 +2197,7 @@

    5. Ticket Sales (Batch Applications for the Java Platform)

    Inject EntityManagerFactory in the class as:

    -
    @PersistenceUnit EntityManagerFactory emf;
    +
    @PersistenceUnit EntityManagerFactory emf;
    @@ -2110,10 +2205,10 @@

    5. Ticket Sales (Batch Applications for the Java Platform)

    -
    public List<Sales> getSalesData() {
    -    return emf.
    +
    public List<Sales> getSalesData() {
    +    return emf.
             createEntityManager().
    -        createNamedQuery("Sales.findAll", Sales.class).
    +        createNamedQuery("Sales.findAll", Sales.class).
             getResultList();
     }
    @@ -2147,32 +2242,34 @@

    5. Ticket Sales (Batch Applications for the Java Platform)

    -
    <ui:define name="content">
    -    <h1>Movie Sales</h1>
    -    <h:form>
    -        <h:dataTable value="#{salesBean.salesData}" var="s" border="1">
    -            <h:column>
    -                <f:facet name="header">
    -                    <h:outputText value="Show ID" />
    -                </f:facet>
    -                #{s.id}
    -            </h:column>
    -            <h:column>
    -                <f:facet name="header">
    -                    <h:outputText value="Sales" />
    -                </f:facet>
    -                #{s.amount}
    -            </h:column>
    -        </h:dataTable>
    -        <h:commandButton
    -            value="Run Job"
    -            action="sales"
    -            actionListener="#{salesBean.runJob()}"/>
    -        <h:commandButton
    -            value="Refresh"
    -            action="sales" />
    -    </h:form>
    -</ui:define>
    +
    <ui:composition template="../WEB-INF/template.xhtml">
    +    <ui:define name="content">
    +        <h1>Movie Sales</h1>
    +        <h:form>
    +            <h:dataTable value="#{salesBean.salesData}" var="s" border="1">
    +                <h:column>
    +                    <f:facet name="header">
    +                        <h:outputText value="Show ID" />
    +                    </f:facet>
    +                    #{s.id}
    +                </h:column>
    +                <h:column>
    +                    <f:facet name="header">
    +                        <h:outputText value="Sales" />
    +                    </f:facet>
    +                    #{s.amount}
    +                </h:column>
    +            </h:dataTable>
    +            <h:commandButton
    +                value="Run Job"
    +                action="sales"
    +                actionListener="#{salesBean.runJob()}"/>
    +            <h:commandButton
    +                value="Refresh"
    +                action="sales" />
    +        </h:form>
    +    </ui:define>
    +</ui:composition>
    @@ -2190,10 +2287,10 @@

    5. Ticket Sales (Batch Applications for the Java Platform)

    Add the following code in template.xhtml along with other <outputLink>s:

    -
    <p/><h:outputLink
    -    value="${facesContext.externalContext.requestContextPath}/faces/batch/sales.xhtml">
    +
    <p/><h:outputLink
    +    value="${facesContext.externalContext.requestContextPath}/faces/batch/sales.xhtml">
         Sales
    -    </h:outputLink>
    + </h:outputLink>
  • @@ -2326,27 +2423,27 @@

    6. View and Delete Movie (Java API for RESTful Web Services)

    Add the following code to the class:

    -
    Client client;
    +
    Client client;
     WebTarget target;
     
    -@Inject HttpServletRequest httpServletRequest;
    +@Inject HttpServletRequest httpServletRequest;
     
    -@PostConstruct
    -public void init() {
    +@PostConstruct
    +public void init() {
         client = ClientBuilder.newClient();
         target = client
    -                .target("http://" +
    +                .target("http://" +
                     httpServletRequest.getLocalName() +
    -                ":" +
    +                ":" +
                     httpServletRequest.getLocalPort() +
    -                "/" +
    +                "/" +
                     httpServletRequest.getContextPath() +
    -                "/webresources/movie/");
    +                "/webresources/movie/");
     
     }
     
    -@PreDestroy
    -public void destroy() {
    +@PreDestroy
    +public void destroy() {
         client.close();
     }
    @@ -2372,10 +2469,10 @@

    6. View and Delete Movie (Java API for RESTful Web Services)

    Add the following method to the class:

    -
    public Movie[] getMovies() {
    -    return target
    +
    public Movie[] getMovies() {
    +    return target
             .request()
    -        .get(Movie[].class);
    +        .get(Movie[].class);
     }
    @@ -2406,16 +2503,18 @@

    6. View and Delete Movie (Java API for RESTful Web Services)

    -
    <ui:define name="content">
    -    <h:form prependId="false">
    -        <h:selectOneRadio value="#{movieBackingBean.movieId}" layout="pageDirection">
    -            <c:forEach items="#{movieClientBean.movies}" var="m">
    -                <f:selectItem itemValue="#{m.id}" itemLabel="#{m.name}"/>
    -            </c:forEach>
    -        </h:selectOneRadio>
    -        <h:commandButton value="Details" action="movie" />
    -    </h:form>
    -</ui:define>
    +
    <ui:composition template="../WEB-INF/template.xhtml">
    +    <ui:define name="content">
    +        <h:form prependId="false">
    +            <h:selectOneRadio value="#{movieBackingBean.movieId}" layout="pageDirection">
    +                <c:forEach items="#{movieClientBean.movies}" var="m">
    +                    <f:selectItem itemValue="#{m.id}" itemLabel="#{m.name}"/>
    +                </c:forEach>
    +            </h:selectOneRadio>
    +            <h:commandButton value="Details" action="movie" />
    +        </h:form>
    +    </ui:define>
    +</ui:composition>
    @@ -2449,12 +2548,12 @@

    6. View and Delete Movie (Java API for RESTful Web Services)

    -
    int movieId;
    +
    int movieId;

    Add getters/setters by right-clicking on the editor pane and selecting -‘Insert Code’ (Ctrl + I shortcut on Mac). Select the field and click on +‘Insert Code’ (Ctrl+I shortcut on OSX). Select the field and click on ‘Generate’.

    @@ -2481,14 +2580,14 @@

    6. View and Delete Movie (Java API for RESTful Web Services)

    In ‘template.xhtml’, add the following code along with other <outputLink>s:

    -
    <p/><h:outputLink
    -        value="${facesContext.externalContext.requestContextPath}/faces/client/movies.xhtml">
    +
    <p/><h:outputLink
    +        value="${facesContext.externalContext.requestContextPath}/faces/client/movies.xhtml">
             Movies
    -    </h:outputLink>
    + </h:outputLink>
    -

    Running the project (Fn + F6 shortcut on Mac) and clicking on ‘Movies’ +

    Running the project (Fn+F6 shortcut on OSX) and clicking on ‘Movies’ in the left navigation bar shows the output as shown.

    @@ -2507,7 +2606,7 @@

    6. View and Delete Movie (Java API for RESTful Web Services)

    of selected movie from the page. Add the following code:

    -
    @Inject
    +
    @Inject
     MovieBackingBean bean;
    @@ -2516,13 +2615,13 @@

    6. View and Delete Movie (Java API for RESTful Web Services)

    In MovieClientBean, add the following method:

    -
    public Movie getMovie() {
    +
    public Movie getMovie() {
         Movie m = target
    -        .path("{movie}")
    -        .resolveTemplate("movie", bean.getMovieId())
    +        .path("{movie}")
    +        .resolveTemplate("movie", bean.getMovieId())
             .request()
             .get(Movie.class);
    -    return m;
    +    return m;
     }
    @@ -2548,26 +2647,26 @@

    6. View and Delete Movie (Java API for RESTful Web Services)

    -
    <ui:define name="content">
    -    <h1>Movie Details</h1>
    -    <h:form>
    -        <table cellpadding="5" cellspacing="5">
    -            <tr>
    -                <th align="left">Movie Id:</th>
    -                <td>#{movieClientBean.movie.id}</td>
    -            </tr>
    -            <tr>
    -                <th align="left">Movie Name:</th>
    -                <td>#{movieClientBean.movie.name}</td>
    -            </tr>
    -            <tr>
    -                <th align="left">Movie Actors:</th>
    -                <td>#{movieClientBean.movie.actors}</td>
    -            </tr>
    -        </table>
    -        <h:commandButton value="Back" action="movies" />
    -    </h:form>
    -</ui:define>
    +
    <ui:define name="content">
    +    <h1>Movie Details</h1>
    +    <h:form>
    +        <table cellpadding="5" cellspacing="5">
    +            <tr>
    +                <th align="left">Movie Id:</th>
    +                <td>#{movieClientBean.movie.id}</td>
    +            </tr>
    +            <tr>
    +                <th align="left">Movie Name:</th>
    +                <td>#{movieClientBean.movie.name}</td>
    +            </tr>
    +            <tr>
    +                <th align="left">Movie Actors:</th>
    +                <td>#{movieClientBean.movie.actors}</td>
    +            </tr>
    +        </table>
    +        <h:commandButton value="Back" action="movies" />
    +    </h:form>
    +</ui:define>
    @@ -2598,10 +2697,10 @@

    6. View and Delete Movie (Java API for RESTful Web Services)

    following code with other <commandButton>.

    -
    <h:commandButton
    -    value="Delete"
    -    action="movies"
    -    actionListener="#{movieClientBean.deleteMovie()}"/>
    +
    <h:commandButton
    +    value="Delete"
    +    action="movies"
    +    actionListener="#{movieClientBean.deleteMovie()}"/>
    @@ -2613,10 +2712,10 @@

    6. View and Delete Movie (Java API for RESTful Web Services)

    Add the following code to ‘MovieClientBean’:

    -
    public void deleteMovie() {
    +
    public void deleteMovie() {
         target
    -        .path("{movieId}")
    -        .resolveTemplate("movieId", bean.getMovieId())
    +        .path("{movieId}")
    +        .resolveTemplate("movieId", bean.getMovieId())
             .request()
             .delete();
     }
    @@ -2709,8 +2808,8 @@

    7. Add Movie (Java API for JSON Processing)

    following class-level annotations:

    -
    @Provider
    -@Consumes(MediaType.APPLICATION_JSON)
    +
    @Provider
    +@Consumes(MediaType.APPLICATION_JSON)
    @@ -2745,7 +2844,7 @@

    7. Add Movie (Java API for JSON Processing)

    Change implementation of the isReadable method as:

    -
    return Movie.class.isAssignableFrom(type);
    +
    return Movie.class.isAssignableFrom(type);
    @@ -2757,42 +2856,42 @@

    7. Add Movie (Java API for JSON Processing)

    Replace the readFrom method with:

    -
    @Override
    -public Movie readFrom(
    -    Class<Movie> type,
    -    Type type1,
    -    Annotation[] antns,
    +
    @Override
    +public Movie readFrom(
    +    Class<Movie> type,
    +    Type type1,
    +    Annotation[] antns,
         MediaType mt,
    -    MultivaluedMap<String, String> mm,
    -    InputStream in)
    -      throws IOException, WebApplicationException {
    +    MultivaluedMap<String, String> mm,
    +    InputStream in)
    +      throws IOException, WebApplicationException {
     
    -    Movie movie = new Movie();
    +    Movie movie = new Movie();
         JsonParser parser = Json.createParser(in);
    -    while (parser.hasNext()) {
    -        switch (parser.next()) {
    -            case KEY_NAME:
    -                String key = parser.getString();
    +    while (parser.hasNext()) {
    +        switch (parser.next()) {
    +            case KEY_NAME:
    +                String key = parser.getString();
                     parser.next();
    -                switch (key) {
    -                    case "id":
    +                switch (key) {
    +                    case "id":
                             movie.setId(parser.getInt());
    -                        break;
    -                    case "name":
    +                        break;
    +                    case "name":
                             movie.setName(parser.getString());
    -                        break;
    -                    case "actors":
    +                        break;
    +                    case "actors":
                             movie.setActors(parser.getString());
    -                        break;
    -                    default:
    -                        break;
    +                        break;
    +                    default:
    +                        break;
                     }
    -                break;
    -            default:
    -                break;
    +                break;
    +            default:
    +                break;
             }
         }
    -    return movie;
    +    return movie;
     }
    @@ -2811,8 +2910,8 @@

    7. Add Movie (Java API for JSON Processing)

    following class-level annotations:

    -
    @Provider
    -@Produces(MediaType.APPLICATION_JSON)
    +
    @Provider
    +@Produces(MediaType.APPLICATION_JSON)
    @@ -2834,7 +2933,7 @@

    7. Add Movie (Java API for JSON Processing)

    Make this class implement MessageBodyWriter interface by adding the following code:

    -
    implements MessageBodyWriter<Movie>
    +
    implements MessageBodyWriter<Movie>
    @@ -2858,7 +2957,7 @@

    7. Add Movie (Java API for JSON Processing)

    Change implementation of the isWritable method to:

    -
    return Movie.class.isAssignableFrom(type);
    +
    return Movie.class.isAssignableFrom(type);
    @@ -2870,7 +2969,7 @@

    7. Add Movie (Java API for JSON Processing)

    Add implementation of the getSize method as:

    -
    return -1;
    +
    return -1;
    @@ -2884,11 +2983,11 @@

    7. Add Movie (Java API for JSON Processing)

    Change implementation of the writeTo method to:

    -
    JsonGenerator gen = Json.createGenerator(entityStream);
    +
    JsonGenerator gen = Json.createGenerator(entityStream);
     gen.writeStartObject()
    -    .write("id", t.getId())
    -    .write("name", t.getName())
    -    .write("actors", t.getActors())
    +    .write("id", t.getId())
    +    .write("name", t.getName())
    +    .write("actors", t.getActors())
         .writeEnd();
         gen.flush();
    @@ -2917,29 +3016,31 @@

    7. Add Movie (Java API for JSON Processing)

    -
    <ui:define name="content">
    -<h1>Add a New Movie</h1>
    -<h:form>
    -    <table cellpadding="5" cellspacing="5">
    -        <tr>
    -            <th align="left">Movie Id:</th>
    -            <td><h:inputText value="#{movieBackingBean.movieId}"/></td>
    -        </tr>
    -        <tr>
    -            <th align="left">Movie Name:</th>
    -            <td><h:inputText value="#{movieBackingBean.movieName}"/> </td>
    -        </tr>
    -        <tr>
    -            <th align="left">Movie Actors:</th>
    -            <td><h:inputText value="#{movieBackingBean.actors}"/></td>
    -        </tr>
    -    </table>
    -    <h:commandButton
    -        value="Add"
    -        action="movies"
    -        actionListener="#{movieClientBean.addMovie()}"/>
    -</h:form>
    -</ui:define>
    +
    <ui:composition template="../WEB-INF/template.xhtml">
    +    <ui:define name="content">
    +    <h1>Add a New Movie</h1>
    +    <h:form>
    +        <table cellpadding="5" cellspacing="5">
    +            <tr>
    +                <th align="left">Movie Id:</th>
    +                <td><h:inputText value="#{movieBackingBean.movieId}"/></td>
    +            </tr>
    +            <tr>
    +                <th align="left">Movie Name:</th>
    +                <td><h:inputText value="#{movieBackingBean.movieName}"/> </td>
    +            </tr>
    +            <tr>
    +                <th align="left">Movie Actors:</th>
    +                <td><h:inputText value="#{movieBackingBean.actors}"/></td>
    +            </tr>
    +        </table>
    +        <h:commandButton
    +            value="Add"
    +            action="movies"
    +            actionListener="#{movieClientBean.addMovie()}"/>
    +    </h:form>
    +    </ui:define>
    +</ui:composition>
    @@ -2963,8 +3064,8 @@

    7. Add Movie (Java API for JSON Processing)

    Add movieName and actors field to MovieBackingBean as:

    -
    String movieName;
    -String actors;
    +
    String movieName;
    +String actors;
    @@ -2976,7 +3077,7 @@

    7. Add Movie (Java API for JSON Processing)

    Add the following code to ‘movies.xhtml’

    -
    <h:commandButton value="New Movie" action="addmovie" />
    +
    <h:commandButton value="New Movie" action="addmovie" />
    @@ -2987,15 +3088,15 @@

    7. Add Movie (Java API for JSON Processing)

    Add the following method in MovieClientBean:

    -
    public void addMovie() {
    -    Movie m = new Movie();
    +
    public void addMovie() {
    +    Movie m = new Movie();
         m.setId(bean.getMovieId());
         m.setName(bean.getMovieName());
         m.setActors(bean.getActors());
         target
             .register(MovieWriter.class)
             .request()
    -        .post(Entity.entity(m, MediaType.APPLICATION_JSON));
    +        .post(Entity.entity(m, MediaType.APPLICATION_JSON));
     }
    @@ -3108,8 +3209,8 @@

    8. Movie Points (Java Message Service)

    -
    @Named
    -@RequestScoped
    +
    @Named
    +@RequestScoped
    @@ -3141,10 +3242,10 @@

    8. Movie Points (Java Message Service)

    -
    @NotNull
    -@Pattern(regexp = "^\\d{2},\\d{2}",
    -         message = "Message format must be 2 digits, comma, 2 digits, e.g.12,12")
    -private String message;
    +
    @NotNull
    +@Pattern(regexp = "^\\d{2},\\d{2}",
    +         message = "Message format must be 2 digits, comma, 2 digits, e.g.12,12")
    +private String message;
    @@ -3162,7 +3263,7 @@

    8. Movie Points (Java Message Service)

    Generate getter/setters for this field. Right-click in the editor pane, -select ‘Insert Code’ (Ctrl + I shortcut on Mac), select ‘Getter and +select ‘Insert Code’ (Ctrl+I shortcut on OSX), select ‘Getter and Setter’, select the field, and click on ‘Generate’.

    @@ -3170,14 +3271,14 @@

    8. Movie Points (Java Message Service)

    Add the following code to the class:

    -
    @Inject
    +
    @Inject
     JMSContext context;
     
    -@Resource(lookup = "java:global/jms/pointsQueue")
    -Queue pointsQueue;
    +@Resource(lookup = "java:global/jms/pointsQueue")
    +Queue pointsQueue;
     
    -public void sendMessage() {
    -    System.out.println("Sending message: " + message);
    +public void sendMessage() {
    +    System.out.println("Sending message: " + message);
         context.createProducer().send(pointsQueue, message);
     }
    @@ -3191,7 +3292,7 @@

    8. Movie Points (Java Message Service)

    -
    @Inject
    +
    @Inject
     JMSContext context;
    @@ -3250,10 +3351,10 @@

    8. Movie Points (Java Message Service)

    -
    @JMSDestinationDefinition(name = "java:global/jms/pointsQueue",
    -interfaceName = "javax.jms.Queue")
    -@Named
    -@RequestScoped
    +
    @JMSDestinationDefinition(name = "java:global/jms/pointsQueue",
    +interfaceName = "javax.jms.Queue")
    +@Named
    +@RequestScoped
    @@ -3272,17 +3373,17 @@

    8. Movie Points (Java Message Service)

    Add the following code to the class:

    -
    @Inject
    +
    @Inject
     JMSContext context;
     
    -@Resource(lookup="java:global/jms/pointsQueue")
    -Queue pointsQueue;
    +@Resource(lookup="java:global/jms/pointsQueue")
    +Queue pointsQueue;
     
    -public String receiveMessage() {
    -    try (JMSConsumer consumer = context.createConsumer(pointsQueue)) {
    -        String message = consumer.receiveBody(String.class);
    -        System.out.println("Received message: " + message);
    -        return message;
    +public String receiveMessage() {
    +    try (JMSConsumer consumer = context.createConsumer(pointsQueue)) {
    +        String message = consumer.receiveBody(String.class);
    +        System.out.println("Received message: " + message);
    +        return message;
         }
     }
    @@ -3299,19 +3400,19 @@

    8. Movie Points (Java Message Service)

    Add the following method to the class:

    -
    public int getQueueSize() {
    -    int count = 0;
    -    try {
    +
    public int getQueueSize() {
    +    int count = 0;
    +    try {
             QueueBrowser browser = context.createBrowser(pointsQueue);
    -        Enumeration elems = browser.getEnumeration();
    -        while (elems.hasMoreElements()) {
    +        Enumeration elems = browser.getEnumeration();
    +        while (elems.hasMoreElements()) {
                 elems.nextElement();
                 count++;
             }
    -    } catch (JMSException ex) {
    +    } catch (JMSException ex) {
             ex.printStackTrace();
         }
    -    return count;
    +    return count;
     }
    @@ -3343,24 +3444,26 @@

    8. Movie Points (Java Message Service)

    -
    <ui:define name="content">
    -    <h1>Points</h1>
    -    <h:form>
    -    Queue size:
    -        <h:outputText value="#{receivePointsBean.queueSize}"/><p/>
    -        <h:inputText value="#{sendPointsBean.message}"/>
    -        <h:commandButton
    -            value="Send Message"
    -            action="points"
    -            actionListener="#{sendPointsBean.sendMessage()}"/>
    -    </h:form>
    -    <h:form>
    -        <h:commandButton
    -            value="Receive Message"
    -            action="points"
    -            actionListener="#{receivePointsBean.receiveMessage()}"/>
    -    </h:form>
    -</ui:define>
    +
    <ui:composition template="../WEB-INF/template.xhtml">
    +    <ui:define name="content">
    +        <h1>Points</h1>
    +        <h:form>
    +        Queue size:
    +            <h:outputText value="#{receivePointsBean.queueSize}"/><p/>
    +            <h:inputText value="#{sendPointsBean.message}"/>
    +            <h:commandButton
    +                value="Send Message"
    +                action="points"
    +                actionListener="#{sendPointsBean.sendMessage()}"/>
    +        </h:form>
    +        <h:form>
    +            <h:commandButton
    +                value="Receive Message"
    +                action="points"
    +                actionListener="#{receivePointsBean.receiveMessage()}"/>
    +        </h:form>
    +    </ui:define>
    +</ui:composition>
    @@ -3386,10 +3489,10 @@

    8. Movie Points (Java Message Service)

    <outputLink>s:

    -
    <p/><h:outputLink
    -        value="${facesContext.externalContext.requestContextPath}/faces/points/points.xhtml">
    +
    <p/><h:outputLink
    +        value="${facesContext.externalContext.requestContextPath}/faces/points/points.xhtml">
             Points
    -    </h:outputLink>
    + </h:outputLink>
    @@ -3550,22 +3653,24 @@

    9. Show Booking (JavaServer Faces)

    -
    <ui:define name="content">
    -    <h2>Pick a movie</h2>
    -    <h:form prependId="false">
    -        <h:selectOneRadio
    -            value="#{booking.movieId}"
    -            layout="pageDirection"
    -            required="true">
    -            <f:selectItems
    -                value="#{movieFacadeREST.all}"
    -                var="m"
    -                itemValue="#{m.id}"
    -                itemLabel="#{m.name}"/>
    -        </h:selectOneRadio>
    -        <h:commandButton id="shows" value="Pick a time" action="showtimes" />
    -    </h:form>
    -</ui:define>
    +
    <ui:composition template="../WEB-INF/template.xhtml">
    +    <ui:define name="content">
    +        <h2>Pick a movie</h2>
    +        <h:form prependId="false">
    +            <h:selectOneRadio
    +                value="#{booking.movieId}"
    +                layout="pageDirection"
    +                required="true">
    +                <f:selectItems
    +                    value="#{movieFacadeREST.all}"
    +                    var="m"
    +                    itemValue="#{m.id}"
    +                    itemLabel="#{m.name}"/>
    +            </h:selectOneRadio>
    +            <h:commandButton id="shows" value="Pick a time" action="showtimes" />
    +        </h:form>
    +    </ui:define>
    +</ui:composition>
    @@ -3594,15 +3699,17 @@

    9. Show Booking (JavaServer Faces)

    Add @Named class-level annotation to make the class EL-injectable.

    -

    Add @FlowScoped("booking") to define the scope of bean as the flow. The bean -is automatically activated and passivated as the flow is entered or exited.

    +

    Add @FlowScoped("booking") to define the scope of bean as the flow. The bean is automatically activated and passivated as the flow is entered or exited.

    +
    +
    +

    Add implements Serializable to the class as beans with @FlowScoped annotation need to be passivation capable, and thus serializable.

    Add the following field:

    -
    int movieId;
    +
    int movieId;
    @@ -3614,7 +3721,7 @@

    9. Show Booking (JavaServer Faces)

    -
    @PersistenceContext
    +
    @PersistenceContext
     EntityManager em;
    @@ -3623,14 +3730,14 @@

    9. Show Booking (JavaServer Faces)

    -
    public String getMovieName() {
    -    try {
    -        return em.createNamedQuery("Movie.findById", Movie.class)
    -                  .setParameter("id", movieId)
    +
    public String getMovieName() {
    +    try {
    +        return em.createNamedQuery("Movie.findById", Movie.class)
    +                  .setParameter("id", movieId)
                       .getSingleResult()
                       .getName();
    -    } catch (NoResultException e) {
    -        return "";
    +    } catch (NoResultException e) {
    +        return "";
         }
     }
    @@ -3659,18 +3766,20 @@

    9. Show Booking (JavaServer Faces)

    -
    <ui:define name="content">
    -    <h2>Show Timings for <font color="red">#{booking.movieName}</font></h2>
    -    <h:form>
    -        <h:selectOneRadio value="#{booking.startTime}" layout="pageDirection" required="true">
    -            <c:forEach items="#{timeslotFacadeREST.all}" var="s">
    -                <f:selectItem itemValue="#{s.id},#{s.startTime}" itemLabel="#{s.startTime}"/>
    -            </c:forEach>
    -        </h:selectOneRadio>
    -        <h:commandButton value="Confirm" action="confirm" />
    -        <h:commandButton id="back" value="Back" action="booking" immediate="true"/>
    -    </h:form>
    -</ui:define>
    +
    <ui:composition template="../WEB-INF/template.xhtml">
    +    <ui:define name="content">
    +        <h2>Show Timings for <font color="red">#{booking.movieName}</font></h2>
    +        <h:form>
    +            <h:selectOneRadio value="#{booking.startTime}" layout="pageDirection" required="true">
    +                <c:forEach items="#{timeslotFacadeREST.all}" var="s">
    +                    <f:selectItem itemValue="#{s.id},#{s.startTime}" itemLabel="#{s.startTime}"/>
    +                </c:forEach>
    +            </h:selectOneRadio>
    +            <h:commandButton value="Confirm" action="confirm" />
    +            <h:commandButton id="back" value="Back" action="booking" immediate="true"/>
    +        </h:form>
    +    </ui:define>
    +</ui:composition>
    @@ -3698,8 +3807,8 @@

    9. Show Booking (JavaServer Faces)

    Add the following fields to the Booking class:

    -
    String startTime;
    -int startTimeId;
    +
    String startTime;
    +int startTimeId;
    @@ -3707,18 +3816,18 @@

    9. Show Booking (JavaServer Faces)

    -
    public String getStartTime() {
    -    return startTime;
    +
    public String getStartTime() {
    +    return startTime;
     }
     
    -public void setStartTime(String startTime) {
    -    StringTokenizer tokens = new StringTokenizer(startTime, ",");
    -    startTimeId = Integer.parseInt(tokens.nextToken());
    -    this.startTime = tokens.nextToken();
    +public void setStartTime(String startTime) {
    +    StringTokenizer tokens = new StringTokenizer(startTime, ",");
    +    startTimeId = Integer.parseInt(tokens.nextToken());
    +    this.startTime = tokens.nextToken();
     }
     
    -public int getStartTimeId() {
    -    return startTimeId;
    +public int getStartTimeId() {
    +    return startTimeId;
     }
    @@ -3728,28 +3837,28 @@

    9. Show Booking (JavaServer Faces)

    -
    public String getTheater() {
    -    // for a movie and show
    -    try {
    +
    public String getTheater() {
    +    // for a movie and show
    +    try {
     
    -        // Always return the first theater
    -        List<ShowTiming> list =
    -            em.createNamedQuery("ShowTiming.findByMovieAndTimingId",
    +        // Always return the first theater
    +        List<ShowTiming> list =
    +            em.createNamedQuery("ShowTiming.findByMovieAndTimingId",
                     ShowTiming.class)
    -                .setParameter("movieId", movieId)
    -                .setParameter("timingId", startTimeId)
    +                .setParameter("movieId", movieId)
    +                .setParameter("timingId", startTimeId)
                     .getResultList();
     
    -        if (list.isEmpty())
    -            return "none";
    +        if (list.isEmpty())
    +            return "none";
     
    -        return list
    -                .get(0)
    +        return list
    +                .get(0)
                     .getTheaterId()
                     .getId()
                     .toString();
    -    } catch (NoResultException e) {
    -        return "none";
    +    } catch (NoResultException e) {
    +        return "none";
         }
     }
    @@ -3778,28 +3887,30 @@

    9. Show Booking (JavaServer Faces)

    -
    <ui:define name="content">
    -    <c:choose>
    -        <c:when test="#{booking.theater == 'none'}">
    -            <h2>No theater found, choose a different time</h2>
    -            <h:form>
    -                Movie name: #{booking.movieName}<p/>
    -                Starts at: #{booking.startTime}<p/>
    -                <h:commandButton id="back" value="Back" action="showtimes"/>
    -            </h:form>
    -        </c:when>
    -        <c:otherwise>
    -            <h2>Confirm ?</h2>
    -            <h:form>
    -                Movie name: #{booking.movieName}<p/>
    -                Starts at: #{booking.startTime}<p/>
    -                Theater: #{booking.theater}<p/>
    -                <h:commandButton id="next" value="Book" action="print"/>
    -                <h:commandButton id="back" value="Back" action="showtimes"/>
    -            </h:form>
    -        </c:otherwise>
    -    </c:choose>
    -</ui:define>
    +
    <ui:composition template="../WEB-INF/template.xhtml">
    +    <ui:define name="content">
    +        <c:choose>
    +            <c:when test="#{booking.theater == 'none'}">
    +                <h2>No theater found, choose a different time</h2>
    +                <h:form>
    +                    Movie name: #{booking.movieName}<p/>
    +                    Starts at: #{booking.startTime}<p/>
    +                    <h:commandButton id="back" value="Back" action="showtimes"/>
    +                </h:form>
    +            </c:when>
    +            <c:otherwise>
    +                <h2>Confirm ?</h2>
    +                <h:form>
    +                    Movie name: #{booking.movieName}<p/>
    +                    Starts at: #{booking.startTime}<p/>
    +                    Theater: #{booking.theater}<p/>
    +                    <h:commandButton id="next" value="Book" action="print"/>
    +                    <h:commandButton id="back" value="Back" action="showtimes"/>
    +                </h:form>
    +            </c:otherwise>
    +        </c:choose>
    +    </ui:define>
    +</ui:composition>
    @@ -3830,15 +3941,17 @@

    9. Show Booking (JavaServer Faces)

    -
    <ui:define name="content">
    -    <h2>Reservation Confirmed</h2>
    -    <h:form>
    -        Movie name: #{booking.movieName}<p/>
    -        Starts at: #{booking.startTime}<p/>
    -        Theater: #{booking.theater}<p/>
    -        <h:commandButton id="home" value="home" action="goHome" /><p/>
    -    </h:form>
    -</ui:define>
    +
    <ui:composition template="../WEB-INF/template.xhtml">
    +    <ui:define name="content">
    +        <h2>Reservation Confirmed</h2>
    +        <h:form>
    +            Movie name: #{booking.movieName}<p/>
    +            Starts at: #{booking.startTime}<p/>
    +            Theater: #{booking.theater}<p/>
    +            <h:commandButton id="home" value="home" action="goHome" /><p/>
    +        </h:form>
    +    </ui:define>
    +</ui:composition>
    @@ -3861,7 +3974,7 @@

    9. Show Booking (JavaServer Faces)

    or programmatically by having a class with a method with the following annotations:

    -
    @Produces @FlowDefinition
    +
    @Produces @FlowDefinition
    @@ -3877,18 +3990,18 @@

    9. Show Booking (JavaServer Faces)

    -
    <faces-config
    -    version="2.2"
    -    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-facesconfig_2_2.xsd">
    -    <flow-definition id="booking">
    -        <flow-return id="goHome">
    -        <from-outcome>/index</from-outcome>
    -        </flow-return>
    -    </flow-definition>
    -</faces-config>
    +
    <faces-config
    +    version="2.2"
    +    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-facesconfig_2_2.xsd">
    +    <flow-definition id="booking">
    +        <flow-return id="goHome">
    +        <from-outcome>/index</from-outcome>
    +        </flow-return>
    +    </flow-definition>
    +</faces-config>
    @@ -3906,7 +4019,7 @@

    9. Show Booking (JavaServer Faces)

    changing:

    -
    <h:commandLink action="item1">Item 1</h:commandLink>
    +
    <h:commandLink action="item1">Item 1</h:commandLink>
    @@ -3914,7 +4027,7 @@

    9. Show Booking (JavaServer Faces)

    -
    <h:commandLink action="booking">Book a movie</h:commandLink>
    +
    <h:commandLink action="booking">Book a movie</h:commandLink>
    @@ -4222,7 +4335,7 @@

    12. Acknowledgements

    13. Completed Solutions

    -

    The completed solution can be downloaded from javaee7-hol.

    +

    The completed solution for this lab can be downloaded from javaee7-hol.

    @@ -4263,10 +4376,13 @@

    15. Revision History

    1. -

      Added IntelliJ IDEA specific instructions. (Jan 22, 2014)

      +

      Cleaned up NetBeans instructions and some other typos from DevoxxUK (Jun 25, 2014)

    2. -

      Added macros to generate WildFly and GlassFish-server specific instructions. Also enabled IntelliJ and Eclipse specific macros. (Jan 10, 2014)

      +

      Added IntelliJ IDEA specific instructions (Jan 22, 2014)

      +
    3. +
    4. +

      Added macros to generate WildFly and GlassFish-server specific instructions. Also enabled IntelliJ and Eclipse specific macros (Jan 10, 2014)

    5. Moving the source document from Pages to AsciiDoc (Dec 3, 2013)

      @@ -4276,34 +4392,12 @@

      15. Revision History

    -

    Appendix A: Appendix

    +

    16. Appendix A: Appendix

    -

    A.1. Configure WildFly 8 in NetBeans

    -
    -

    A.1.1. Configure Update Center

    -
    -
      -
    1. -

      If you are using NetBeans development build then skip this section and go to Install WildFly plugin. Otherwise in NetBeans, click on ‘Tools’, ‘Plugins’, ‘Settings’, and click on ‘Add’.

      -
    2. -
    3. -

      Specify the name as “Dev Update Center” and the URL as “http://deadlock.netbeans.org/job/nbms-and-javadoc/lastStableBuild/artifact/nbbuild/nbms/updates.xml.gz”.

      -
      -
      -16 netbeans add dev update center -
      -
      Figure 53. NetBeans Update Center
      -
      -
      -

      and click on ‘OK’.

      -
      -
    4. -
    -
    -
    +

    16.1. Configure WildFly 8 in NetBeans

    -

    A.1.2. Install WildFly plugin

    +

    16.1.1. Install WildFly plugin

    1. @@ -4312,20 +4406,20 @@

      A.1.2. Install WildFly plugin

      16 netbeans available plugins wildfly
      -
      Figure 54. Available Plugins in NetBeans
      +
      Figure 53. Available Plugins in NetBeans

    The exact plugin version and the date may be different.

  • -

    Click on ‘Install’ button, ‘Next >’, accept the license agreement by clicking on the checkbox, and click on ‘Install’ button to install the plugin. Click on ‘Finish’ to restart the IDE and complete installation.

    +

    Click the Install button, then Next >, accept the license agreement by clicking on the checkbox, then click the Install button to install the plugin. Click the Finish button to restart the IDE and complete installation.

  • -

    A.1.3. Configure WildFly 8

    +

    16.1.2. Configure WildFly 8

    1. @@ -4337,38 +4431,38 @@

      A.1.3. Configure WildFly 8

      netbeans addserver
      -
      Figure 55. Add Server in NetBeans
      +
      Figure 54. Add Server in NetBeans
  • Select ‘WildFly Application Server’ in the Add Server Instance wizard, set the -name to ‘WildFly 8’ and click ‘Next >’.

    +name to ‘WildFly 8’ and click Next >.

    16 netbeans add instance wildfly
    -
    Figure 56. Add WildFly instance to NetBeans
    +
    Figure 55. Add WildFly instance to NetBeans
  • -

    Click on ‘Browse’ for ‘Server Location’ and select the directory that got created -when WildFly archive was unzipped. Click on ‘Browse’ for ‘Server Configuration’ and +

    Click on Browse… for ‘Server Location’ and select the directory that got created +when WildFly archive was unzipped. Click on Browse… for ‘Server Configuration’ and select the ‘standalone/configuration/standalone-full.xml’ file in the unzipped WildFly archive.

    16 netbeans wildfly full platform
    -
    Figure 57. Configure WildFly full instance in NetBeans
    +
    Figure 56. Configure WildFly full instance in NetBeans
    -

    Click on ‘Next’ and then ‘Finish’. The ‘Services’ should show the WildFly instance.

    +

    Click on Next and then Finish. The ‘Services’ should show the WildFly instance.

    16 netbeans wildfly server
    -
    Figure 58. WildFly instance in NetBeans Services tab
    +
    Figure 57. WildFly instance in NetBeans Services tab
  • @@ -4376,7 +4470,7 @@

    A.1.3. Configure WildFly 8

    -

    A.2. Prepare IntelliJ IDEA for working with WildFly 8

    +

    16.2. Prepare IntelliJ IDEA for working with WildFly 8

    To be able to perform the exercises discussed in this tutorial, you need the Ultimate Edition of IntelliJ IDEA. Keep that in mind when downloading IntelliJ IDEA from http://www.jetbrains.com/idea/download/.

    @@ -4403,14 +4497,14 @@

    A.2. Prepare IntelliJ IDEA for working with WildF

    -

    A.2.1. Specify the JDK

    +

    16.2.1. Specify the JDK

    First of all, you should specify the JDK that you are going to use. In IntelliJ IDEA, this is done in the Project Structure dialog:

    1. -

      Start IntelliJ IDEA. If, as a result, a project opens, close the project (File | Close Project).

      +

      Start IntelliJ IDEA. If, as a result, a project opens, close the project (File ▸ Close Project).

    2. On the Welcome screen, under Quick Start, click Configure.

      @@ -4418,37 +4512,37 @@

      A.2.1. Specify the JDK

      i13 welcome configure
      -
      Figure 59. Welcome to IntelliJ IDEA
      +
      Figure 58. Welcome to IntelliJ IDEA
  • Under Configure, click Project Defaults, and then, under Project Defaults, click Project Structure.

  • -

    In the left-hand pane of the Project Structure dialog, under Platform Settings, select SDKs. Click image::images/i13-plus-icon.png[title="Plus icon in IntelliJ IDEA"] and select JDK.

    +

    In the left-hand pane of the Project Structure dialog, under Platform Settings, select SDKs. Click i13-plus-icon and select JDK.

    i13 plus jdk
    -
    Figure 60. Add JDK in IntelliJ IDEA
    +
    Figure 59. Add JDK in IntelliJ IDEA
  • -

    In the Select Home Directory for JDK dialog, select the folder in which the JDK that you are going to use is installed, and click OK.

    +

    In the Select Home Directory for JDK dialog, select the folder in which the JDK that you are going to use is installed, and click OK.

    i13 jdk home
    -
    Figure 61. JDK home in IntelliJ IDEA
    +
    Figure 60. JDK home in IntelliJ IDEA
  • -

    In the Project Structure dialog, click Apply.

    +

    In the Project Structure dialog, click Apply.

    i13 jdk defined
    -
    Figure 62. JDK defined in IntelliJ IDEA
    +
    Figure 61. JDK defined in IntelliJ IDEA

    Now, let’s make the JDK that we have specified the default SDK.

    @@ -4460,53 +4554,53 @@

    A.2.1. Specify the JDK

    i13 project sdk
    -
    Figure 63. Project SDK in IntelliJ IDEA
    +
    Figure 62. Project SDK in IntelliJ IDEA
  • -

    Click OK.

    +

    Click OK.

  • -

    A.2.2. Define WildFly

    +

    16.2.2. Define WildFly

    -

    Defining an application server in IntelliJ IDEA, normally, is just telling the IDE where the server is installed. The servers are defined in the Settings dialog. (On Mac OS, this dialog is called Preferences.)

    +

    Defining an application server in IntelliJ IDEA, normally, is just telling the IDE where the server is installed. The servers are defined in the Settings dialog. (On OSX, this dialog is called Preferences.)

    1. -

      On the Welcome screen, to the left of Project Defaults, click Back image::images/i13-back-icon.png[title="Back icon in IntelliJ IDEA"].

      +

      On the Welcome screen, to the left of Project Defaults, click Back i13-back-icon.

    2. Under Configure, click Settings.

    3. -

      In the left-hand pane of the Settings (Preferences) dialog, under IDE Settings, select Application Servers. On the Application Servers page, click image::images/i13-plus-icon.png[title="Plus icon in IntelliJ IDEA"] and select JBoss Server. (WildFly is a server from the "JBoss family".)

      +

      In the left-hand pane of the Settings (Preferences) dialog, under IDE Settings, select Application Servers. On the Application Servers page, click i13-plus-icon and select JBoss Server. (WildFly is a server from the "JBoss family".)

      i13 plus jboss
      -
      Figure 64. Add WildFly in IntelliJ IDEA
      +
      Figure 63. Add WildFly in IntelliJ IDEA
    4. -

      In the JBoss Server dialog, click image::images/i13-ellipsis-button.png[title="Ellipsis button in IntelliJ IDEA"] to the right of the JBoss Home field.

      +

      In the JBoss Server dialog, click i13-ellipsis-button to the right of the JBoss Home field.

      i13 jboss server dialog initial
      -
      Figure 65. WildFly server dialog in IntelliJ IDEA
      +
      Figure 64. WildFly server dialog in IntelliJ IDEA
    5. -

      In the JBoss Home Directory dialog, select the folder in which you have the WildFly server installed, and click OK.

      +

      In the JBoss Home Directory dialog, select the folder in which you have the WildFly server installed, and click OK.

      i13 jboss home directory
      -
      Figure 66. WildFly home in IntelliJ IDEA
      +
      Figure 65. WildFly home in IntelliJ IDEA
    6. @@ -4515,30 +4609,30 @@

      A.2.2. Define WildFly

      i13 jboss server dialog final
      -
      Figure 67. WildFly final dialog in IntelliJ IDEA
      +
      Figure 66. WildFly final dialog in IntelliJ IDEA
  • -

    In the Settings (Preferences) dialog, click OK.

    +

    In the Settings (Preferences) dialog, click OK.

    i13 jboss defined
    -
    Figure 68. WildFly defined in IntelliJ IDEA
    +
    Figure 67. WildFly defined in IntelliJ IDEA
  • -

    A.2.3. Create a project

    +

    16.2.3. Create a project

    The sample application is supplied as a Maven project with an associated pom.xml file that contains all the necessary project definitions. The corresponding IntelliJ IDEA project in such a case can be created by simply "opening" the pom.xml file. (Obviously, this isn’t the only way to create projects in IDEA. You can create projects for existing collections of source files, import Eclipse and Flash Builder projects, and Gradle build scripts. Finally, you can create projects from scratch.)

    1. -

      On the Welcome screen, to the left of Configure, click Back image::images/i13-back-icon.png[title="Back icon in IntelliJ IDEA"].

      +

      On the Welcome screen, to the left of Configure, click Back i13-back-icon.

    2. Under Quick Start, click Open Project.

      @@ -4546,16 +4640,16 @@

      A.2.3. Create a project

      i13 open project
      -
      Figure 69. Open project in IntelliJ IDEA
      +
      Figure 68. Open project in IntelliJ IDEA
  • -

    In the Open Project dialog, select the pom.xml file associated with the sample application, and click OK.

    +

    In the Open Project dialog, select the pom.xml file associated with the sample application, and click OK.

    i13 select pom
    -
    Figure 70. Select pom in IntelliJ IDEA
    +
    Figure 69. Select pom in IntelliJ IDEA

    Wait while IntelliJ IDEA is processing pom.xml and creating the project. When this process is complete, the following message is shown:

    @@ -4564,16 +4658,16 @@

    A.2.3. Create a project

    i13 jpa detected
    -
    Figure 71. Configure JPA in IntelliJ IDEA
    +
    Figure 70. Configure JPA in IntelliJ IDEA
  • -

    Click Configure in the message box. (If by now the message has disappeared, click image::images/i13-exclamation-mark-icon.png[title="Mark icon in IntelliJ IDEA"] on the Status bar.

    +

    Click Configure in the message box. (If by now the message has disappeared, click i13-exclamation-mark-icon on the Status bar.

    i13 jpa detected status bar
    -
    Figure 72. JPA detected in status bar in IntelliJ IDEA
    +
    Figure 71. JPA detected in status bar in IntelliJ IDEA

    The Event Log tool window will open. Click Configure in this window.)

    @@ -4582,16 +4676,16 @@

    A.2.3. Create a project

    i13 jpa detected event log
    -
    Figure 73. JPA detected event log in IntelliJ IDEA
    +
    Figure 72. JPA detected event log in IntelliJ IDEA
  • -

    In the Setup Frameworks dialog, just click OK. (By doing so you confirm that the file persistence.xml found in the project belongs to the JPA framework.)

    +

    In the Setup Frameworks dialog, just click OK. (By doing so you confirm that the file persistence.xml found in the project belongs to the JPA framework.)

    i13 setup frameworks jpa
    -
    Figure 74. Setup frameworks in IntelliJ IDEA
    +
    Figure 73. Setup frameworks in IntelliJ IDEA

    Now, as an intermediate check, make sure that the project structure looks something similar to this:

    @@ -4600,35 +4694,35 @@

    A.2.3. Create a project

    i13 initial project structure
    -
    Figure 75. Project structure in IntelliJ IDEA
    +
    Figure 74. Project structure in IntelliJ IDEA
  • -

    A.2.4. Create a run/debug configuration

    +

    16.2.4. Create a run/debug configuration

    Applications in IntelliJ IDEA are run and debugged according to what is called run/debug configurations. Now we are going to create the configuration for running and debugging the sample application in the context of WildFly.

    1. -

      In the main menu, select Run | Edit Configurations.

      +

      In the main menu, select Run ▸ Edit Configurations….

      i13 run edit configurations
      -
      Figure 76. Edit configurations in IntelliJ IDEA
      +
      Figure 75. Edit configurations in IntelliJ IDEA
    2. -

      In the Run/Debug Configurations dialog, click image::images/i13-plus-icon.png[title="Plus icon in IntelliJ IDEA"], select JBoss Server, and then select Local.

      +

      In the Run/Debug Configurations dialog, click i13-plus-icon, select JBoss Server, and then select Local.

      i13 run configs plus jboss
      -
      Figure 77. WildFly configuration in IntelliJ IDEA
      +
      Figure 76. WildFly configuration in IntelliJ IDEA

      As a result, the run/debug configuration for the WildFly server is created and its settings are shown in the right-hand part of the dialog.

      @@ -4638,39 +4732,39 @@

      A.2.4. Create a run/debug configuration<

      Change the name of the run/debug configuration to WildFly8 (optional).

    3. -

      In the lower part of the dialog, within the line Warning: No artifacts marked for deployment, click Fix and select movieplex7:war exploded. (Artifacts in IntelliJ IDEA are deployment-ready project outputs and also the configurations according to which such outputs are produced. In our case, there are two configurations for the sample application (movieplex7:war and movieplex7:war exploded). Both configurations represent a format suitable for deployment onto a Java EE 7-enabled application server. movieplex7:war corresponds to a Web archive (WAR). movieplex7:war exploded corresponds to the sample application directory structure (a decompressed archive). The second of the formats is more suitable at the development stage because manipulations with it are faster.)

      +

      In the lower part of the dialog, within the line Warning: No artifacts marked for deployment, click Fix and select movieplex7:war exploded. (Artifacts in IntelliJ IDEA are deployment-ready project outputs and also the configurations according to which such outputs are produced. In our case, there are two configurations for the sample application (movieplex7:war and movieplex7:war exploded). Both configurations represent a format suitable for deployment onto a Java EE 7-enabled application server. movieplex7:war corresponds to a Web archive (WAR). movieplex7:war exploded corresponds to the sample application directory structure (a decompressed archive). The second of the formats is more suitable at the development stage because manipulations with it are faster.)

      i13 jboss fix deployment
      -
      Figure 78. Fixing deployment warning in IntelliJ IDEA
      +
      Figure 77. Fixing deployment warning in IntelliJ IDEA
    4. -

      Within the line Error: Artifact 'movieplex7: exploded' has invalid extension, click Fix.

      +

      Within the line Error: Artifact 'movieplex7: exploded' has invalid extension, click Fix.

      i13 jboss invalid extension
      -
      Figure 79. Invalid extension error message in IntelliJ IDEA
      +
      Figure 78. Invalid extension error message in IntelliJ IDEA
    5. -

      In the Project Structure dialog, add .war at the end of the output directory path, and click OK. (For the servers of the JBoss family, the application root directory has to have .war at the end.)

      +

      In the Project Structure dialog, add .war at the end of the output directory path, and click OK. (For the servers of the JBoss family, the application root directory has to have .war at the end.)

      i13 jboss fix extension
      -
      Figure 80. Extension error fix in IntelliJ IDEA
      +
      Figure 79. Extension error fix in IntelliJ IDEA
    6. -

      In the Run/Debug Configurations dialog, switch to the Server tab. In the field for the application starting page URL, replace http://localhost:8080/movieplex7-1/ with http://localhost:8080/movieplex7-1.0-SNAPSHOT/ and click OK.

      +

      In the Run/Debug Configurations dialog, switch to the Server tab. In the field for the application starting page URL, replace http://localhost:8080/movieplex7-1/ with http://localhost:8080/movieplex7-1.0-SNAPSHOT/ and click OK.

      i13 jboss url fixed
      -
      Figure 81. Fixing application URL in IntelliJ IDEA
      +
      Figure 80. Fixing application URL in IntelliJ IDEA
    @@ -4680,15 +4774,15 @@

    A.2.4. Create a run/debug configuration<

    -

    A.2.5. Run the application

    +

    16.2.5. Run the application

    -

    In the Application Servers tool window, select the server run/debug configuration (WildFly8 [local]) and click Run image::images/i13-run-icon.png[title="Run icon in IntelliJ IDEA"].

    +

    In the Application Servers tool window, select the server run/debug configuration (WildFly8 [local]) and click Run i13-run-icon.

    i13 run wildfly
    -
    Figure 82. Run WildFly in IntelliJ IDEA
    +
    Figure 81. Run WildFly in IntelliJ IDEA

    IntelliJ IDEA compiles the code, builds the artifact, starts WildFly and deploys the artifact to the server. You can monitor this process in the Run tool window that opens in the lower part of the workspace.

    @@ -4697,7 +4791,7 @@

    A.2.5. Run the application

    i13 run tool window wildfly
    -
    Figure 83. Run tool window in IntelliJ IDEA
    +
    Figure 82. Run tool window in IntelliJ IDEA

    Finally, your default Web browser opens and the starting page of the application is shown.

    @@ -4706,7 +4800,7 @@

    A.2.5. Run the application

    i13 starting page in browser
    -
    Figure 84. Starting page in browser from IntelliJ IDEA
    +
    Figure 83. Starting page in browser from IntelliJ IDEA

    At this step IntelliJ IDEA is fully prepared for your development work, and you can continue with your exercises.

    @@ -4718,8 +4812,8 @@

    A.2.5. Run the application

    diff --git a/docs/javaee7-hol.pdf b/docs/javaee7-hol.pdf index 59f01ea..73810e5 100644 Binary files a/docs/javaee7-hol.pdf and b/docs/javaee7-hol.pdf differ diff --git a/docs/javaee7-hol.xml b/docs/javaee7-hol.xml index 7c74124..bba9492 100644 --- a/docs/javaee7-hol.xml +++ b/docs/javaee7-hol.xml @@ -5,19 +5,19 @@ Java EE 7 Hands-on Lab -Jan 28, 2014 +Jun 25, 2014 Arun Gupta -arungupta@redhat.com +https://twitter.com/arungupta[@arungupta] AG -2.0 -Jan 28, 2014 +2.1 +Jun 25, 2014 AG @@ -82,11 +82,11 @@ using the following Java EE 7 technologies: http://www.oracle.com/technetwork/java/javase/downloads/index.html. -Application Server: This lab can use WildFly 8 or GlassFish 4 as the application server. This document provide instructions for +Application Server: This lab can use WildFly 8 or GlassFish 4 as the application server. This document provides instructions for WildFly 8. -IDE: NetBeans 7.4+, JBoss Developer Studio (Eclipse-based), or IntelliJ IDEA 13 can be used. This document provide instructions for +IDE: NetBeans 8.0+, JBoss Developer Studio (Eclipse-based), or IntelliJ IDEA 13 can be used. This document provides instructions for NetBeans 8. Download “All” or “Java EE” version from http://netbeans.org/downloads/. A @@ -106,6 +106,7 @@ snapshot of the downloads page is shown and highlights the exact explains how to configure WildFly in IntelliJ IDEA. + @@ -246,6 +247,7 @@ to stay focused on explaining the technology. It is highly recommended to make sure that the code copied from this sample application is updated to meet those requirements. +
    Lab Flow The attendees will start with an existing maven application and by @@ -265,16 +267,15 @@ platform. While you are copy/pasting the code from this document into NetBeans, here are couple of tips that will be really useful and make your experience enjoyable! - + + +Source Code Formatting NetBeans provides capability to neatly format the source code following conventions. This can be done for any type of source code, whether its XML or Java or something else. It is highly recommended to use this functionality after the code is copy/pasted from this document to the editor. This keeps the code legible. - - - This functionality can be accessed by right-clicking in the editor pane and selecting “Format” as shown.
    @@ -319,15 +320,15 @@ shortcuts: - Ctrl + Shift + F + CtrlShiftF - Mac + OSX - Alt + Shift + F + AltShiftF Windows @@ -335,7 +336,7 @@ shortcuts: - Alt + Shift + F + AltShiftF Linux @@ -346,15 +347,15 @@ shortcuts: - + + + +Automatic Imports Copy/pasting the Java code from this document in NetBeans editor does not auto-import the classes. This is required to be done manually in order for the classes to compile. This can be fixed for each missing import statement by clicking on the yellow bulb shown in the side bar. - - -
    ServerEndpoint import @@ -409,15 +410,15 @@ shortcuts: - Command + Shift + I + CommandShiftI - Mac + OSX - Ctrl + Shift + I + CtrlShiftI Windows @@ -425,7 +426,7 @@ shortcuts: - Ctrl + Shift + I + CtrlShiftI Linux @@ -440,6 +441,10 @@ shortcuts: class is available to import from multiple packages. If multiple packages are available then specific packages to import from are clearly marked in the document. + + + +
    Estimated Time @@ -546,6 +551,7 @@ shorter time, and you can do it too! version of the lab depending upon your target audience and available time. +
    @@ -588,6 +594,7 @@ is shown. <scope>provided</scope> </dependency> </dependencies> + This will ensure that Java EE 7 APIs are retrieved from the central Maven repository. @@ -602,12 +609,8 @@ specifically targeted at modern web applications. The complete set of specifications defined in the Web Profile is defined in the Java EE 7 Web Profile Specification. + WildFly can be started in Full Platform or Web Profile. - -This lab requires Full Platform download. All technologies used in this -lab, except Java Message Service and Batch Applications for the Java -Platform, can be deployed on Web Profile. - Default Data Source: Expand ‘Other Sources’, @@ -661,6 +664,7 @@ to view the XML source. </properties> </persistence-unit> </persistence> + Notice <jta-data-source> is commented out, i.e. no data source element is specified. This element identifies the JDBC resource to connect to in the runtime environment of the underlying application server. @@ -668,6 +672,7 @@ the runtime environment of the underlying application server. provided by the runtime. This pre-configured data source is accessible under the JNDI name java:comp/DefaultDataSource + The JPA 2.1 specification says if neither jta-data-source nor non-jta-data-source elements are specified, the deployer must specify a JTA data source or the default JTA data source must be provided by the @@ -742,7 +747,7 @@ to the database artifacts. javax.persistence.schema-generation.create-source - javax.persistence.schema-generation.drop-source +javax.persistence.schema-generation.drop-source Specifies whether the creation or deletion of database artifacts is to occur on the basis of the object/relational mapping metadata, DDL @@ -755,7 +760,7 @@ script, or a combination of the two. javax.persistence.schema-generation.create-script-source - javax.persistence.schema-generation.drop-script-source +javax.persistence.schema-generation.drop-script-source Specifies a java.IO.Reader configured for reading of the SQL script or a string designating a file URL for the SQL script to create or delete @@ -851,7 +856,7 @@ corresponding REST endpoint is shown. MovieFacadeREST - /webresources/movie + /webresources/movie @@ -861,7 +866,7 @@ corresponding REST endpoint is shown. SalesFacadeREST - /webresources/sales + /webresources/sales @@ -871,7 +876,7 @@ corresponding REST endpoint is shown. ShowTimingFacadeREST - /webresources/showtiming + /webresources/showtiming @@ -881,7 +886,7 @@ corresponding REST endpoint is shown. TheaterFacadeREST - /webresources/theater + /webresources/theater @@ -891,7 +896,7 @@ corresponding REST endpoint is shown. TimeslotFacadeREST - /webresources/timeslot + /webresources/timeslot @@ -932,6 +937,7 @@ that the classes cannot be resolved. This is expected before the dependencies are downloaded. However these references will be resolved correctly after the dependencies are downloaded during project building. + During the first run, the IDE will ask you to select a deployment server. Choose the configured WildFly server and click on ‘OK’.
    @@ -957,6 +963,7 @@ Choose the configured WildFly server and click on ‘OK’. + Chat Room (Java API for WebSocket) @@ -1025,6 +1032,7 @@ public class ChatServer { } } } + In this code: @@ -1043,11 +1051,12 @@ The second parameter, client, defines the other end of the We connection. The method implementation transmits the received text message to all clients connected to this endpoint. Resolve the imports by right-clicking in the editor and selecting ‘Fix -Imports’ or (Command + Shift + I shortcut on Mac or Ctrl + Shift + I on +Imports’ or (CommandShiftI shortcut on OSX or CtrlShiftI on Windows). Make sure to pick java.websocket.Session for resolving imports. This is not the default option shown by NetBeans. +
    javax.websocket.Session import @@ -1062,6 +1071,7 @@ Windows). code. + In ‘Web Pages’, select ‘New’, ‘Folder’, give the folder name as @@ -1086,33 +1096,36 @@ code. In this file, remove <ui:define> sections where name attribute value is ‘top’ and ‘left’. These sections are inherited from the template. Replace <ui:define> section with ‘content’ name such that it looks like: -<ui:define name="content"> - <form action=""> - <table> - <tr> - <td> - Chat Log<br/> - <textarea readonly="true" rows="6" cols="50" id="chatlog"></textarea> - </td> - <td> - Users<br/> - <textarea readonly="true" rows="6" cols="20" id="users"></textarea> - </td> - </tr> - <tr> - <td colspan="2"> - <input id="textField" name="name" value="Duke" type="text"/> - <input onclick="join();" value="Join" type="button"/> - <input onclick="send_message();" value="Send" type="button"/><p/> - <input onclick="disconnect();" value="Disconnect" type="button"/> - </td> - </tr> - </table> - </form> - <div id="output"></div> - <script language="javascript" type="text/javascript" - src="${facesContext.externalContext.requestContextPath}/chat/websocket.js"></script> -</ui:define> +<ui:composition template="../WEB-INF/template.xhtml"> + <ui:define name="content"> + <form action=""> + <table> + <tr> + <td> + Chat Log<br/> + <textarea readonly="true" rows="6" cols="50" id="chatlog"></textarea> + </td> + <td> + Users<br/> + <textarea readonly="true" rows="6" cols="20" id="users"></textarea> + </td> + </tr> + <tr> + <td colspan="2"> + <input id="textField" name="name" value="Duke" type="text"/> + <input onclick="join();" value="Join" type="button"/> + <input onclick="send_message();" value="Send" type="button"/><p/> + <input onclick="disconnect();" value="Disconnect" type="button"/> + </td> + </tr> + </table> + </form> + <div id="output"></div> + <script language="javascript" type="text/javascript" + src="${facesContext.externalContext.requestContextPath}/chat/websocket.js"></script> + </ui:define> +</ui:composition> + The code builds an HTML form that has two textareas – one to display the chat log and the other to display the list of users currently logged. A single text box is used to take the user name or the chat message. @@ -1127,7 +1140,7 @@ initialization occurs in ‘websocket.js’ included at the bottom of th fragment. -Right-click on ‘chat’ in ‘Web Pages’, select ‘New’, ‘Web’ +Right-click on ‘chat’ in ‘Web Pages’, select ‘New’, ‘Other’, ‘Web’ categories, ‘JavaScript File’ file type. Click on ‘Next’. Give the name as ‘websocket’ and click on ‘Finish’. @@ -1192,6 +1205,7 @@ function writeToScreen(message) { pre.innerHTML = message; output.appendChild(pre); } + The WebSocket endpoint URI is calculated by using standard JavaScript variables and appending the URI specified in the ChatServer class. WebSocket is initialized by calling new WebSocket(...). Event handlers are @@ -1270,11 +1284,13 @@ logged in users as well. Edit ‘WEB-INF/template.xhtml’ and change: <h:outputLink value="item2.xhtml">Item 2</h:outputLink> + to <h:outputLink value="${facesContext.externalContext.requestContextPath}/faces/chat/chatroom.xhtml"> Chat Room </h:outputLink> + The outputLink tag renders an HTML anchor tag with an href attribute. ${facesContext.externalContext.requestContextPath} provides the request URI that identifies the web application context for this request. This @@ -1347,6 +1363,7 @@ like as shown. WebSocket traffic. + Ticket Sales (Batch Applications for the Java Platform) @@ -1415,6 +1432,7 @@ specify the value as ‘org.javaee7.movieplex7.batch’, and click on specify the name as ‘SalesReader’. Make this class extend from ‘AbstractItemReader’ by changing the class definition and add: extends AbstractItemReader + AbstractItemReader is an abstract class that implements ItemReader interface. The ItemReader interface defines methods that read a stream of items for chunk processing. This reader implementation returns a @@ -1436,6 +1454,7 @@ public void open(Serializable checkpoint) throws Exception { .getContextClassLoader() .getResourceAsStream("META-INF/sales.csv"))); } + This method initializes a BufferedReader from ‘META-INF/sales.csv’ that is bundled with the application. Sampling of the first few lines from ‘sales.csv’ is shown below: @@ -1444,6 +1463,7 @@ is bundled with the application. 3,80.00 4,470.00 5,1100.x0 + Each line has a show identifier comma separated by the total sales for that show. Note that the last line (5th record in the sample) has an intentional typo. In addition, 17th record also has an additional @@ -1462,6 +1482,7 @@ public String readItem() { } return string; } + The readItem method returns the next item from the stream. It returns null to indicate end of stream. Note end of stream indicates end of chunk, so the current chunk will be committed and the step will end. @@ -1472,6 +1493,7 @@ so the current chunk will be committed and the step will end. ‘New’, ‘Java Class’, specify the name as ‘SalesProcessor’. Change the class definition and add: implements ItemProcessor + ItemProcessor is an interface that defines a method that is used to operate on an input item and produce an output item. This processor accepts a String input item from the reader, SalesReader in our case, @@ -1492,6 +1514,7 @@ public Sales processItem(Object s) { return sales; } + This method takes a String parameter coming from the SalesReader, parses the value, populates them in the Sales instance, and returns it. This is then aggregated with the writer. @@ -1508,6 +1531,7 @@ particular record is skipped from aggregation as well (shown later). ‘New’, ‘Java Class’, specify the name as ‘SalesWriter’. Change the class definition and add: extends AbstractItemWriter + AbstractItemWriter is an abstract class that implements ItemWriter interface. The ItemWriter interface defines methods that write to a stream of items for chunk processing. This writer writes a list of Sales @@ -1519,6 +1543,7 @@ the bean to be injected in Job XML. Inject EntityManager as: @PersistenceContext EntityManager em; + Override writeItems method from the abstract class by adding the following code: @Override @Transactional @@ -1527,6 +1552,7 @@ public void writeItems(List list) { em.persist(s); } } + Batch runtime aggregates the list of Sales instances returned from the SalesProessor and makes it available as List in this method. This method iterates over the list and persist each item in the database. @@ -1546,6 +1572,7 @@ using rollbackOn and dontRollbackOn attrib There is really no need for @Transactional on writeItems method but shows a usage for the annotation. + Resolve the imports. @@ -1558,7 +1585,7 @@ the name as ‘batch-jobs’, and click on ‘Finish’. Replace contents of the file with the following: <job id="endOfDaySales" - xmlns="http://xmlns.jcp.org/xml/ns/javaee[http://xmlns.jcp.org/xml/ns/javaee]" + xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0"> <step id="populateSales"> <chunk item-count="3" skip-limit="5"> @@ -1571,6 +1598,7 @@ click on ‘Next’, take the default, and click on ‘Finish’ </chunk> </step> </job> + This code shows that the job has one step of chunk type. The <reader>, <processor>, and <writer> elements define the CDI bean name of the implementations of ItemReader, ItemProcessor, and ItemWriter interfaces. @@ -1601,6 +1629,7 @@ button. ex.printStackTrace(); } } + This method uses BatchRuntime to get an instance of JobOperator, which is then used to start the job. JobOperator is the interface for operating on batch jobs. It can be used to start, stop, and restart @@ -1623,6 +1652,7 @@ the bean to be injectable in an EL expression. Inject EntityManagerFactory in the class as: @PersistenceUnit EntityManagerFactory emf; + and add the following method: public List<Sales> getSalesData() { return emf. @@ -1630,6 +1660,7 @@ the bean to be injectable in an EL expression. createNamedQuery("Sales.findAll", Sales.class). getResultList(); } + This method uses a pre-defined @NamedQuery to query the database and return all the rows from the table. Resolve the imports. @@ -1645,32 +1676,35 @@ expand ‘Web Pages’, ‘WEB-INF’, select ‘template.xh In this file, remove <ui:define> sections where name attribute value is ‘top’ and ‘left’. These sections are inherited from the template. Replace <ui:define> section with ‘content’ name such that it looks like: -<ui:define name="content"> - <h1>Movie Sales</h1> - <h:form> - <h:dataTable value="#{salesBean.salesData}" var="s" border="1"> - <h:column> - <f:facet name="header"> - <h:outputText value="Show ID" /> - </f:facet> - #{s.id} - </h:column> - <h:column> - <f:facet name="header"> - <h:outputText value="Sales" /> - </f:facet> - #{s.amount} - </h:column> - </h:dataTable> - <h:commandButton - value="Run Job" - action="sales" - actionListener="#{salesBean.runJob()}"/> - <h:commandButton - value="Refresh" - action="sales" /> - </h:form> -</ui:define> +<ui:composition template="../WEB-INF/template.xhtml"> + <ui:define name="content"> + <h1>Movie Sales</h1> + <h:form> + <h:dataTable value="#{salesBean.salesData}" var="s" border="1"> + <h:column> + <f:facet name="header"> + <h:outputText value="Show ID" /> + </f:facet> + #{s.id} + </h:column> + <h:column> + <f:facet name="header"> + <h:outputText value="Sales" /> + </f:facet> + #{s.amount} + </h:column> + </h:dataTable> + <h:commandButton + value="Run Job" + action="sales" + actionListener="#{salesBean.runJob()}"/> + <h:commandButton + value="Refresh" + action="sales" /> + </h:form> + </ui:define> +</ui:composition> + This code displays the show identifier and sales from that show in a table by invoking SalesBean.getSalesData(). First command button allows invoking the job that processes the CSV file and populates the database. @@ -1684,6 +1718,7 @@ needs to be repeated for f: prefix. value="${facesContext.externalContext.requestContextPath}/faces/batch/sales.xhtml"> Sales </h:outputLink> + Run the project to see the output as shown. @@ -1734,6 +1769,7 @@ have correct numeric entries for the sales total. The Job XML for the application explicitly mentioned to skip such errors. + View and Delete Movie (Java API for RESTful Web Services) @@ -1781,6 +1817,7 @@ to be automatically activated and passivated with the request. Make sure to pick javax.enterprise.context.RequestScoped class. +
    RequestScoped import @@ -1817,6 +1854,7 @@ public void init() { public void destroy() { client.close(); } + ClientBuilder is the main entry point to the Client API. It uses a fluent builder API to invoke REST endpoints. A new Client instance is created using the default client builder implementation provided by the @@ -1837,6 +1875,7 @@ added in CDI 1.1 .request() .get(Movie[].class); } + A request is prepared by calling the request method. HTTP GET method is invoked by calling get method. The response type is specified in the last method call and so return value is of the type Movie[]. @@ -1854,16 +1893,19 @@ expand ‘Web Pages’, ‘WEB-INF’, select ‘template.xh In this file, remove <ui:define> sections where name attribute value is ‘top’ and ‘left’. These sections are inherited from the template. Replace <ui:define> section with ‘content’ name such that it looks like: -<ui:define name="content"> - <h:form prependId="false"> - <h:selectOneRadio value="#{movieBackingBean.movieId}" layout="pageDirection"> - <c:forEach items="#{movieClientBean.movies}" var="m"> - <f:selectItem itemValue="#{m.id}" itemLabel="#{m.name}"/> - </c:forEach> - </h:selectOneRadio> - <h:commandButton value="Details" action="movie" /> - </h:form> -</ui:define> +<ui:composition template="../WEB-INF/template.xhtml"> + <ui:define name="content"> + <h:form prependId="false"> + <h:selectOneRadio value="#{movieBackingBean.movieId}" layout="pageDirection"> + <c:forEach items="#{movieClientBean.movies}" var="m"> + <f:selectItem itemValue="#{m.id}" itemLabel="#{m.name}"/> + </c:forEach> + </h:selectOneRadio> + <h:commandButton value="Details" action="movie" /> + </h:form> + </ui:define> +</ui:composition> + This code fragment invokes getMovies method from MovieClientBean, iterates over the response in a for loop, and display the name of each movie with a radio button. The selected radio button value is bound to @@ -1890,8 +1932,9 @@ and f: prefixes. on ‘Finish’. Add the following field: int movieId; + Add getters/setters by right-clicking on the editor pane and selecting -‘Insert Code’ (Ctrl + I shortcut on Mac). Select the field and click on +‘Insert Code’ (CtrlI shortcut on OSX). Select the field and click on ‘Generate’. Add @Named and @SessionScoped class-level annotations and implements Serializable. @@ -1899,6 +1942,7 @@ on ‘Finish’. Make sure to import javax.enterprise.context.SessionScoped. + In ‘template.xhtml’, add the following code along with other <outputLink>s: @@ -1906,7 +1950,8 @@ on ‘Finish’. value="${facesContext.externalContext.requestContextPath}/faces/client/movies.xhtml"> Movies </h:outputLink> -Running the project (Fn + F6 shortcut on Mac) and clicking on ‘Movies’ + +Running the project (FnF6 shortcut on OSX) and clicking on ‘Movies’ in the left navigation bar shows the output as shown.
    List of movies output page @@ -1926,6 +1971,7 @@ displayed. of selected movie from the page. Add the following code: @Inject MovieBackingBean bean; + In MovieClientBean, add the following method: @@ -1937,6 +1983,7 @@ MovieBackingBean bean; .get(Movie.class); return m; } + This code reuses the Client and WebTarget instances created in @PostConstruct. It also adds a variable part to the URI of the REST endpoint, defined using {movie}, and binds it to a concrete value using @@ -1973,6 +2020,7 @@ click on ‘Select File’. Click on ‘Finish’. <h:commandButton value="Back" action="movies" /> </h:form> </ui:define> + Click on the yellow-bulb to resolve the namespace prefix-URI mapping for h:. The output values are displayed by calling the getMovie method and @@ -2001,6 +2049,7 @@ following code with other <commandButton>. value="Delete" action="movies" actionListener="#{movieClientBean.deleteMovie()}"/> + This button displays a label ‘Delete’, invokes the method deleteMovie from ‘MovieClientBean’, and then renders ‘movies.xhtml’. @@ -2013,6 +2062,7 @@ from ‘MovieClientBean’, and then renders ‘movies.xhtml’. .request() .delete(); } + This code again reuses the Client and WebTarget instances created in @PostConstruct. It also adds a variable part to the URI of the REST endpoint, defined using {movieId}, and binds it to a concrete value @@ -2035,6 +2085,7 @@ the database and refreshes list on the page. Note that a redeploy of the project will delete all the movies anyway and add them all back. + Add Movie (Java API for JSON Processing) @@ -2079,6 +2130,7 @@ specify the name as ‘MovieReader’, and click on ‘Finish’ following class-level annotations: @Provider @Consumes(MediaType.APPLICATION_JSON) + @Provider allows this implementation to be discovered by the JAX-RS runtime during the provider scanning phase. @Consumes indicates that this implementation will consume a JSON representation of the resource. @@ -2112,6 +2164,7 @@ select ‘Implement all abstract methods’. Change implementation of the isReadable method as: return Movie.class.isAssignableFrom(type); + This method ascertains if the MessageBodyReader can produce an instance of a particular type. @@ -2154,6 +2207,7 @@ public Movie readFrom( } return movie; } + This code reads a type from the input stream in. JsonParser, a streaming parser, is created from the input stream. Key values are read from the parser and a Movie instance is populated and returned. @@ -2165,6 +2219,7 @@ specify the name as ‘MovieWriter’, and click on ‘Finish’ following class-level annotations: @Provider @Produces(MediaType.APPLICATION_JSON) + @Provider allows this implementation to be discovered by the JAX-RS runtime during the provider scanning phase. @Produces indicates that this implementation will produce a JSON representation of the resource. @@ -2183,6 +2238,7 @@ this implementation will produce a JSON representation of the resource. Make this class implement MessageBodyWriter interface by adding the following code: implements MessageBodyWriter<Movie> + Resolve the imports. The IDE provide a hint to implement abstract methods as:
    @@ -2201,12 +2257,14 @@ select ‘Implement all abstract methods’. Change implementation of the isWritable method to: return Movie.class.isAssignableFrom(type); + This method ascertains if the MessageBodyWriter supports a particular type. Add implementation of the getSize method as: return -1; + Originally, this method was called to ascertain the length in bytes of the serialized form of t. In JAX-RS 2.0, this method is deprecated and the value returned by the method is ignored by a JAX-RS runtime. All @@ -2221,6 +2279,7 @@ gen.writeStartObject() .write("actors", t.getActors()) .writeEnd(); gen.flush(); + This method writes a type to an HTTP message. JsonGenerator writes JSON data to an output stream in a streaming way. Overloaded write methods are used to write different data types to the stream. @@ -2237,29 +2296,32 @@ Click on ‘Finish’. In this file, remove <ui:define> sections where name attribute value is ‘top’ and ‘left’. These sections are inherited from the template. Replace <ui:define> section with ‘content’ name such that it looks like: -<ui:define name="content"> -<h1>Add a New Movie</h1> -<h:form> - <table cellpadding="5" cellspacing="5"> - <tr> - <th align="left">Movie Id:</th> - <td><h:inputText value="#{movieBackingBean.movieId}"/></td> - </tr> - <tr> - <th align="left">Movie Name:</th> - <td><h:inputText value="#{movieBackingBean.movieName}"/> </td> - </tr> - <tr> - <th align="left">Movie Actors:</th> - <td><h:inputText value="#{movieBackingBean.actors}"/></td> - </tr> - </table> - <h:commandButton - value="Add" - action="movies" - actionListener="#{movieClientBean.addMovie()}"/> -</h:form> -</ui:define> +<ui:composition template="../WEB-INF/template.xhtml"> + <ui:define name="content"> + <h1>Add a New Movie</h1> + <h:form> + <table cellpadding="5" cellspacing="5"> + <tr> + <th align="left">Movie Id:</th> + <td><h:inputText value="#{movieBackingBean.movieId}"/></td> + </tr> + <tr> + <th align="left">Movie Name:</th> + <td><h:inputText value="#{movieBackingBean.movieName}"/> </td> + </tr> + <tr> + <th align="left">Movie Actors:</th> + <td><h:inputText value="#{movieBackingBean.actors}"/></td> + </tr> + </table> + <h:commandButton + value="Add" + action="movies" + actionListener="#{movieClientBean.addMovie()}"/> + </h:form> + </ui:define> +</ui:composition> + This code creates a form to accept input of id, name, and actors of a movie. These values are bound to fields in MovieBackingBean. The click of command button invokes the addMovie method from MovieClientBean and @@ -2281,12 +2343,14 @@ prefix/URI mapping as shown. Add movieName and actors field to MovieBackingBean as: String movieName; String actors; + Generate getters and setters by clicking on the menu item ‘Source’ and then ‘Insert Code’. Add the following code to ‘movies.xhtml’ <h:commandButton value="New Movie" action="addmovie" /> + along with rest of the <commandButton>s. @@ -2301,6 +2365,7 @@ then ‘Insert Code’. .request() .post(Entity.entity(m, MediaType.APPLICATION_JSON)); } + This method creates a new Movie instance, populates it with the values from the backing bean, and POSTs the bean to the REST endpoint. The register method registers a MovieWriter that provides conversion from @@ -2361,6 +2426,7 @@ sequence; however this is not done in the application. Note that the newly added movie is now displayed. + Movie Points (Java Message Service) @@ -2399,6 +2465,7 @@ and click on ‘Finish’. Add the following class-level annotations: @Named @RequestScoped + This makes the bean to be EL-injectable and automatically activated and passivated with the request. Resolve the imports. @@ -2426,6 +2493,7 @@ explicit call to the bean from a JSF page. @Pattern(regexp = "^\\d{2},\\d{2}", message = "Message format must be 2 digits, comma, 2 digits, e.g.12,12") private String message; + This field contains the message sent to the queue. This field’s value is bound to an inputText in a JSF page (created later). Constraints have been specified on this bean that enable validation of data on form @@ -2436,7 +2504,7 @@ specified using message attribute. This could be thought as conveying the customer identifier and the points accrued by that customer. Generate getter/setters for this field. Right-click in the editor pane, -select ‘Insert Code’ (Ctrl + I shortcut on Mac), select ‘Getter and +select ‘Insert Code’ (CtrlI shortcut on OSX), select ‘Getter and Setter’, select the field, and click on ‘Generate’. @@ -2451,6 +2519,7 @@ public void sendMessage() { System.out.println("Sending message: " + message); context.createProducer().send(pointsQueue, message); } + The Java EE Platform requires a pre-configured JMS connection factory under the JNDI name java:comp/DefaultJMSConnectionFactory. If no connection factory is specified then the pre-configured connection @@ -2458,6 +2527,7 @@ factory is used. In a Java EE environment, where CDI is enabled by default anyway, a container-managed JMSContext can be injected as: @Inject JMSContext context; + This code uses the default factory to inject an instance of container-managed JMSContext. JMSContext is a new interface introduced in JMS 2. This combines in a @@ -2480,6 +2550,7 @@ message field. Make sure Queue class is imported from javax.jms.Queue instead of the default java.util.Queue. + Click on ‘OK’. @@ -2490,6 +2561,7 @@ default java.util.Queue. interfaceName = "javax.jms.Queue") @Named @RequestScoped + This allows the bean to refered from an EL expression. It also activates and passivates the bean with the request. JMSDestinationDefinition is a new annotation introduced in JMS 2. It is @@ -2513,6 +2585,7 @@ public String receiveMessage() { return message; } } + This code creates JMSConsumer in a try-with-resources block which is then used to synchronously receive a message. Note that JMSConsumer is created as an auto-managed resource and so is closed automatically after @@ -2535,6 +2608,7 @@ using Message Driven Beans. However that is not covered in this lab. } return count; } + This code creates a QueueBrowser to look at the messages on a queue without removing them. It calculates and returns the total number of messages in the queue. @@ -2553,24 +2627,27 @@ next to ‘Template:’, expand ‘Web Pages’, ‘WEB-INF& In this file, remove <ui:define> sections where name attribute value is ‘top’ and ‘left’. These sections are inherited from the template. Replace the <ui:define> section with ‘content’ name such that it looks like: -<ui:define name="content"> - <h1>Points</h1> - <h:form> - Queue size: - <h:outputText value="#{receivePointsBean.queueSize}"/><p/> - <h:inputText value="#{sendPointsBean.message}"/> - <h:commandButton - value="Send Message" - action="points" - actionListener="#{sendPointsBean.sendMessage()}"/> - </h:form> - <h:form> - <h:commandButton - value="Receive Message" - action="points" - actionListener="#{receivePointsBean.receiveMessage()}"/> - </h:form> -</ui:define> +<ui:composition template="../WEB-INF/template.xhtml"> + <ui:define name="content"> + <h1>Points</h1> + <h:form> + Queue size: + <h:outputText value="#{receivePointsBean.queueSize}"/><p/> + <h:inputText value="#{sendPointsBean.message}"/> + <h:commandButton + value="Send Message" + action="points" + actionListener="#{sendPointsBean.sendMessage()}"/> + </h:form> + <h:form> + <h:commandButton + value="Receive Message" + action="points" + actionListener="#{receivePointsBean.receiveMessage()}"/> + </h:form> + </ui:define> +</ui:composition> + Click on the yellow bulb to resolve namespace prefix/URI mapping for h: prefix. This page displays the number of messages in the current queue. It @@ -2590,6 +2667,7 @@ message is displayed on the screen. value="${facesContext.externalContext.requestContextPath}/faces/points/points.xhtml"> Points </h:outputLink> + Run the project. The update page looks like as shown: @@ -2681,6 +2759,7 @@ queue has 0 messages. remaining messages in the queue. + Show Booking (JavaServer Faces) @@ -2735,22 +2814,25 @@ next to ‘Template:’, expand ‘Web Pages’, ‘WEB-INF& In this file, remove <ui:define> sections with ‘top’ and ‘left’ name attributes. These sections are inherited from the template. Replace <ui:define> section with ‘content’ name such that it looks like: -<ui:define name="content"> - <h2>Pick a movie</h2> - <h:form prependId="false"> - <h:selectOneRadio - value="#{booking.movieId}" - layout="pageDirection" - required="true"> - <f:selectItems - value="#{movieFacadeREST.all}" - var="m" - itemValue="#{m.id}" - itemLabel="#{m.name}"/> - </h:selectOneRadio> - <h:commandButton id="shows" value="Pick a time" action="showtimes" /> - </h:form> -</ui:define> +<ui:composition template="../WEB-INF/template.xhtml"> + <ui:define name="content"> + <h2>Pick a movie</h2> + <h:form prependId="false"> + <h:selectOneRadio + value="#{booking.movieId}" + layout="pageDirection" + required="true"> + <f:selectItems + value="#{movieFacadeREST.all}" + var="m" + itemValue="#{m.id}" + itemLabel="#{m.name}"/> + </h:selectOneRadio> + <h:commandButton id="shows" value="Pick a time" action="showtimes" /> + </h:form> + </ui:define> +</ui:composition> + The code builds an HTML form that displays the list of movies as radio button choices. The chosen movie is bound to #{booking.movieId} which will be defined as a flow-scoped bean. The value of action attribute on @@ -2774,15 +2856,17 @@ add namespace prefix/URI mapping for h:. Repeat the same for Specify the class name as ‘Booking’ and the package name as ‘org.javaee7.movieplex7.booking’. Add @Named class-level annotation to make the class EL-injectable. -Add @FlowScoped("booking") to define the scope of bean as the flow. The bean -is automatically activated and passivated as the flow is entered or exited. +Add @FlowScoped("booking") to define the scope of bean as the flow. The bean is automatically activated and passivated as the flow is entered or exited. +Add implements Serializable to the class as beans with @FlowScoped annotation need to be passivation capable, and thus serializable. Add the following field: int movieId; + and generate getters/setters by going to ‘Source’, ‘Insert Code’, selecting ‘Getter and Setter’, and select the field. Inject EntityManager in this class by adding the following code: @PersistenceContext EntityManager em; + Add the following convenience method: public String getMovieName() { try { @@ -2794,6 +2878,7 @@ EntityManager em; return ""; } } + This method will return the movie name based upon the selected movie. Alternatively, movie id and name may be passed from the selected radio button and parsed in the backing bean. This will reduce an extra trip to @@ -2806,18 +2891,21 @@ steps used to create ‘booking.xhtml’. In this file, remove <ui:define> sections with ‘top’ and ‘left’ name attributes. These sections are inherited from the template. Replace <ui:define> section with ‘content’ name such that it looks like: -<ui:define name="content"> - <h2>Show Timings for <font color="red">#{booking.movieName}</font></h2> - <h:form> - <h:selectOneRadio value="#{booking.startTime}" layout="pageDirection" required="true"> - <c:forEach items="#{timeslotFacadeREST.all}" var="s"> - <f:selectItem itemValue="#{s.id},#{s.startTime}" itemLabel="#{s.startTime}"/> - </c:forEach> - </h:selectOneRadio> - <h:commandButton value="Confirm" action="confirm" /> - <h:commandButton id="back" value="Back" action="booking" immediate="true"/> - </h:form> -</ui:define> +<ui:composition template="../WEB-INF/template.xhtml"> + <ui:define name="content"> + <h2>Show Timings for <font color="red">#{booking.movieName}</font></h2> + <h:form> + <h:selectOneRadio value="#{booking.startTime}" layout="pageDirection" required="true"> + <c:forEach items="#{timeslotFacadeREST.all}" var="s"> + <f:selectItem itemValue="#{s.id},#{s.startTime}" itemLabel="#{s.startTime}"/> + </c:forEach> + </h:selectOneRadio> + <h:commandButton value="Confirm" action="confirm" /> + <h:commandButton id="back" value="Back" action="booking" immediate="true"/> + </h:form> + </ui:define> +</ui:composition> + This code builds an HTML form that displays the chosen movie name and all the show times. #{timeslotFacadeREST.all} returns the list of all the movies and iterates over them using a c:forEach loop. The id and @@ -2837,6 +2925,7 @@ available for this movie; however this is not part of the application. Add the following fields to the Booking class: String startTime; int startTimeId; + And the following methods: public String getStartTime() { return startTime; @@ -2851,6 +2940,7 @@ public void setStartTime(String startTime) { public int getStartTimeId() { return startTimeId; } + These methods will parse the values received from the form. Also add the following method: public String getTheater() { @@ -2877,6 +2967,7 @@ following method: return "none"; } } + This method will find the first theater available for the chosen movie and show the timing. Additionally a list of theaters offering that movie may be shown in a @@ -2889,28 +2980,31 @@ the steps used to create ‘booking.xhtml’. In this file, remove <ui:define> sections wht ‘top’ and ‘left’ name attributes. These sections are inherited from the template. Replace ‘<ui:define>’ section with ‘content’ name such that it looks like: -<ui:define name="content"> - <c:choose> - <c:when test="#{booking.theater == 'none'}"> - <h2>No theater found, choose a different time</h2> - <h:form> - Movie name: #{booking.movieName}<p/> - Starts at: #{booking.startTime}<p/> - <h:commandButton id="back" value="Back" action="showtimes"/> - </h:form> - </c:when> - <c:otherwise> - <h2>Confirm ?</h2> - <h:form> - Movie name: #{booking.movieName}<p/> - Starts at: #{booking.startTime}<p/> - Theater: #{booking.theater}<p/> - <h:commandButton id="next" value="Book" action="print"/> - <h:commandButton id="back" value="Back" action="showtimes"/> - </h:form> - </c:otherwise> - </c:choose> -</ui:define> +<ui:composition template="../WEB-INF/template.xhtml"> + <ui:define name="content"> + <c:choose> + <c:when test="#{booking.theater == 'none'}"> + <h2>No theater found, choose a different time</h2> + <h:form> + Movie name: #{booking.movieName}<p/> + Starts at: #{booking.startTime}<p/> + <h:commandButton id="back" value="Back" action="showtimes"/> + </h:form> + </c:when> + <c:otherwise> + <h2>Confirm ?</h2> + <h:form> + Movie name: #{booking.movieName}<p/> + Starts at: #{booking.startTime}<p/> + Theater: #{booking.theater}<p/> + <h:commandButton id="next" value="Book" action="print"/> + <h:commandButton id="back" value="Back" action="showtimes"/> + </h:form> + </c:otherwise> + </c:choose> + </ui:define> +</ui:composition> + The code displays the selected movie, show timing, and theater if available. The reservation can proceed if all three are available. ‘print.xhtml’ is the last page that shows the confirmed reservation @@ -2927,15 +3021,18 @@ steps used to create ‘booking.xhtml’. In this file, remove <ui:define> sections wht ‘top’ and ‘left’ name attributes. These sections are inherited from the template. Replace <ui:define> section with ‘content’ name such that it looks like: -<ui:define name="content"> - <h2>Reservation Confirmed</h2> - <h:form> - Movie name: #{booking.movieName}<p/> - Starts at: #{booking.startTime}<p/> - Theater: #{booking.theater}<p/> - <h:commandButton id="home" value="home" action="goHome" /><p/> - </h:form> -</ui:define> +<ui:composition template="../WEB-INF/template.xhtml"> + <ui:define name="content"> + <h2>Reservation Confirmed</h2> + <h:form> + Movie name: #{booking.movieName}<p/> + Starts at: #{booking.startTime}<p/> + Theater: #{booking.theater}<p/> + <h:commandButton id="home" value="home" action="goHome" /><p/> + </h:form> + </ui:define> +</ui:composition> + This code displays the movie name, show timings, and the selected theater. Right-click on the yellow bulb to fix namespace prefix/URI mapping for ‘h:’. @@ -2949,6 +3046,7 @@ informed that the views in this directory are to be treated as view nodes in a flow. This can be done declaratively by adding ‘booking/booking-flow.xml’ or programmatically by having a class with a method with the following annotations: @Produces @FlowDefinition + This lab takes the declarative approach. Right-click on ‘Web Pages/booking’ folder, select ‘New’, ‘Other’, ‘XML’, ‘XML Document’, give the name as ‘booking-flow’, click on ‘Next>’, take @@ -2966,6 +3064,7 @@ the default of ‘Well-formed Document’, and click on ‘Finish </flow-return> </flow-definition> </faces-config> + This defines the flow graph. It uses the parent element used in a standard faces-config.xml but defines a <flow-definition> inside it. <flow-return> defines a return node in a flow graph. <from-outcome> @@ -2976,8 +3075,10 @@ return to. In this case, the navigation returns to the home page. Finally, invoke the flow by editing ‘WEB-INF/template.xhtml’ and changing: <h:commandLink action="item1">Item 1</h:commandLink> + to <h:commandLink action="booking">Book a movie</h:commandLink> + commandLink renders an HTML anchor tag that behaves like a form submit button. The action attribute points to the directory where all views for the flow are stored. This directory already contains ‘booking-flow.xml’ @@ -3046,6 +3147,7 @@ notice how the values in the bean are preserved. Click on ‘home’ takes to the main application page. + Conclusion @@ -3065,6 +3167,7 @@ and demonstrated the following features of the platform: Default JMSConnectionFactory + Java API for WebSocket 1.0 @@ -3076,6 +3179,7 @@ and demonstrated the following features of the platform: JavaScript client + Batch Applications for the Java Platform 1.0 @@ -3087,6 +3191,7 @@ and demonstrated the following features of the platform: Exception handling + Java API for JSON Processing 1.0 @@ -3098,6 +3203,7 @@ and demonstrated the following features of the platform: Streaming API for consuming JSON + Java API for RESTful Web Services 2.0 @@ -3109,6 +3215,7 @@ and demonstrated the following features of the platform: Custom Entity Providers + Java Message Service 2.0 @@ -3123,6 +3230,7 @@ and demonstrated the following features of the platform: Synchronous message send and receive + Contexts and Dependency Injection 1.1 @@ -3134,6 +3242,7 @@ and demonstrated the following features of the platform: Injection of beans + JavaServer Faces 2.2 @@ -3142,6 +3251,7 @@ and demonstrated the following features of the platform: Faces Flow + Bean Validation 1.1 @@ -3150,6 +3260,7 @@ and demonstrated the following features of the platform: Integration with JavaServer Faces + Java Transaction API 1.2 @@ -3158,6 +3269,7 @@ and demonstrated the following features of the platform: @Transactional + Java Persistence API 2.1 @@ -3166,8 +3278,10 @@ and demonstrated the following features of the platform: Schema generation properties + + Hopefully this has raised your interest enough in trying out Java EE 7 applications using WildFly 8. Send us feedback or file issues at http://github.com/javaee-samples/javaee7-hol. @@ -3253,7 +3367,7 @@ node, and select Completed Solutions -The completed solution can be downloaded from javaee7-hol. +The completed solution for this lab can be downloaded from javaee7-hol. TODO @@ -3268,6 +3382,7 @@ node, and select WebSocket Java Client + Disable errors in persistence.xml @@ -3279,47 +3394,30 @@ node, and select Change logging to use java.util.Logging. + Revision History -Added IntelliJ IDEA specific instructions. (Jan 22, 2014) +Cleaned up NetBeans instructions and some other typos from DevoxxUK (Jun 25, 2014) -Added macros to generate WildFly and GlassFish-server specific instructions. Also enabled IntelliJ and Eclipse specific macros. (Jan 10, 2014) +Added IntelliJ IDEA specific instructions (Jan 22, 2014) + + +Added macros to generate WildFly and GlassFish-server specific instructions. Also enabled IntelliJ and Eclipse specific macros (Jan 10, 2014) Moving the source document from Pages to AsciiDoc (Dec 3, 2013) + Appendix
    Configure WildFly 8 in NetBeans -
    -Configure Update Center - - -If you are using NetBeans development build then skip this section and go to . Otherwise in NetBeans, click on ‘Tools’, ‘Plugins’, ‘Settings’, and click on ‘Add’. - - -Specify the name as “Dev Update Center” and the URL as “http://deadlock.netbeans.org/job/nbms-and-javadoc/lastStableBuild/artifact/nbbuild/nbms/updates.xml.gz”. -
    -NetBeans Update Center - - - - - 16 netbeans add dev update center - -
    - -and click on ‘OK’. -
    -
    -
    Install WildFly plugin @@ -3338,9 +3436,10 @@ node, and select The exact plugin version and the date may be different. -Click on ‘Install’ button, ‘Next >’, accept the license agreement by clicking on the checkbox, and click on ‘Install’ button to install the plugin. Click on ‘Finish’ to restart the IDE and complete installation. +Click the Install button, then Next >, accept the license agreement by clicking on the checkbox, then click the Install button to install the plugin. Click the Finish button to restart the IDE and complete installation. +
    Configure WildFly 8 @@ -3363,7 +3462,7 @@ node, and select Select ‘WildFly Application Server’ in the Add Server Instance wizard, set the -name to ‘WildFly 8’ and click ‘Next >’. +name to ‘WildFly 8’ and click Next >.
    Add WildFly instance to NetBeans @@ -3376,8 +3475,8 @@ name to ‘WildFly 8’ and click ‘Next >’. -Click on ‘Browse’ for ‘Server Location’ and select the directory that got created -when WildFly archive was unzipped. Click on ‘Browse’ for ‘Server Configuration’ and +Click on Browse… for ‘Server Location’ and select the directory that got created +when WildFly archive was unzipped. Click on Browse… for ‘Server Configuration’ and select the ‘standalone/configuration/standalone-full.xml’ file in the unzipped WildFly archive.
    @@ -3390,7 +3489,7 @@ archive.
    -Click on ‘Next’ and then ‘Finish’. The ‘Services’ should show the WildFly instance. +Click on Next and then Finish. The ‘Services’ should show the WildFly instance.
    WildFly instance in NetBeans Services tab @@ -3403,6 +3502,7 @@ archive. +
    @@ -3426,12 +3526,13 @@ archive. +
    Specify the JDK First of all, you should specify the JDK that you are going to use. In IntelliJ IDEA, this is done in the Project Structure dialog: -Start IntelliJ IDEA. If, as a result, a project opens, close the project (File | Close Project). +Start IntelliJ IDEA. If, as a result, a project opens, close the project (File Close Project). On the Welcome screen, under Quick Start, click Configure. @@ -3450,7 +3551,12 @@ archive. Under Configure, click Project Defaults, and then, under Project Defaults, click Project Structure. -In the left-hand pane of the Project Structure dialog, under Platform Settings, select SDKs. Click image::images/i13-plus-icon.png[title="Plus icon in IntelliJ IDEA"] and select JDK. +In the left-hand pane of the Project Structure dialog, under Platform Settings, select SDKs. Click + + + + i13-plus-icon + and select JDK.
    Add JDK in IntelliJ IDEA @@ -3463,7 +3569,7 @@ archive. -In the Select Home Directory for JDK dialog, select the folder in which the JDK that you are going to use is installed, and click OK. +In the Select Home Directory for JDK dialog, select the folder in which the JDK that you are going to use is installed, and click OK.
    JDK home in IntelliJ IDEA @@ -3476,7 +3582,7 @@ archive. -In the Project Structure dialog, click Apply. +In the Project Structure dialog, click Apply.
    JDK defined in IntelliJ IDEA @@ -3503,22 +3609,33 @@ archive. -Click OK. +Click OK. +
    Define WildFly -Defining an application server in IntelliJ IDEA, normally, is just telling the IDE where the server is installed. The servers are defined in the Settings dialog. (On Mac OS, this dialog is called Preferences.) +Defining an application server in IntelliJ IDEA, normally, is just telling the IDE where the server is installed. The servers are defined in the Settings dialog. (On OSX, this dialog is called Preferences.) -On the Welcome screen, to the left of Project Defaults, click Back image::images/i13-back-icon.png[title="Back icon in IntelliJ IDEA"]. +On the Welcome screen, to the left of Project Defaults, click Back + + + + i13-back-icon +. Under Configure, click Settings. -In the left-hand pane of the Settings (Preferences) dialog, under IDE Settings, select Application Servers. On the Application Servers page, click image::images/i13-plus-icon.png[title="Plus icon in IntelliJ IDEA"] and select JBoss Server. (WildFly is a server from the "JBoss family".) +In the left-hand pane of the Settings (Preferences) dialog, under IDE Settings, select Application Servers. On the Application Servers page, click + + + + i13-plus-icon + and select JBoss Server. (WildFly is a server from the "JBoss family".)
    Add WildFly in IntelliJ IDEA @@ -3531,7 +3648,12 @@ archive. -In the JBoss Server dialog, click image::images/i13-ellipsis-button.png[title="Ellipsis button in IntelliJ IDEA"] to the right of the JBoss Home field. +In the JBoss Server dialog, click + + + + i13-ellipsis-button + to the right of the JBoss Home field.
    WildFly server dialog in IntelliJ IDEA @@ -3544,7 +3666,7 @@ archive. -In the JBoss Home Directory dialog, select the folder in which you have the WildFly server installed, and click OK. +In the JBoss Home Directory dialog, select the folder in which you have the WildFly server installed, and click OK.
    WildFly home in IntelliJ IDEA @@ -3570,7 +3692,7 @@ archive. -In the Settings (Preferences) dialog, click OK. +In the Settings (Preferences) dialog, click OK.
    WildFly defined in IntelliJ IDEA @@ -3583,13 +3705,19 @@ archive. +
    Create a project The sample application is supplied as a Maven project with an associated pom.xml file that contains all the necessary project definitions. The corresponding IntelliJ IDEA project in such a case can be created by simply "opening" the pom.xml file. (Obviously, this isn’t the only way to create projects in IDEA. You can create projects for existing collections of source files, import Eclipse and Flash Builder projects, and Gradle build scripts. Finally, you can create projects from scratch.) -On the Welcome screen, to the left of Configure, click Back image::images/i13-back-icon.png[title="Back icon in IntelliJ IDEA"]. +On the Welcome screen, to the left of Configure, click Back + + + + i13-back-icon +. Under Quick Start, click Open Project. @@ -3605,7 +3733,7 @@ archive. -In the Open Project dialog, select the pom.xml file associated with the sample application, and click OK. +In the Open Project dialog, select the pom.xml file associated with the sample application, and click OK.
    Select pom in IntelliJ IDEA @@ -3629,7 +3757,12 @@ archive. -Click Configure in the message box. (If by now the message has disappeared, click image::images/i13-exclamation-mark-icon.png[title="Mark icon in IntelliJ IDEA"] on the Status bar. +Click Configure in the message box. (If by now the message has disappeared, click + + + + i13-exclamation-mark-icon + on the Status bar.
    JPA detected in status bar in IntelliJ IDEA @@ -3653,7 +3786,7 @@ archive. -In the Setup Frameworks dialog, just click OK. (By doing so you confirm that the file persistence.xml found in the project belongs to the JPA framework.) +In the Setup Frameworks dialog, just click OK. (By doing so you confirm that the file persistence.xml found in the project belongs to the JPA framework.)
    Setup frameworks in IntelliJ IDEA @@ -3677,13 +3810,14 @@ archive. +
    Create a run/debug configuration Applications in IntelliJ IDEA are run and debugged according to what is called run/debug configurations. Now we are going to create the configuration for running and debugging the sample application in the context of WildFly. -In the main menu, select Run | Edit Configurations. +In the main menu, select Run Edit Configurations….
    Edit configurations in IntelliJ IDEA @@ -3696,7 +3830,12 @@ archive. -In the Run/Debug Configurations dialog, click image::images/i13-plus-icon.png[title="Plus icon in IntelliJ IDEA"], select JBoss Server, and then select Local. +In the Run/Debug Configurations dialog, click + + + + i13-plus-icon +, select JBoss Server, and then select Local.
    WildFly configuration in IntelliJ IDEA @@ -3713,7 +3852,7 @@ archive. Change the name of the run/debug configuration to WildFly8 (optional). -In the lower part of the dialog, within the line Warning: No artifacts marked for deployment, click Fix and select movieplex7:war exploded. (Artifacts in IntelliJ IDEA are deployment-ready project outputs and also the configurations according to which such outputs are produced. In our case, there are two configurations for the sample application (movieplex7:war and movieplex7:war exploded). Both configurations represent a format suitable for deployment onto a Java EE 7-enabled application server. movieplex7:war corresponds to a Web archive (WAR). movieplex7:war exploded corresponds to the sample application directory structure (a decompressed archive). The second of the formats is more suitable at the development stage because manipulations with it are faster.) +In the lower part of the dialog, within the line Warning: No artifacts marked for deployment, click Fix and select movieplex7:war exploded. (Artifacts in IntelliJ IDEA are deployment-ready project outputs and also the configurations according to which such outputs are produced. In our case, there are two configurations for the sample application (movieplex7:war and movieplex7:war exploded). Both configurations represent a format suitable for deployment onto a Java EE 7-enabled application server. movieplex7:war corresponds to a Web archive (WAR). movieplex7:war exploded corresponds to the sample application directory structure (a decompressed archive). The second of the formats is more suitable at the development stage because manipulations with it are faster.)
    Fixing deployment warning in IntelliJ IDEA @@ -3726,7 +3865,7 @@ archive. -Within the line Error: Artifact 'movieplex7: exploded' has invalid extension, click Fix. +Within the line Error: Artifact 'movieplex7: exploded' has invalid extension, click Fix.
    Invalid extension error message in IntelliJ IDEA @@ -3739,7 +3878,7 @@ archive. -In the Project Structure dialog, add .war at the end of the output directory path, and click OK. (For the servers of the JBoss family, the application root directory has to have .war at the end.) +In the Project Structure dialog, add .war at the end of the output directory path, and click OK. (For the servers of the JBoss family, the application root directory has to have .war at the end.)
    Extension error fix in IntelliJ IDEA @@ -3752,7 +3891,7 @@ archive. -In the Run/Debug Configurations dialog, switch to the Server tab. In the field for the application starting page URL, replace http://localhost:8080/movieplex7-1/ with http://localhost:8080/movieplex7-1.0-SNAPSHOT/ and click OK. +In the Run/Debug Configurations dialog, switch to the Server tab. In the field for the application starting page URL, replace http://localhost:8080/movieplex7-1/ with http://localhost:8080/movieplex7-1.0-SNAPSHOT/ and click OK.
    Fixing application URL in IntelliJ IDEA @@ -3765,11 +3904,17 @@ archive. + The Application Servers tool window opens in the lower part of the workspace. Shown in this window are the server run/debug configuration and the associated deployment artifact. Now you are ready to run the application.
    Run the application -In the Application Servers tool window, select the server run/debug configuration (WildFly8 [local]) and click Run image::images/i13-run-icon.png[title="Run icon in IntelliJ IDEA"]. +In the Application Servers tool window, select the server run/debug configuration (WildFly8 [local]) and click Run + + + + i13-run-icon +.
    Run WildFly in IntelliJ IDEA diff --git a/solution/movieplex7-1.0-SNAPSHOT.war b/solution/movieplex7-1.0-SNAPSHOT.war new file mode 100644 index 0000000..6ca561e Binary files /dev/null and b/solution/movieplex7-1.0-SNAPSHOT.war differ diff --git a/solution/movieplex7-solution.zip b/solution/movieplex7-solution.zip index 2a6a75e..0b33108 100644 Binary files a/solution/movieplex7-solution.zip and b/solution/movieplex7-solution.zip differ diff --git a/solution/movieplex7/pom.xml b/solution/movieplex7/pom.xml index 1140a79..ba0863e 100644 --- a/solution/movieplex7/pom.xml +++ b/solution/movieplex7/pom.xml @@ -37,6 +37,11 @@ false + + org.wildfly.plugins + wildfly-maven-plugin + 1.0.2.Final + diff --git a/solution/movieplex7/src/main/java/org/javaee7/movieplex7/booking/Booking.java b/solution/movieplex7/src/main/java/org/javaee7/movieplex7/booking/Booking.java index 42330d4..7d8d145 100644 --- a/solution/movieplex7/src/main/java/org/javaee7/movieplex7/booking/Booking.java +++ b/solution/movieplex7/src/main/java/org/javaee7/movieplex7/booking/Booking.java @@ -39,6 +39,7 @@ */ package org.javaee7.movieplex7.booking; +import java.io.Serializable; import java.util.List; import java.util.StringTokenizer; import javax.faces.flow.FlowScoped; @@ -54,7 +55,7 @@ */ @Named @FlowScoped("booking") -public class Booking { +public class Booking implements Serializable { int movieId; String startTime; diff --git a/starting-template/movieplex7-starting-template.zip b/starting-template/movieplex7-starting-template.zip index cfb3fe9..52a5133 100644 Binary files a/starting-template/movieplex7-starting-template.zip and b/starting-template/movieplex7-starting-template.zip differ diff --git a/starting-template/movieplex7/pom.xml b/starting-template/movieplex7/pom.xml index 2044289..286607b 100644 --- a/starting-template/movieplex7/pom.xml +++ b/starting-template/movieplex7/pom.xml @@ -37,6 +37,11 @@ false + + org.wildfly.plugins + wildfly-maven-plugin + 1.0.2.Final + diff --git a/starting-template/movieplex7/src/main/webapp/WEB-INF/web.xml b/starting-template/movieplex7/src/main/webapp/WEB-INF/web.xml index cc2927d..7412f94 100644 --- a/starting-template/movieplex7/src/main/webapp/WEB-INF/web.xml +++ b/starting-template/movieplex7/src/main/webapp/WEB-INF/web.xml @@ -40,7 +40,7 @@ * holder. */ --> - + javax.faces.PROJECT_STAGE Development