Getting Started Developing Applications Guide -...

295
JBoss AS 7.1 JBoss Community Documentation Page of 1 295 Getting Started Developing Applications Guide Exported from at 2012-07-06 10:35:03 EDT JBoss Community Documentation Editor Copyright 2012 JBoss Community contributors.

Transcript of Getting Started Developing Applications Guide -...

JBoss AS 7.1

JBoss Community Documentation Page of 1 295

Getting Started

Developing Applications

Guide

Exported from at 2012-07-06 10:35:03 EDTJBoss Community Documentation Editor

Copyright 2012 JBoss Community contributors.

JBoss AS 7.1

JBoss Community Documentation Page of 2 295

Table of Contents

1 Introduction ________________________________________________________________________ 6

1.1 Downloading the quickstarts _______________________________________________________ 7

2 Getting started with JBoss AS __________________________________________________________ 8

2.1 Installing and starting JBoss AS on Linux, Unix or Mac OS X _____________________________ 8

2.2 Installing and starting JBoss AS on Windows __________________________________________ 9

2.3 Starting JBoss AS from Eclipse with JBoss Tools ______________________________________ 10

2.4 Importing the quickstarts into Eclipse _______________________________________________ 19

2.5 Managing JBoss Application Server ________________________________________________ 24

3 CDI + Servlet: Helloworld quickstart ____________________________________________________ 25

3.1 Deploying the Helloworld example using Eclipse ______________________________________ 25

3.2 The helloworld example in depth ___________________________________________________ 27

4 CDI + JSF: Numberguess quickstart ____________________________________________________ 30

4.1 Deploying the Numberguess example using Eclipse ___________________________________ 30

4.2 The numberguess example in depth ________________________________________________ 32

5 CDI + JPA + EJB + JTA + JSF: Login quickstart ___________________________________________ 41

5.1 Deploying the Login example using Eclipse __________________________________________ 41

5.2 The login example in depth _______________________________________________________ 43

6 CDI + JSF + EJB + JTA + Bean Validation + JAX-RS + Arquillian: Kitchensink quickstart ___________ 49

6.1 Deploying the Kitchensink example using Eclipse _____________________________________ 49

6.2 The kitchensink example in depth __________________________________________________ 51

6.2.1 Arquillian _______________________________________________________________ 64

7 OSGi: Helloworld OSGi quickstart ______________________________________________________ 82

7.1 The Helloworld OSGi example in depth _____________________________________________ 83

7.2 Creating a new OSGi bundle using Eclipse __________________________________________ 86

8 EJB: Invocation from remote clients using JNDI: ejb-remote quickstart _________________________ 92

8.1 Deploying your EJBs on the server side: ____________________________________________ 92

8.2 Writing a remote client application for accessing and invoking the EJBs deployed on the server _ 94

8.3 Setting up EJB client context properties ____________________________________________ 100

8.4 Using a different file for setting up EJB client context __________________________________ 103

8.5 Setting up the client classpath with the jars that are required to run the client application ______ 103

8.6 Summary ____________________________________________________________________ 103

9 Creating your own application ________________________________________________________ 105

10 More Resources __________________________________________________________________ 113

11 All JBoss AS 7 documentation _______________________________________________________ 114

12 Introduction ______________________________________________________________________ 115

12.1 Downloading the quickstarts _____________________________________________________ 116

JBoss AS 7.1

JBoss Community Documentation Page of 3 295

13 Getting started with JBoss AS ________________________________________________________ 117

13.1 Installing and starting JBoss AS on Linux, Unix or Mac OS X ___________________________ 117

13.2 Installing and starting JBoss AS on Windows ________________________________________ 118

13.3 Starting JBoss AS from Eclipse with JBoss Tools _____________________________________ 119

13.4 Importing the quickstarts into Eclipse ______________________________________________ 128

13.5 Managing JBoss Application Server _______________________________________________ 133

13.6 Installing and starting JBoss AS on Linux, Unix or Mac OS X ___________________________ 133

13.7 Installing and starting JBoss AS on Windows ________________________________________ 134

13.8 Starting JBoss AS from Eclipse with JBoss Tools _____________________________________ 135

13.9 Importing the quickstarts into Eclipse ______________________________________________ 144

13.10Managing JBoss Application Server _______________________________________________ 149

14 Helloworld quickstart _______________________________________________________________ 150

14.1 Deploying the Helloworld example using Eclipse _____________________________________ 150

14.2 The helloworld example in depth __________________________________________________ 152

14.3 Deploying the Helloworld example using Eclipse _____________________________________ 154

14.4 The helloworld example in depth __________________________________________________ 156

15 Numberguess quickstart ____________________________________________________________ 159

15.1 Deploying the Numberguess example using Eclipse __________________________________ 159

15.2 The numberguess example in depth _______________________________________________ 161

15.3 Deploying the Numberguess example using Eclipse __________________________________ 169

15.4 The numberguess example in depth _______________________________________________ 171

16 Login quickstart ___________________________________________________________________ 180

16.1 Deploying the Login example using Eclipse _________________________________________ 180

16.2 The login example in depth ______________________________________________________ 182

16.3 Deploying the Login example using Eclipse _________________________________________ 187

16.4 The login example in depth ______________________________________________________ 189

17 Kitchensink quickstart ______________________________________________________________ 195

17.1 Deploying the Kitchensink example using Eclipse ____________________________________ 195

17.2 The kitchensink example in depth _________________________________________________ 197

17.2.1 Arquillian ______________________________________________________________ 210

17.3 Deploying the Kitchensink example using Eclipse ____________________________________ 227

17.4 The kitchensink example in depth _________________________________________________ 228

17.4.1 Arquillian ______________________________________________________________ 241

18 Helloworld OSGi quickstart __________________________________________________________ 259

18.1 The Helloworld OSGi example in depth ____________________________________________ 260

18.2 Creating a new OSGi bundle using Eclipse _________________________________________ 263

18.3 The helloworld-osgi example in depth ______________________________________________ 268

18.4 Creating a new OSGi Bundle using Eclipse _________________________________________ 271

19 Creating your own application ________________________________________________________ 277

19.1 Creating your own application using Eclipse _________________________________________ 284

JBoss AS 7.1

JBoss Community Documentation Page of 4 295

20 More Resources __________________________________________________________________ 285

20.1 Getting Started Developing Applications Presentation & Demo __________________________ 285

20.1.1 Introduction ____________________________________________________________ 285

20.1.2 Prerequisites for using the script ____________________________________________ 286

20.1.3 Import examples into Eclipse and set up JBoss AS ______________________________ 286

20.1.4 The Helloworld Quickstart _________________________________________________ 286

20.1.5 The numberguess quickstart _______________________________________________ 290

20.1.6 The login quickstart ______________________________________________________ 292

20.1.7 The kitchensink quickstart _________________________________________________ 294

JBoss AS 7.1

JBoss Community Documentation Page of 5 295

Introduction

Downloading the quickstarts

Getting started with JBoss AS

Installing and starting JBoss AS on Linux, Unix or Mac OS X

Installing and starting JBoss AS on Windows

Starting JBoss AS from Eclipse with JBoss Tools

Importing the quickstarts into Eclipse

Managing JBoss Application Server

CDI + Servlet: Helloworld quickstart

Deploying the Helloworld example using Eclipse

The helloworld example in depth

CDI + JSF: Numberguess quickstart

Deploying the Numberguess example using Eclipse

The numberguess example in depth

CDI + JPA + EJB + JTA + JSF: Login quickstart

Deploying the Login example using Eclipse

The login example in depth

CDI + JSF + EJB + JTA + Bean Validation + JAX-RS + Arquillian: Kitchensink quickstart

Deploying the Kitchensink example using Eclipse

The kitchensink example in depth

Arquillian

OSGi: Helloworld OSGi quickstart

The Helloworld OSGi example in depth

Creating a new OSGi bundle using Eclipse

EJB: Invocation from remote clients using JNDI: ejb-remote quickstart

Deploying your EJBs on the server side:

Writing a remote client application for accessing and invoking the EJBs deployed on the server

Setting up EJB client context properties

Using a different file for setting up EJB client context

Setting up the client classpath with the jars that are required to run the client application

Summary

Creating your own application

More Resources

All JBoss AS 7 documentation

JBoss AS 7.1

JBoss Community Documentation Page of 6 295

1 IntroductionThis guide will walk you through installing and starting up JBoss Application Server 7. It will then introduce

key features of the Java EE 6 (Web Profile) programming model, of which JBoss AS 7 is a certified

implementation.

Java EE 6

The Java EE 6 platform offers developers the ability to write distributed, transactional and portable

applications quickly and easily. We class applications that require these capabilities "enterprise

applications". These applications must be fast, secure and reliable.

Java EE has always offered strong messaging (JMS), transactional (JTA) and resource (JCA)

capabilities as well as exposing web services via SOAP (JAX-WS). Java EE 5 started a radical shift

for the programming model, offering a powerful, declarative and lightweight object-relational

mapper (JPA) and annotation-driven, lightweight access to enterprise services (EJB 3). Java EE 6

added a type-safe, loosely coupled programming model (CDI), declarative validation of constraints

(Bean Validation) and RESTful web services (JAX-RS) to produce a complete, modern

development environment.

JBoss AS 7 departs from the familiar structure of previous JBoss AS versions, so we recommend all

developers follow the steps in to install and start up the application server forGetting started with JBoss AS

the first time.

JBoss AS 7 comes with a series of quickstarts aimed to get you up to writing applications with minimal fuss.

We recommend that you work through the quickstarts in the order they are presented in this guide, however

if you have previous experience with Java EE 6, you may wish to skip some or all of the quickstarts:

Core  

Helloworld

quickstart

If you have previously developed applications using technologies such as JSF or Wicket,

and EJB or Spring, you may wish to skip this quickstart.

Numberguess

quickstart

If you have previously developed applications using technologies such as JSF or Wicket,

EJB or Spring, and JPA or Hibernate you may wish to skip this quickstart.

Login

quickstart

If you are a Java EE wizard you may wish to skip this quickstart.

Kitchensink

quickstart

A great starting point for your project.

Optional  

JBoss AS 7.1

JBoss Community Documentation Page of 7 295

Helloworld

OSGi

quickstart

If you want to get started with OSGi in JBoss AS, check out this quickstart.

1.1 Downloading the quickstarts

The quickstarts are distributed alongside JBoss AS (in a separate zip from the runtime) and are available for

download from . Make sure you download the latest zip!the JBoss AS download page

JBoss AS 7.1

JBoss Community Documentation Page of 8 295

2 Getting started with JBoss ASTo run the examples with the provided build scripts, you'll need the following:

Java 1.6, to run JBoss AS and Maven

Maven 3, to build and deploy the examples

the JBoss AS 7 distribution zip

the JBoss AS 7 quickstarts zip

If you already have any of these pieces of software, there is no need to install them again!

Choose your Java runtime, and follow their installation instructions. For example, you could choose one of:

OpenJDK

Oracle Java SE

Oracle JRockit

Follow the official Maven installation guide if you don't already have Maven 3 installed. You can check which

version of Maven you have installed (if any) by running . If you see a version newer thanmvn --version

3.0.0, you are ready to go.

You can also deploy the examples using your favorite IDE. We provide instructions for using Eclipse only.

Now, download JBoss AS 7 from the .JBoss AS download page

JBoss AS 7 offers the ability to manage multiple AS instances from a single control point. A

collection of such servers are referred to as members of a "domain", with a single Domain

Controller process acting as the management control point. Domains can span multiple physical (or

virtual) machines, with all AS instances on a given host under the control of a Host Controller

process. The Host Controllers interact with the Domain Controller to control the lifecycle of the AS

instances running on that host and to assist the Domain Controller in managing them.

JBoss AS 7 also offers a standalone mode, which is perfect for a single server. We use this

throughout the quickstart examples.

2.1 Installing and starting JBoss AS on Linux, Unix or

Mac OS X

First, let's verify that verify that both Java and Maven are correctly installed. In a console, type:

java -version

JBoss AS 7.1

JBoss Community Documentation Page of 9 295

You should see a version string (at least ) printed. If not, contact your provider of Java for assistance.1.6.0

Next, type:

mvn --version

You should see a version string (at lest ) printed. If not, contact the Maven community for assistance.3.0.0

Next, we need to choose a location for JBoss AS to live. By default, JBoss AS 7 will be extracted into

(where 7.x.x.x matches the version you downloaded):jboss-7.x.x.x

unzip jboss-7.x.x.x.zip

Now, let's start JBoss AS in standalone mode:

jboss-7.x.x.x/bin/standalone.sh

If you want to stop JBoss AS, simply press whilst the terminal has focus.Crtl-C

That's it, JBoss AS is installed and running! Visit to check the server has startedhttp://localhost:8080/

properly.

You can find the server log for standalone instances in

. The Getting Started Guide covers more onjboss-7.x.x.x/standalone/log/server.log

configuring logging.

2.2 Installing and starting JBoss AS on Windows

First, let's verify that verify that both Java and Maven are correctly installed. In a Command Prompt, type:

java -version

You should see a version string (at least ) printed. If not, contact your provider of Java for assistance.1.6.0

Next, type:

mvn --version

You should see a version string (at lest ) printed. If not, contact the Maven community for assistance.3.0.0

JBoss AS 7.1

JBoss Community Documentation Page of 10 295

Next, we need to choose a location for JBoss AS to live. By default, JBoss AS 7 will be extracted into

(where 7.x.x.x matches the version you downloaded). Unzip JBoss AS using your tool ofjboss-7.x.x.x

choice.

Finally, let's start JBoss AS in standalone mode. Locate your JBoss AS installation and run

located in .standalone.bat bin

If you want to stop JBoss AS, simply press whilst the terminal has focus.Crtl-C

That's it, JBoss AS is installed and running! Visit to check the server has startedhttp://localhost:8080/

properly.

You can find the server log for standalone instances in

. The Getting Started Guide covers more onjboss-7.x.x.x/standalone/log/server.log

configuring logging.

2.3 Starting JBoss AS from Eclipse with JBoss Tools

You may choose to use Eclipse rather than the command line to run JBoss AS, and to deploy the examples.

If you don't wish to use Eclipse, you should skip this section.

In order to use JBoss AS from Eclipse, you must first install JBoss AS for your operating system as

described in or Installing and starting JBoss AS on Linux, Unix or Mac OS X Installing and starting

.JBoss AS on Windows

In order use JBoss AS from Eclipse, you'll need Eclipse Indigo (Eclipse 3.7) and JBoss Tools 3.3 M2 or

newer. If you want to run the quickstarts from Eclipse, you will also need m2eclipse. You can find

instructions for installing Eclipse, m2eclipse and JBoss Tools on the . Make sure you installJBoss Tools Site

the and features.Maven Support Web and Java EE Development

Having successfully installed and started Eclipse, we need to add our JBoss AS instance to it. First, navigate

to :File -> New -> Other

JBoss AS 7.1

JBoss Community Documentation Page of 11 295

Now, locate the New Server Wizard:

JBoss AS 7.1

JBoss Community Documentation Page of 12 295

And choose JBoss AS 7.0:

JBoss AS 7.1

JBoss Community Documentation Page of 13 295

Hit , and locate the JBoss AS 7 installation by clicking on :Next > Browse ...

JBoss AS 7.1

JBoss Community Documentation Page of 14 295

Now, choose the JBoss AS 7 installation directory:

JBoss AS 7.1

JBoss Community Documentation Page of 15 295

Assuming you selected a valid installation, Eclipse should now allow you to hit :Finish

JBoss AS 7.1

JBoss Community Documentation Page of 16 295

Now, let's start JBoss AS from Eclipse. If you previously started JBoss AS from the command line, you

should stop it there first.

First, we need to make sure the tab is on view. Open the Server Window -> Show View -> Other...

dialog:

JBoss AS 7.1

JBoss Community Documentation Page of 17 295

And select the view:Server

JBoss AS 7.1

JBoss Community Documentation Page of 18 295

You should see the appear with the JBoss AS server:Server View

Now, we can start the server. Right click on the server in the view, and select :Server Start

JBoss AS 7.1

JBoss Community Documentation Page of 19 295

If you want to debug your application, you can simply select rather than . This willDebug Start

start the server in debug mode, and automatically attach the Eclipse debugger.

You'll see the server output in the :Console

That's it, we now have the server up and running in Eclipse!

2.4 Importing the quickstarts into Eclipse

In order to import the quickstarts into Eclipse, you will need m2eclipse installed. You can find instructions for

installing Eclipse, m2eclipse and JBoss Tools on the JBoss AS site.

JBoss AS 7.1

JBoss Community Documentation Page of 20 295

First, choose :File -> Import...

Select :Existing Maven Projects

JBoss AS 7.1

JBoss Community Documentation Page of 21 295

Click on , and navigate to the directory:Browse quickstarts/

JBoss AS 7.1

JBoss Community Documentation Page of 22 295

Finally, make sure all 4 quickstarts are found and selected, and click :Finish

JBoss AS 7.1

JBoss Community Documentation Page of 23 295

Eclipse should now successfully import 4 projects:

JBoss AS 7.1

JBoss Community Documentation Page of 24 295

It will take a short time to import the projects, as Maven needs to download the project's dependencies from

remote repositories.

2.5 Managing JBoss Application Server

Here we will quickly outline how you can access both the command line interface and the web management

interface for managing JBoss AS. Detailed information for both can be found in the .Admin Guide

When the server is running, the web management interface can be accessed at http://localhost:9990/console

. You can use the web management interface to create datasources, manage deployments and configure

the server.

JBoss AS also comes with a command line interface. To run it on Linux, Unix or Mac, execute:

jboss-7.x.x.x/bin/jboss-admin.sh --connect

Or, on Windows:

jboss-7.x.x.x/bin/jboss-admin.bat --connect

Once started, type to discover the commands available to you.help

Throughout this guide we use the maven plugin to deploy and undeploy applications. This pluginjboss-as

uses the JBoss AS Native Java Detyped Management API to communicate with the server. The Detyped

API is used by management tools to control an entire domain of servers, and exposes only a small number

of types, allowing for backwards and forwards compatibility.

JBoss AS 7.1

JBoss Community Documentation Page of 25 295

3 CDI + Servlet: Helloworld quickstartThis quickstart shows you how to deploy a simple servlet to JBoss AS. The business logic is encapsulated in

a service, which is provided as a CDI bean, and injected into the Servlet.

Contexts and Dependency Injection for Java EE

CDI is a new specification in Java EE 6, inspired by JBoss Seam and Google Guice, and also

drawing on lessons learned from frameworks such as Spring. It allows application developers to

concentrate on developing their application logic by providing the ability to wire services together,

and abstract out orthogonal concerns, all in a type safe manner.

Switch to the directory and instruct Maven to build and deploy the application:quickstarts/helloworld

mvn package jboss-as:deploy

The quickstart uses a Maven plugin to deploy the application. The plugin requires JBoss AS to be running

(you can find out how to start the server in or Installing and starting JBoss AS on Linux, Unix or Mac OS X

).Installing and starting JBoss AS on Windows

Now, check if the application has deployed properly by clicking . Ifhttp://localhost:8080/jboss-as-helloworld

you see a "Hello World" message it's all working!

Should you wish to undeploy the quickstart, or redeploy after making some changes, it's pretty

easy:

- deploy any changes to the application to the application servermvn jboss-as:deploy

- undeploy the example from JBoss ASmvn jboss-as:undeploy

It's time to pull the covers back and dive into the internals of the example application.

3.1 Deploying the Helloworld example using Eclipse

You may choose to deploy the example using Eclipse. You'll need to have JBoss AS started in Eclipse (as

described in ) and to have imported the quickstarts intoStarting JBoss AS from Eclipse with JBoss Tools

Eclipse (as described in ).Importing the quickstarts into Eclipse

With the quickstarts imported, you can deploy the example by right clicking on the jboss-as-helloworld

project, and choosing :Run As -> Run On Server

JBoss AS 7.1

JBoss Community Documentation Page of 26 295

Make sure the JBoss AS server is selected, and hit :Finish

JBoss AS 7.1

JBoss Community Documentation Page of 27 295

You should see JBoss AS start up (unless you already started it in Starting JBoss AS from Eclipse with

) and the application deploy in the Console log:JBoss Tools

3.2 The helloworld example in depth

JBoss AS 7.1

JBoss Community Documentation Page of 28 295

The helloworld is very simple - all it does is print "Hello World" onto a web page.

The helloworld example is comprised a servlet and a CDI bean. We also include an empty file,beans.xml

which tells JBoss AS to look for beans in this application and to activate the CDI. is located in beans.xml

, which can be found in the directory of the example. Also in this directory weWEB-INF src/main/webapp

include which uses a simple meta refresh to send the users browser to the Servlet, which isindex.html

located at .http://localhost:8080/jboss-as-helloworld/HelloWorld

All the configuration files for this example are located in , which can be found in the WEB-INF/

directory of the example.src/main/webapp

Notice that we don't even need a !web.xml

Let's start by taking a look at the servlet:

HelloWorldServlet.java

27. import javax.servlet.http.HttpServletResponse;

28.

29. /**

30. * <p>

31. * A simple servlet taking advantage of features added in 3.0.

32. * </p>

33. *

34. * <p>

35. * The servlet is registered and mapped to /HelloServlet using the {@linkplain WebServlet

36. * @HttpServlet}. The {@link HelloService} is injected by CDI.

37. * </p>

38. *

39. * @author Pete Muir

40. *

41. */

42. @SuppressWarnings("serial")

43. @WebServlet("/HelloWorld")

44. public class HelloWorldServlet extends HttpServlet {

45.

46. static String PAGE_HEADER = "<html><head><title>helloworld</title><body>";

47.

48. static String PAGE_FOOTER = "</body></html>";

49.

50. @Inject

51. HelloService helloService;

52.

53. @Override

54. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws

ServletException, IOException {

55. PrintWriter writer = resp.getWriter();

56. writer.println(PAGE_HEADER);

57. writer.println("<h1>" + helloService.createHelloMessage("World") + "</h1>");

58. writer.println(PAGE_FOOTER);

59. writer.close();

60. }

61.

62. }

JBoss AS 7.1

JBoss Community Documentation Page of 29 295

Line Note

27 If you've used Servlet before, then you'll remember having to use xml to register your servlets.

Fortunately, this is a thing of the past. Now all you need to do is add the annotation,@WebServlet

and provide a mapping to a URL used to access the servlet. Much cleaner!

30-32 Every web page needs to be correctly formed HTML. We've created static Strings to hold the

minimum header and footer to write out.

34,35 We inject the HelloService (a CDI bean) which generates the actual message. This allows to alter

the implementation of at a later date without changing the view layer at allHelloService

(assuming we don't alter the API of ).HelloService

41 We call into the service to generate the message "Hello World", and write it out to the HTTP

request.

The package declaration and imports have been excluded from these listings. The complete listing

is

available in the example source code.

Now we understand how the information is sent to the browser, let's take a look at the service.

HelloService.java

public class HelloService {

String createHelloMessage(String name) {

return "Hello " + name + "!";

}

}

The service is very simple - no registration (XML or annotation) is required!

JBoss AS 7.1

JBoss Community Documentation Page of 30 295

4 CDI + JSF: Numberguess quickstartThis quickstart shows you how to create and deploy a simple application to JBoss AS; the application does

not persist any information. Information is displayed using a JSF view, and business logic is encapsulated in

two CDI beans.

Switch to the directory and instruct Maven to build and deploy thequickstarts/numberguess

application:

mvn package jboss-as:deploy

The quickstart uses a Maven plugin to deploy the application. The plugin requires JBoss AS to be running

(you can find out how to start the server in or Installing and starting JBoss AS on Linux, Unix or Mac OS X

).Installing and starting JBoss AS on Windows

Or you can start the server using an IDE, like Eclipse.

Now, see if you can determine the most efficient approach to pinpoint the random number at the URL

.http://localhost:8080/jboss-as-numberguess

Should you wish to undeploy the quickstart, or redeploy after making some changes, it's pretty

easy:

- deploy any changes to the application to the application servermvn jboss-as:deploy

- undeploy the example from JBoss ASmvn jboss-as:undeploy

It's time to pull the covers back and dive into the internals of the example application.

4.1 Deploying the Numberguess example using Eclipse

You may choose to deploy the example using Eclipse. You'll need to have JBoss AS started in Eclipse (as

described in ) and to have imported the quickstarts intoStarting JBoss AS from Eclipse with JBoss Tools

Eclipse (as described in ).Importing the quickstarts into Eclipse

With the quickstarts imported, you can deploy the example by right clicking on the

project, and choosing :jboss-as-numberguess Run As -> Run On Server

JBoss AS 7.1

JBoss Community Documentation Page of 31 295

Make sure the JBoss AS server is selected, and hit :Finish

JBoss AS 7.1

JBoss Community Documentation Page of 32 295

You should see JBoss AS start up (unless you already started it in Starting JBoss AS from Eclipse with

) and the application deploy in the Console log:JBoss Tools

4.2 The numberguess example in depth

JBoss AS 7.1

JBoss Community Documentation Page of 33 295

In the numberguess application you get 10 attempts to guess a number between 1 and 100. After each

attempt, you're told whether your guess was too high or too low.

The numberguess example is comprised of a number of beans, configuration files and Facelets (JSF) views,

packaged as a war module. Let's start by examining the configuration files.

All the configuration files for this example are located in , which can be found in the WEB-INF/

directory of the example. First, we have the JSF 2.0 version of . Asrc/main/webapp faces-config.xml

standardized version of Facelets is the default view handler in JSF 2.0, so there's really nothing that we have

to configure. JBoss AS goes above and beyond Java EE here, and will automatically configure JSF for you if

you include this file. Thus, the configuration consists of only the root element.

faces-config.xml

03. the copyright.txt in the distribution for a full listing of individual contributors.

04. Licensed under the Apache License, Version 2.0 (the "License"); you may not

05. use this file except in compliance with the License. You may obtain a copy

06. of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required

07. by applicable law or agreed to in writing, software distributed under the

08. License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS

09. OF ANY KIND, either express or implied. See the License for the specific

10. language governing permissions and limitations under the License. -->

11. <!-- Marker file indicating JSF 2.0 should be enabled in the application -->

12.

13. <faces-config version="2.0"

14. xmlns="http://java.sun.com/xml/ns/javaee"

15. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

16. xsi:schemaLocation="

17. http://java.sun.com/xml/ns/javaee

18. http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">

19.

20. </faces-config>

There's also an empty file, which tells JBoss AS to look for beans in this application and tobeans.xml

activate the CDI.

Notice that we don't even need a !web.xml

Let's take a look at the main JSF view, .src/main/webapp/home.xhtml

JSF uses the extension for source files, but serves up the rendered views with the .xhtml .jsf

extension.

home.xhtml

JBoss AS 7.1

JBoss Community Documentation Page of 34 295

03. <html xmlns="http://www.w3.org/1999/xhtml"

04. xmlns:ui="http://java.sun.com/jsf/facelets"

05. xmlns:h="http://java.sun.com/jsf/html"

06. xmlns:f="http://java.sun.com/jsf/core">

07.

08. <head>

09. <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />

10. <title>numberguess</title>

11. </head>

12.

13. <body>

14. <div id="content">

15. <h1>Guess a number...</h1>

16. <h:form id="numberGuess">

17.

18. <!-- Feedback for the user on their guess -->

19. <div style="color: red">

20. <h:messages id="messages" globalOnly="false" />

21. <h:outputText id="Higher" value="Higher!"

22. rendered="#{game.number gt game.guess and game.guess ne 0}" />

23. <h:outputText id="Lower" value="Lower!"

24. rendered="#{game.number lt game.guess and game.guess ne 0}" />

25. </div>

26.

27. <!-- Instructions for the user -->

28. <div>

29. I'm thinking of a number between <span

30. id="numberGuess:smallest">#{game.smallest}</span> and <span

31. id="numberGuess:biggest">#{game.biggest}</span>. You have

32. #{game.remainingGuesses} guesses remaining.

33. </div>

34.

35. <!-- Input box for the users guess, plus a button to submit, and reset -->

36. <!-- These are bound using EL to our CDI beans -->

37. <div>

38. Your guess:

39. <h:inputText id="inputGuess" value="#{game.guess}"

40. required="true" size="3"

41. disabled="#{game.number eq game.guess}"

42. validator="#{game.validateNumberRange}" />

43. <h:commandButton id="guessButton" value="Guess"

44. action="#{game.check}"

45. disabled="#{game.number eq game.guess}" />

46. </div>

47. <div>

48. <h:commandButton id="restartButton" value="Reset"

49. action="#{game.reset}" immediate="true" />

50. </div>

51. </h:form>

52.

53. </div>

54.

55. <br style="clear: both" />

56.

57. </body>

58. </html>

JBoss AS 7.1

JBoss Community Documentation Page of 35 295

Line

number

Note

20 - 24 There are a number of messages which can be sent to the user, "Higher!" and "Lower!"

29 - 32 As the user guesses, the range of numbers they can guess gets smaller - this sentence changes

to make sure they know the number range of a valid guess.

38 - 42 This input field is bound to a bean property using a value expression.

42 A validator binding is used to make sure the user doesn't accidentally input a number outside of

the range in which they can guess - if the validator wasn't here, the user might use up a guess

on an out of bounds number.

43 - 45 There must be a way for the user to send their guess to the server. Here we bind to an action

method on the bean.

The example consists of 4 classes, the first two of which are qualifiers. First, there is the

qualifier, used for injecting a random number:@Random

A is used to disambiguate between two beans both of which are eligible for injection basedqualifier

on their type. For more, see the .Weld Reference Guide

Random.java

21. import static java.lang.annotation.ElementType.PARAMETER;

22. import static java.lang.annotation.ElementType.TYPE;

23. import static java.lang.annotation.RetentionPolicy.RUNTIME;

24.

25. import java.lang.annotation.Documented;

26. import java.lang.annotation.Retention;

27. import java.lang.annotation.Target;

28.

29. import javax.inject.Qualifier;

30.

31. /**

32. * Qualifier for random numbers

33. *

34. * @author Pete Muir

35. *

36. */

37. @Target({ TYPE, METHOD, PARAMETER, FIELD })

38. @Retention(RUNTIME)

39. @Documented

40. @Qualifier

41. public @interface Random {

42.

43. }

There is also the qualifier, used for injecting the maximum number that can be injected:@MaxNumber

JBoss AS 7.1

JBoss Community Documentation Page of 36 295

MaxNumber.java

21. import static java.lang.annotation.ElementType.PARAMETER;

22. import static java.lang.annotation.ElementType.TYPE;

23. import static java.lang.annotation.RetentionPolicy.RUNTIME;

24.

25. import java.lang.annotation.Documented;

26. import java.lang.annotation.Retention;

27. import java.lang.annotation.Target;

28.

29. import javax.inject.Qualifier;

30.

31. /**

32. * Qualifier for the maximum number

33. *

34. * @author Pete Muir

35. *

36. */

37. @Target({ TYPE, METHOD, PARAMETER, FIELD })

38. @Retention(RUNTIME)

39. @Documented

40. @Qualifier

41. public @interface MaxNumber {

42.

43. }

The application-scoped class is responsible for creating the random number, via a producerGenerator

method. It also exposes the maximum possible number via a producer method:

JBoss AS 7.1

JBoss Community Documentation Page of 37 295

Generator.java

28. *

29. * <p>

30. * Placing the random number generation, as well as the configuring the maximum number

allows for a

31. * more loosely coupled application. We can now change out the implementation of number

generation

32. * without any effect on the client code. We also produce a more intuitive design - both are

33. * identifed by the fact they are numbers (int) and that they are qualified as the maximum

number or

34. * a random number.

35. * </p>

36. *

37. * <p>

38. * We use the application scope to store the random number generator so that we use the same

seed.

39. * </p>

40. *

41. * @author Pete Muir

42. *

43. */

44. @ApplicationScoped

45. public class Generator implements Serializable {

46. private static final long serialVersionUID = -7213673465118041882L;

47.

48. private java.util.Random random = new java.util.Random(System.currentTimeMillis());

49.

50. private int maxNumber = 100;

51.

52. java.util.Random getRandom() {

53. return random;

54. }

55.

56. @Produces

57. @Random

58. int next() {

59. // a number between 1 and 100

60. return getRandom().nextInt(maxNumber - 1) + 1;

61. }

62.

63. @Produces

64. @MaxNumber

65. int getMaxNumber() {

66. return maxNumber;

67. }

68. }

The is application scoped, so we don't get a different random each time.Generator

The final bean in the application is the session-scoped class. This is the primary entry point of theGame

application. It's responsible for setting up or resetting the game, capturing and validating the user's guess

and providing feedback to the user with a . We've used the post-construct lifecycle methodFacesMessage

to initialize the game by retrieving a random number from the bean.@RandomInstance<Integer>

JBoss AS 7.1

JBoss Community Documentation Page of 38 295

You'll notice that we've also added the annotation to this class. This annotation is only required@Named

when you want to make the bean accessible to a JSF view via EL (i.e., }).#{game

Game.java

035. * </p>

036. * <p>

037. * It contains properties for the <code>number</code> to be guessed, the current

<code>guess</code>,

038. * the <code>smallest</code> and <code>biggest</code> numbers guessed so far (as this is a

039. * higher/lower game we can prevent them entering numbers that they should know are wrong),

and the

040. * number of <code>remainingGuesses</code>.

041. * </p>

042. * <p>

043. * The {@link #check()} method, and {@link #reset()} methods provide the business logic

whilst the

044. * {@link #validateNumberRange(FacesContext, UIComponent, Object)} method provides feedback

to the

045. * user.

046. * </p>

047. *

048. * @author Pete Muir

049. *

050. */

051. @Named

052. @SessionScoped

053. public class Game implements Serializable {

054.

055. private static final long serialVersionUID = 991300443278089016L;

056.

057. /**

058. * The number that the user needs to guess

059. */

060. private int number;

061.

062. /**

063. * The users latest guess

064. */

065. private int guess;

066.

067. /**

068. * The smallest number guessed so far (so we can track the valid guess range).

069. */

070. private int smallest;

071.

072. /**

073. * The largest number guessed so far

074. */

075. private int biggest;

076.

077. /**

078. * The number of guesses remaining

079. */

080. private int remainingGuesses;

081.

082. /**

JBoss AS 7.1

JBoss Community Documentation Page of 39 295

083. * The maximum number we should ask them to guess

084. */

085. @Inject

086. @MaxNumber

087. private int maxNumber;

088.

089. /**

090. * The random number to guess

091. */

092. @Inject

093. @Random

094. Instance<Integer> randomNumber;

095.

096. public Game() {

097. }

098.

099. public int getNumber() {

100. return number;

101. }

102.

103. public int getGuess() {

104. return guess;

105. }

106.

107. public void setGuess(int guess) {

108. this.guess = guess;

109. }

110.

111. public int getSmallest() {

112. return smallest;

113. }

114.

115. public int getBiggest() {

116. return biggest;

117. }

118.

119. public int getRemainingGuesses() {

120. return remainingGuesses;

121. }

122.

123. /**

124. * Check whether the current guess is correct, and update the biggest/smallest guesses

as needed.

125. * Give feedback to the user if they are correct.

126. */

127. public void check() {

128. if (guess > number) {

129. biggest = guess - 1;

130. } else if (guess < number) {

131. smallest = guess + 1;

132. } else if (guess == number) {

133. FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Correct!"));

134. }

135. remainingGuesses--;

136. }

137.

138. /**

139. * Reset the game, by putting all values back to their defaults, and getting a new

JBoss AS 7.1

JBoss Community Documentation Page of 40 295

random number.

140. * We also call this method when the user starts playing for the first time using

141. * {@linkplain PostConstruct @PostConstruct} to set the initial values.

142. */

143. @PostConstruct

144. public void reset() {

145. this.smallest = 0;

146. this.guess = 0;

147. this.remainingGuesses = 10;

148. this.biggest = maxNumber;

149. this.number = randomNumber.get();

150. }

151.

152. /**

153. * A JSF validation method which checks whether the guess is valid. It might not be

valid because

154. * there are no guesses left, or because the guess is not in range.

155. *

156. */

157. public void validateNumberRange(FacesContext context, UIComponent toValidate, Object

value) {

158. if (remainingGuesses <= 0) {

159. FacesMessage message = new FacesMessage("No guesses left!");

160. context.addMessage(toValidate.getClientId(context), message);

161. ((UIInput) toValidate).setValid(false);

162. return;

163. }

164. int input = (Integer) value;

165.

166. if (input < smallest || input > biggest) {

167. ((UIInput) toValidate).setValid(false);

168.

169. FacesMessage message = new FacesMessage("Invalid guess");

170. context.addMessage(toValidate.getClientId(context), message);

171. }

172. }

173. }

JBoss AS 7.1

JBoss Community Documentation Page of 41 295

5 CDI + JPA + EJB + JTA + JSF: Login quickstartThis quickstart shows you how to create and deploy an application which persists information to a database

to JBoss AS. Information is displayed using JSF views, business logic is encapsulated in CDI beans,

information is persisted using JPA, and transactions can be controlled manually or using EJB.

Switch to the directory and instruct Maven to build and deploy the application:quickstarts/login

mvn package jboss-as:deploy

The quickstart uses a Maven plugin to deploy the application. The plugin requires JBoss AS to be running

(you can find out how to start the server in or Installing and starting JBoss AS on Linux, Unix or Mac OS X

).Installing and starting JBoss AS on Windows

Or you can start the server using an IDE, like Eclipse.

Visit and try logging in with the username and password .http://localhost:8080/jboss-as-login demo demo

Now, click on and then on . From this screen you can add yourself as a user, and thenLogout View Users

login as this user.

Should you wish to undeploy the quickstart, or redeploy after making some changes, it's pretty

easy:

- deploy any changes to the application to the application servermvn jboss-as:deploy

- undeploy the example from JBoss ASmvn jboss-as:undeploy

It's time to pull the covers back and dive into the internals of the example application.

5.1 Deploying the Login example using Eclipse

You may choose to deploy the example using Eclipse. You'll need to have JBoss AS started in Eclipse (as

described in ) and to have imported the quickstarts intoStarting JBoss AS from Eclipse with JBoss Tools

Eclipse (as described in [Importing the quickstarts into Eclipse).

With the quickstarts imported, you can deploy the example by right clicking on the jboss-as-login

project, and choosing :Run As -> Run On Server

JBoss AS 7.1

JBoss Community Documentation Page of 42 295

Make sure the JBoss AS server is selected, and hit :Finish

JBoss AS 7.1

JBoss Community Documentation Page of 43 295

You should see JBoss AS start up (unless you already started it in Starting JBoss AS from Eclipse with

) and the application deploy in the Console log:JBoss Tools

5.2 The login example in depth

JBoss AS 7.1

JBoss Community Documentation Page of 44 295

In the login example, all users are stored in an H2 database (an in-memory, embedded database provided

out of the box in JBoss AS). Each user is stored as an entity, and entities are mapped to the database using

JPA. By default, transactions are managed manually, using the JTA API. Optionally, you can use EJB to

manage transactions (we'll look at how to enable that later). We need a transaction in progress in order to

read and write any entities.

The login example is comprised of two JSF views, an entity, and a number of CDI beans. Additionally, there

are the usual configuration files in (which can be found in the directory of theWEB-INF/ src/main/webapp

example). Here we find and tell JBoss AS to enable CDI and JSF for thebeans.xml face-config.xml

application. Notice that we don't need a . There are two new configuration files in web.xml

(which can be found in the directory of theWEB-INF/classes/META-INF src/main/resources

example) — , which sets up JPA, and which Hibernate, the JPA providerpersistence.xml import.sql

in JBoss AS, will use to load the initial users into the application when the application starts.

is pretty straight forward, and links JPA to a datasource: Unable topersistence.xml Code Snippet error:

retrieve the URL:

https://github.com/jbossas/quickstart/raw/master/login/src/main/resources/META-INF/persistence.xml status

code: 404.

Line

number

Note

6 The persistence unit is given a name, so that the application can use multiple if needed. If only

one is defined, JPA will automatically use it.

8 The persistence unit references a data source. Here we are using the built in, sample, data

source.

10 JPA allows us to configure the JPA provider specific properties. Here we tell Hibernate to

automatically create any needed tables when the application starts (and drop them when the

application is stopped).

JBoss AS ships with a sample datasource . This datajava:jboss/datasources/ExampleDS

source is backed by H2, an in-memory database. Whilst this datasource is great for quickstarts,

you will probably want to use a different datasource in your application. The Getting Started Guide

tells you how to create a new datasource.

Let's take a look at the JSF views. First up is :src/main/webapp/home.xhtml Code Snippet error:

Unable to retrieve the URL:

https://github.com/jbossas/quickstart/raw/master/login/src/main/webapp/home.xhtml status code: 404.

Line

number

Note

JBoss AS 7.1

JBoss Community Documentation Page of 45 295

7 As we have multiple views in this application, we've created a template that defines the common

elements. We'll examine this next. Here we define the "content" section of the page, which will

be inserted into the template.

9 We output any messages for the user at the top of the form, such as the welcome message

when you login.

11 - 16 The login form fields are only rendered if there is no logged in user. This allows us to prevent

someone from logging in twice.

17, 18 Depending on whether the user is logged in or not, we display a log out or log in button. We also

display a link to the page which shows the available users.

Now let's take a look at the template. It defines common elements for the page, and allows pages which use

it to insert content in various places. Unable to retrieve the URL:Code Snippet error:

https://github.com/jbossas/quickstart/raw/master/login/src/main/webapp/template.xhtml status code: 404.

Line number Note

9 The head, defined in case a page wants to add some content to the head of the page.

28 The content, defined by a page using this template, will be inserted here

Finally, let's take a look at the user management page. It uses a table to display all existing users, and

provides a form to add users Unable to retrieve the URL:Code Snippet error:

https://github.com/jbossas/quickstart/raw/master/login/src/main/webapp/users.xhtml status code: 404.

Line

number

Note

11 The table which displays the current users in the database. The datatable references the ,users

and iterates over each one. Each user is assigned to the variable , which we can use whenu

laying out the table structure.

13 - 15 Each column in the table is given a header, plus content.

Finally, we provide a simple form that allows you to add a new user.

The example has one entity, which is mapped via JPA to the relational database:Code Snippet error:

Unable to retrieve the URL:

https://github.com/jbossas/quickstart/raw/master/login/src/main/java/org/jboss/as/quickstarts/login/User.java

status code: 404.

Line

number

Note

6 The annotation used on the class tells JPA that this class should be mapped as a@Entity

table in the database.

JBoss AS 7.1

JBoss Community Documentation Page of 46 295

8, 9 Every entity requires an id, the annotation placed on a field (or a JavaBean@Id

mutator/accessor) tells JPA that this property is the id. You can use a synthetic id, or a natural id

(as we do here).

10, 11 The entity also stores the real name of the user, and their password.

13 - 35 As this is Java, every property needs an accessor/mutator!

Next up, let's take a look at , a data structure used to temporarily hold the credentialsCredentials.java

the user has entered whilst logging in. Unable to retrieve the URL:Code Snippet error:

https://github.com/jbossas/quickstart/raw/master/login/src/main/java/org/jboss/as/quickstarts/login/Credentials.java

status code: 404.

Line

number

Note

6 The bean is request scoped, as entered data is naturally scoped to a request.

7 The bean is given a name, so we can access it from JSF.

10 - 27 The bean needs to store the username and password entered, and also make them usable via

accessors and mutators.

The logic allowing a user to log in, and storing who is currently logged in, is encoded in :Login.java Code

Unable to retrieve the URL:Snippet error:

https://github.com/jbossas/quickstart/raw/master/login/src/main/java/org/jboss/as/quickstarts/login/Login.java

status code: 404.

Line

number

Note

12 The bean is session scoped, meaning that the currently logged user is kept until the session

ends.

13 The bean is given a name, so we can access it from JSF.

18, 19 We inject the credentials filled in on the web page so we can check them in the login()

method.

21, 22 We inject the user manager, which takes care of loading and adding users from the database.

26 - 33 The login method is triggered when the button is pressed. It asks the toLogin userManager

find a user with matching username and password, and if a user is found, sets the

and displays a message to the user.currentUser

35 - 39 The logout method is triggered when the button is pressed. It clearsthe Logout currentUser

and displays a message to the user.

45 - 49 The current user is exposed to the application using a producer method, which means that there

is no coupling between a class wanting to know the current user, and the class. The Login

qualifier is used to indicate that this is special.LoggedIn User

JBoss AS 7.1

JBoss Community Documentation Page of 47 295

Now, let's look at the most interesting part of the application, how we interact with the database. As we

mentioned earlier, by default the application uses the JTA API to manually control transactions. To

implement both approaches, we've defined a interface, with two implementations, one ofUserManager

which (the EJB variant) is as an alternative which can be enabled via a deployment descriptor. Let's first look

at the interface, and the manual transaction control variant. Unable to retrieve the URL:Code Snippet error:

https://github.com/jbossas/quickstart/raw/master/login/src/main/java/org/jboss/as/quickstarts/login/UserManager.java

status code: 404.

The methods are fairly self explanatory, so let's move on quickly to the implementation,

: Unable to retrieve the URL:ManagedBeanUserManager Code Snippet error:

https://github.com/jbossas/quickstart/raw/master/login/src/main/java/org/jboss/as/quickstarts/login/ManagedBeanUserManager.java

status code: 404.

Line

number

Note

13 The bean is given a name, so we can access it from JSF.

14 The bean is request scoped, meaning that the new user object being added is the same for

every invocation of during the request.userManager

17 - 18 We inject a JDK logger so that we can log when a user is added

20 - 21 We inject the entity manager. This was set up in .persistence.xml

29 - 45 We create a named producer method that uses JPA to expose all the users currently in the

database. This allows JSF to access this list. We also make this request scoped so that the

database isn't hit every time we need to display the users list.

47 - 61 takes the and persists it to the database.addUser newUser

63 - 88 The method can check whether a user with a matching username and passwordfindUser()

exists, and return it if it does.

90 - 95 The is exposed to JSF by using a named producer method.newUser

You've probably noticed two things as you've read through this. Firstly, that manually managing transactions

is a real pain. Secondly, you may be wondering how the entity manager and the logger are injected. First,

let's tidy up the transaction manager, and use EJB to provide us with declarative transaction support.

The class provides this, and is defined as an alternative. Alternatives are disabled byEJBUserManager

default, and when enabled replace the original implementation. In order to enable this variant of

, edit and uncomment the alternative. Your should now look like:UserManager beans.xml beans.xml

JBoss AS 7.1

JBoss Community Documentation Page of 48 295

<beans xmlns="http://java.sun.com/xml/ns/javaee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="

http://java.sun.com/xml/ns/javaee

http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">

<!-- Uncomment this alternative to see EJB declarative transactions in use -->

<alternatives>

<class>org.jboss.as.quickstarts.login.EJBUserManager</class>

</alternatives>

</beans>

Now, let's look at : Unable to retrieve the URL:EJBUserManager Code Snippet error:

https://github.com/jbossas/quickstart/raw/master/login/src/main/java/org/jboss/as/quickstarts/login/EJBUserManager.java

status code: 404.

Using declarative transaction management has allowed us to remove a third of the lines of code from the

class, but more importantly emphasizes the functionality of the class. Much better!

Sharp eyed developers who are used to Java EE will have noticed that we have added this EJB to

a war. This is the key improvement offered in EJB 3.1 (which was first included in Java EE 6).

Finally, let's take a look at the class, which provides resources such as the entity manager. CDIResources

recommends using "resource producers", as we do in this example, to alias resources to CDI beans,

allowing for a consistent style throughout our application: Unable to retrieve the URL:Code Snippet error:

https://github.com/jbossas/quickstart/raw/master/login/src/main/java/org/jboss/as/quickstarts/login/Resources.java

status code: 404.

Line

number

Note

13 - 16 We use the "resource producer" pattern, from CDI, to "alias" the old fashioned

injection of the entity manager to a CDI style injection. This allows us@PersistenceContext

to use a consistent injection style ( ) throughout the application.@Inject

18 - 22 We expose a JDK logger for injection. In order to save a bit more boiler plate, we automatically

set the logger category as the class name!

That concludes our tour of the login application!

JBoss AS 7.1

JBoss Community Documentation Page of 49 295

6 CDI + JSF + EJB + JTA + Bean Validation +

JAX-RS + Arquillian: Kitchensink quickstartThis quickstart shows off all the new features of Java EE 6, and makes a great starting point for your project.

Bean Validation

Bean Validation is a new specification in Java EE 6, inspired by Hibernate Validator. It allows

application developers to specify constraints once (often in their domain model), and have them

applied in all layers of the application, protecting data and giving useful feedback to users.

JAX-RS: The Java API for RESTful Web Services

JAX-RS is a new specification in Java EE 6. It allows application developers to easily expose Java

services as RESTful web services.

Switch to the directory and instruct Maven to build and deploy thequickstarts/kitchensink

application:

mvn package jboss-as:deploy

The quickstart uses a Maven plugin to deploy the application. The plugin requires JBoss AS to be running

(you can find out how to start the server in or Installing and starting JBoss AS on Linux, Unix or Mac OS X

).Installing and starting JBoss AS on Windows

Or you can start the server using an IDE, like Eclipse.

Now, check if the application has deployed properly by clicking . Ifhttp://localhost:8080/jboss-as-kitchensink

you see a splash page it's all working!

Should you wish to undeploy the quickstart, or redeploy after making some changes, it's pretty

easy:

- deploy any changes to the application to the application servermvn jboss-as:deploy

- undeploy the example from JBoss ASmvn jboss-as:undeploy

It's time to pull the covers back and dive into the internals of the example application.

JBoss AS 7.1

JBoss Community Documentation Page of 50 295

6.1 Deploying the Kitchensink example using Eclipse

You may choose to deploy the example using Eclipse. You'll need to have JBoss AS started in Eclipse (as

described in ) and to have imported the quickstarts intoStarting JBoss AS from Eclipse with JBoss Tools

Eclipse (as described in ).Importing the quickstarts into Eclipse

With the quickstarts imported, you can deploy the example by right clicking on the

project, and choosing :jboss-as-kitchensink Run As -> Run On Server

Make sure the JBoss AS server is selected, and hit :Finish

JBoss AS 7.1

JBoss Community Documentation Page of 51 295

You should see JBoss AS start up (unless you already started it in Starting JBoss AS from Eclipse with

) and the application deploy in the Console log:JBoss Tools

6.2 The kitchensink example in depth

JBoss AS 7.1

JBoss Community Documentation Page of 52 295

The kitchensink application shows off a number of Java EE technologies such as CDI, JSF, EJB, JTA,

JAX-RS and Arquillian. It does this by providing a member registration database, available via JSF and

JAX-RS.

As usual, let's start by looking at the necessary deployment descriptors. By now, we're very used to seeing

and in (which can be found in the beans.xml faces-config.xml WEB-INF/ src/main/webapp

directory of the example). Notice that, once again, we don't need a . There are two configurationweb.xml

files in (which can be found in the directory of theWEB-INF/classes/META-INF src/main/resources

example) — , which sets up JPA, and which Hibernate, the JPA providerpersistence.xml import.sql

in JBoss AS 7, will use to load the initial users into the application when the application starts. We discussed

both of these files in detail in , and these are largely the same.The login example in depth

Next, let's take a look at the JSF view the user sees. As usual, we use a template to provide the sidebar and

footer. This one lives in :WEB-INF/templates/default.xhtml

JBoss AS 7.1

JBoss Community Documentation Page of 53 295

default.xhtml

03. <html xmlns="http://www.w3.org/1999/xhtml"

04. xmlns:h="http://java.sun.com/jsf/html"

05. xmlns:ui="http://java.sun.com/jsf/facelets">

06. <h:head>

07. <title>kitchensink</title>

08. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

09. <h:outputStylesheet name="css/screen.css" />

10. </h:head>

11. <h:body>

12. <div id="container">

13. <div class="dualbrand">

14. <img src="resources/gfx/dualbrand_logo.png" />

15. </div>

16. <div id="content">

17. <ui:insert name="content">

18. [Template content will be inserted here]

19. </ui:insert>

20. </div>

21. <div id="aside">

22. <p>Learn more about JBoss Enterprise Application Platform 6.</p>

23. <ul>

24. <li><a

25. href="http://red.ht/jbeap-6-docs">Documentation</a></li>

26. <li><a href="http://red.ht/jbeap-6">Product Information</a></li>

27. </ul>

28. <p>Learn more about JBoss AS 7.</p>

29. <ul>

30. <li><a

31.

href="https://docs.jboss.org/author/display/AS7/Getting+Started+Developing+Applications+Guide">Getting

Started Developing Applications Guide</a></li>

32. <li><a href="http://jboss.org/jbossas">Community Project Information</a></li>

33. </ul>

34. </div>

35. <div id="footer">

36. <p>

37. This project was generated from a Maven archetype from

38. JBoss.<br />

39. </p>

40. </div>

41. </div>

42. </h:body>

43. </html>

Line

number

Note

6 - 10 We have a common element, where we define styles and more.<head>

14 - 51, 56

- 61

This application defines a common sidebar and footer, putting them in the template means we

only have to define them once/

JBoss AS 7.1

JBoss Community Documentation Page of 54 295

52 - 54 The content is inserted here, and defined by views using this template.

That leaves the main page, , in which we place the content unique to the main page:index.xhtml

index.xhtml

02. <ui:composition xmlns="http://www.w3.org/1999/xhtml"

03. xmlns:ui="http://java.sun.com/jsf/facelets"

04. xmlns:f="http://java.sun.com/jsf/core"

05. xmlns:h="http://java.sun.com/jsf/html"

06. template="/WEB-INF/templates/default.xhtml">

07. <ui:define name="content">

08. <h1>Welcome to JBoss!</h1>

09.

10. d

11.

12. <h:form id="reg">

13. <h2>Member Registration</h2>

14. <p>Enforces annotation-based constraints defined on the model class.</p>

15. <h:panelGrid columns="3" columnClasses="titleCell">

16. <h:outputLabel for="name" value="Name:"/>

17. <h:inputText id="name" value="#{newMember.name}" />

18. <h:message for="name" errorClass="invalid"/>

19.

20. <h:outputLabel for="email" value="Email:"/>

21. <h:inputText id="email" value="#{newMember.email}"/>

22. <h:message for="email" errorClass="invalid"/>

23.

24. <h:outputLabel for="phoneNumber" value="Phone #:"/>

25. <h:inputText id="phoneNumber" value="#{newMember.phoneNumber}"/>

26. <h:message for="phoneNumber" errorClass="invalid"/>

27. </h:panelGrid>

28.

29. <p>

30. <h:panelGrid columns="2">

31. <h:commandButton id="register" action="#{memberController.register}"

value="Register" styleClass="register"/>

32. <h:messages styleClass="messages" errorClass="invalid" infoClass="valid"

warnClass="warning"

33. globalOnly="true"/>

34. </h:panelGrid>

35. </p>

36. </h:form>

37. <h2>Members</h2>

38. <h:panelGroup rendered="#{empty members}">

39. <em>No registered members.</em>

40. </h:panelGroup>

41. <h:dataTable var="_member" value="#{members}" rendered="#{not empty members}"

styleClass="simpletablestyle">

42. <h:column>

43. <f:facet name="header">Id</f:facet>

44. #{_member.id}

45. </h:column>

46. <h:column>

47. <f:facet name="header">Name</f:facet>

48. #{_member.name}

JBoss AS 7.1

JBoss Community Documentation Page of 55 295

49. </h:column>

50. <h:column>

51. <f:facet name="header">Email</f:facet>

52. #{_member.email}

53. </h:column>

54. <h:column>

55. <f:facet name="header">Phone #</f:facet>

56. #{_member.phoneNumber}

57. </h:column>

58. <h:column>

59. <f:facet name="header">REST URL</f:facet>

60. <a

href="#{request.contextPath}/rest/members/#{_member.id}">/rest/members/#{_member.id}</a>

61. </h:column>

62. <f:facet name="footer">

63. REST URL for all members: <a

href="#{request.contextPath}/rest/members">/rest/members</a>

64. </f:facet>

65. </h:dataTable>

66. </ui:define>

67. </ui:composition>

Line

number

Note

12 - 48 The JSF form allows us to register new users. There should be one already created when the

application started.

22, 31,

40

The application uses Bean Validation to validate data entry. The error messages from Bean

Validation are automatically attached to the relevant field by JSF, and adding a JSFmessages

component will display them.

53 - 77 This application exposes REST endpoints for each registered member. The application helpfully

displays the URL to the REST endpoint on this page.

Next, let's take a look at the entity, before we look at how the application is wired together:Member

Memberjava

20.

21. import javax.persistence.Column;

22. import javax.persistence.Entity;

23. import javax.persistence.GeneratedValue;

24. import javax.persistence.Id;

25. import javax.persistence.Table;

26. import javax.persistence.UniqueConstraint;

27. import javax.validation.constraints.Digits;

28. import javax.validation.constraints.NotNull;

29. import javax.validation.constraints.Pattern;

30. import javax.validation.constraints.Size;

31. import javax.xml.bind.annotation.XmlRootElement;

32.

33. import org.hibernate.validator.constraints.Email;

34. import org.hibernate.validator.constraints.NotEmpty;

JBoss AS 7.1

JBoss Community Documentation Page of 56 295

35.

36. @Entity

37. @XmlRootElement

38. @Table(uniqueConstraints = @UniqueConstraint(columnNames = "email"))

39. public class Member implements Serializable {

40. /** Default value included to remove warning. Remove or modify at will. **/

41. private static final long serialVersionUID = 1L;

42.

43. @Id

44. @GeneratedValue

45. private Long id;

46.

47. @NotNull

48. @Size(min = 1, max = 25)

49. @Pattern(regexp = "[A-Za-z ]*", message = "must contain only letters and spaces")

50. private String name;

51.

52. @NotNull

53. @NotEmpty

54. @Email

55. private String email;

56.

57. @NotNull

58. @Size(min = 10, max = 12)

59. @Digits(fraction = 0, integer = 12)

60. @Column(name = "phone_number")

61. private String phoneNumber;

62.

63. public Long getId() {

64. return id;

65. }

66.

67. public void setId(Long id) {

68. this.id = id;

69. }

70.

71. public String getName() {

72. return name;

73. }

74.

75. public void setName(String name) {

76. this.name = name;

77. }

78.

79. public String getEmail() {

80. return email;

81. }

82.

83. public void setEmail(String email) {

84. this.email = email;

85. }

86.

87. public String getPhoneNumber() {

88. return phoneNumber;

89. }

90.

91. public void setPhoneNumber(String phoneNumber) {

92. this.phoneNumber = phoneNumber;

JBoss AS 7.1

JBoss Community Documentation Page of 57 295

93. }

94. }

Line

number

Note

20 As usual with JPA, we define that the class is an entity by adding @Entity

21 Members are exposed as a RESTful service using JAX-RS. We can use JAXB to map the object

to XML and to do this we need to add .@XmlRootElement

31 - 33 Bean Validation allows constraints to be defined once (on the entity) and applied everywhere.

Here we constrain the person's name to a certain size and regular expression.

38 Hibernate Validator also offers some extra validations such as .@Email

41 - 43 , and are further examples of constraints.@Digits @NotNull @Size

Next, let's take a look at , which is responsible for building the list of members,MemberListProducer

ordered by name. It uses JPA 2 criteria to do this.

JBoss AS 7.1

JBoss Community Documentation Page of 58 295

MemberListProducer.java

18.

19. import javax.annotation.PostConstruct;

20. import javax.enterprise.context.RequestScoped;

21. import javax.enterprise.event.Observes;

22. import javax.enterprise.event.Reception;

23. import javax.enterprise.inject.Produces;

24. import javax.inject.Inject;

25. import javax.inject.Named;

26. import java.util.List;

27.

28. import org.jboss.as.quickstarts.kitchensink.model.Member;

29.

30. @RequestScoped

31. public class MemberListProducer {

32.

33. @Inject

34. private MemberRepository memberRepository;

35.

36. private List<Member> members;

37.

38. // @Named provides access the return value via the EL variable name "members" in the UI

(e.g.,

39. // Facelets or JSP view)

40. @Produces

41. @Named

42. public List<Member> getMembers() {

43. return members;

44. }

45.

46. public void onMemberListChanged(@Observes(notifyObserver = Reception.IF_EXISTS) final

Member member) {

47. retrieveAllMembersOrderedByName();

48. }

49.

50. @PostConstruct

51. public void retrieveAllMembersOrderedByName() {

52. members = memberRepository.findAllOrderedByName();

53. }

54. }

Line

number

Note

18 This bean is request scoped, meaning that any fields (such as ) will be stored for themembers

entire request.

26 - 30 The list of members is exposed as a producer method, it's also available via EL.

32 - 34 The observer method is notified whenever a member is created, removed, or updated. This

allows us to refresh the list of members whenever they are needed. This is a good approach as

it allows us to cache the list of members, but keep it up to date at the same time.

JBoss AS 7.1

JBoss Community Documentation Page of 59 295

36 - 45 JPA 2's criteria API is used to create a list of members sorted by name. You can try out the type

safe criteria API as well by swapping the criteria statements as described.

Let's now look at , the class that allows us to create new members from the JSFMemberRegistration

page Unable to retrieve the URL:Code Snippet error:

https://github.com/jbossas/quickstart/raw/master/kitchensink/src/main/java/org/jboss/as/quickstarts/kitchensink/controller/MemberRegistration.java

status code: 404.

Line

number

Note

18 This bean requires transactions as it needs to write to the database. Making this an EJB gives

us access to declarative transactions - much simpler than manual transaction control!

21 Stereotypes, such as allow grouping of common functionality. Here we use the built in @Model

stereotype to give us a request scoped, named bean.@Model

26 - 28 Seam Solder, used in this project offers an injectable logger based on JBoss Logging.

47 An event is sent every time a member is updated. This allows other pieces of code (in this

example the member list is refreshed) to react to changes in the member list without any

coupling to this class.

Seam Solder is a swiss army knife for any CDI based application. It offers some basic additions to

the CDI programming model (such as an injectable, type-safe, logger) as well as utilities for

developing CDI extensions. You can read more on the .Solder project page

Now, let's take a look at the class, which provides resources such as the entity manager. CDIResources

recommends using "resource producers", as we do in this example, to alias resources to CDI beans,

allowing for a consistent style throughout our application:

JBoss AS 7.1

JBoss Community Documentation Page of 60 295

Resources.java

19. import java.util.logging.Logger;

20.

21. import javax.enterprise.context.RequestScoped;

22. import javax.enterprise.inject.Produces;

23. import javax.enterprise.inject.spi.InjectionPoint;

24. import javax.faces.context.FacesContext;

25. import javax.persistence.EntityManager;

26. import javax.persistence.PersistenceContext;

27.

28. /**

29. * This class uses CDI to alias Java EE resources, such as the persistence context, to CDI

beans

30. *

31. * <p>

32. * Example injection on a managed bean field:

33. * </p>

34. *

35. * <pre>

36. * &#064;Inject

37. * private EntityManager em;

38. * </pre>

39. */

40. public class Resources {

41. // use @SuppressWarnings to tell IDE to ignore warnings about field not being referenced

directly

42. @SuppressWarnings("unused")

43. @Produces

44. @PersistenceContext

45. private EntityManager em;

46.

47. @Produces

48. public Logger produceLog(InjectionPoint injectionPoint) {

49. return Logger.getLogger(injectionPoint.getMember().getDeclaringClass().getName());

50. }

51.

52. @Produces

53. @RequestScoped

54. public FacesContext produceFacesContext() {

55. return FacesContext.getCurrentInstance();

56. }

57.

58. }

Line

number

Note

21 - 24 We use the "resource producer" pattern, from CDI, to "alias" the old fashioned

injection of the entity manager to a CDI style injection. This allows us@PersistenceContext

to use.

If you want to define your own datasource, take a look at the or at .Getting Started Guide the JBoss AS wiki

JBoss AS 7.1

JBoss Community Documentation Page of 61 295

Before we wrap up our tour of the kitchensink example application, let's take a look at how the JAX-RS

endpoints are created. Firstly, {JaxRSActivator}}, which extends and is annotated with Application

, is the Java EE 6 "no XML" approach to activating JAX-RS.@ApplicationPath

The real work goes in , which produces the endpoint:MemberResourceRESTService

MembeResourceRESTService.java

020. import java.util.HashSet;

021. import java.util.List;

022. import java.util.Map;

023. import java.util.Set;

024. import java.util.logging.Logger;

025.

026. import javax.enterprise.context.RequestScoped;

027. import javax.inject.Inject;

028. import javax.persistence.NoResultException;

029. import javax.validation.ConstraintViolation;

030. import javax.validation.ConstraintViolationException;

031. import javax.validation.ValidationException;

032. import javax.validation.Validator;

033. import javax.ws.rs.Consumes;

034. import javax.ws.rs.GET;

035. import javax.ws.rs.POST;

036. import javax.ws.rs.Path;

037. import javax.ws.rs.PathParam;

038. import javax.ws.rs.Produces;

039. import javax.ws.rs.WebApplicationException;

040. import javax.ws.rs.core.MediaType;

041. import javax.ws.rs.core.Response;

042.

043. import org.jboss.as.quickstarts.kitchensink.data.MemberRepository;

044. import org.jboss.as.quickstarts.kitchensink.model.Member;

045. import org.jboss.as.quickstarts.kitchensink.service.MemberRegistration;

046.

047. /**

048. * JAX-RS Example

049. * <p/>

050. * This class produces a RESTful service to read/write the contents of the members table.

051. */

052. @Path("/members")

053. @RequestScoped

054. public class MemberResourceRESTService {

055. @Inject

056. private Logger log;

057.

058. @Inject

059. private Validator validator;

060.

061. @Inject

062. private MemberRepository repository;

063.

064. @Inject

065. MemberRegistration registration;

066.

067. @GET

JBoss AS 7.1

JBoss Community Documentation Page of 62 295

068. @Produces(MediaType.APPLICATION_JSON)

069. public List<Member> listAllMembers() {

070. return repository.findAllOrderedByName();

071. }

072.

073. @GET

074. @Path("/{id:[0-9][0-9]*}")

075. @Produces(MediaType.APPLICATION_JSON)

076. public Member lookupMemberById(@PathParam("id") long id) {

077. Member member = repository.findById(id);

078. if (member == null) {

079. throw new WebApplicationException(Response.Status.NOT_FOUND);

080. }

081. return member;

082. }

083.

084. /**

085. * Creates a new member from the values provided. Performs validation, and will return

a JAX-RS response with either

086. * 200 ok, or with a map of fields, and related errors.

087. */

088. @POST

089. @Consumes(MediaType.APPLICATION_JSON)

090. @Produces(MediaType.APPLICATION_JSON)

091. public Response createMember(Member member) {

092.

093. Response.ResponseBuilder builder = null;

094.

095. try {

096. //Validates member using bean validation

097. validateMember(member);

098.

099. registration.register(member);

100.

101. //Create an "ok" response

102. builder = Response.ok();

103. } catch (ConstraintViolationException ce) {

104. //Handle bean validation issues

105. builder = createViolationResponse(ce.getConstraintViolations());

106. } catch (ValidationException e) {

107. //Handle the unique constrain violation

108. Map<String, String> responseObj = new HashMap<String, String>();

109. responseObj.put("email", "Email taken");

110. builder = Response.status(Response.Status.CONFLICT).entity(responseObj);

111. } catch (Exception e) {

112. // Handle generic exceptions

113. Map<String, String> responseObj = new HashMap<String, String>();

114. responseObj.put("error", e.getMessage());

115. builder = Response.status(Response.Status.BAD_REQUEST).entity(responseObj);

116. }

117.

118. return builder.build();

119. }

120.

121.

122. /**

123. * <p>Validates the given Member variable and throws validation exceptions based on the

type of error.

JBoss AS 7.1

JBoss Community Documentation Page of 63 295

124. * If the error is standard bean validation errors then it will throw a

ConstraintValidationException

125. * with the set of the constraints violated.</p>

126. * <p>If the error is caused because an existing member with the same email is

registered it throws a regular

127. * validation exception so that it can be interpreted separately.</p>

128. *

129. * @param member Member to be validated

130. * @throws ConstraintViolationException If Bean Validation errors exist

131. * @throws ValidationException If member with the same email already exists

132. */

133. private void validateMember(Member member) throws ConstraintViolationException,

ValidationException {

134. //Create a bean validator and check for issues.

135. Set<ConstraintViolation<Member>> violations = validator.validate(member);

136.

137. if (!violations.isEmpty()) {

138. throw new ConstraintViolationException(new

HashSet<ConstraintViolation<?>>(violations));

139. }

140.

141. //Check the uniqueness of the email address

142. if (emailAlreadyExists(member.getEmail())) {

143. throw new ValidationException("Unique Email Violation");

144. }

145. }

146.

147. /**

148. * Creates a JAX-RS "Bad Request" response including a map of all violation fields, and

their message.

149. * This can then be used by clients to show violations.

150. *

151. * @param violations A set of violations that needs to be reported

152. * @return JAX-RS response containing all violations

153. */

154. private Response.ResponseBuilder createViolationResponse(Set<ConstraintViolation<?>>

violations) {

155. log.fine("Validation completed. violations found: " + violations.size());

156.

157. Map<String, String> responseObj = new HashMap<String, String>();

158.

159. for (ConstraintViolation<?> violation : violations) {

160. responseObj.put(violation.getPropertyPath().toString(),

violation.getMessage());

161. }

162.

163. return Response.status(Response.Status.BAD_REQUEST).entity(responseObj);

164. }

165.

166. /**

167. * Checks if a member with the same email address is already registered. This is the

only way to

168. * easily capture the "@UniqueConstraint(columnNames = "email")" constraint from the

Member class.

169. *

170. * @param email The email to check

171. * @return True if the email already exists, and false otherwise

172. */

JBoss AS 7.1

JBoss Community Documentation Page of 64 295

173. public boolean emailAlreadyExists(String email) {

174. Member member = null;

175. try {

176. member = repository.findByEmail(email);

177. } catch (NoResultException e) {

178. // ignore

179. }

180. return member != null;

181. }

182. }

Line

number

Note

20 The annotation tells JAX-RS that this class provides a REST endpoint mapped to @Path

(concatenating the path from the activator with the path for this endpoint).rest/members

23, 24 JAX-RS endpoints are CDI enabled, and can use CDI-style injection.

26 - 35 The method is called when the raw endpoint is accessed and offers up alistAllMembers()

list of endpoints. Notice that the object is automatically mapped to XML by JAXB.

37 - 42 The method is called when the endpoint is accessed with a member idlookupMemberById()

parameter appended (for example rest/members/1). Again, the object is automatically mapped

to XML by JAXB.

6.2.1 Arquillian

If you've been following along with the Test Driven Development craze of the past few years, you're probably

getting a bit nervous by now, wondering how on earth you are going to test your application. Lucky for you,

the Arquillian project is here to help!

Arquillian provides all the boiler plate for running your test inside JBoss AS, allowing you to concentrate on

testing your application. In order to do that, it utilizes Shrinkwrap, a fluent API for defining packaging, to

create an archive to deploy. We'll go through the testcase, and how you configure Arquillian in just a

moment, but first let's run the test.

Before we start, we need to let Arquillian know the path to our JBoss AS install. Open up

and set the property to the path to your JBoss ASsrc/test/resources/arquillian.xml jbossHome

install:

JBoss AS 7.1

JBoss Community Documentation Page of 65 295

Now, make sure JBoss AS is not running (so that the instance started for running the test does not interfere),

and then run the tests from the command line by typing:

mvn clean test -Parq-jbossas-managed

You should see JBoss AS start up, a deployed, test executed, and then the results displayed totest.war

you on the console:

$ > mvn clean test -Parq-jbossas-managed

[INFO] Scanning for projects...

[INFO]

[INFO] ------------------------------------------------------------------------

[INFO] Building JBoss AS Quickstarts: Kitchensink 7.0.0-SNAPSHOT

[INFO] ------------------------------------------------------------------------

[INFO]

[INFO] --- maven-clean-plugin:2.4.1:clean (default-clean) @ jboss-as-kitchensink ---

[INFO] Deleting /Users/pmuir/workspace/jboss-as-docs/quickstarts/kitchensink/target

[INFO]

[INFO] --- maven-resources-plugin:2.4.3:resources (default-resources) @ jboss-as-kitchensink ---

[INFO] Using 'UTF-8' encoding to copy filtered resources.

[INFO] Copying 2 resources

[INFO]

[INFO] --- maven-compiler-plugin:2.3.1:compile (default-compile) @ jboss-as-kitchensink ---

[INFO] Compiling 6 source files to

/Users/pmuir/workspace/jboss-as-docs/quickstarts/kitchensink/target/classes

[INFO]

[INFO] --- maven-resources-plugin:2.4.3:testResources (default-testResources) @

jboss-as-kitchensink ---

[INFO] Using 'UTF-8' encoding to copy filtered resources.

[INFO] Copying 1 resource

[INFO]

[INFO] --- maven-compiler-plugin:2.3.1:testCompile (default-testCompile) @ jboss-as-kitchensink

---

[INFO] Compiling 1 source file to

/Users/pmuir/workspace/jboss-as-docs/quickstarts/kitchensink/target/test-classes

[INFO]

[INFO] --- maven-surefire-plugin:2.7.2:test (default-test) @ jboss-as-kitchensink ---

[INFO] Surefire report directory:

/Users/pmuir/workspace/jboss-as-docs/quickstarts/kitchensink/target/surefire-reports

-------------------------------------------------------

T E S T S

-------------------------------------------------------

Running org.jboss.as.quickstarts.kitchensink.test.MemberRegistrationTest

Jun 25, 2011 7:17:49 PM

org.jboss.arquillian.container.impl.client.container.ContainerRegistryCreator

getActivatedConfiguration

INFO: Could not read active container configuration: null

log4j:WARN No appenders could be found for logger (org.jboss.remoting).

log4j:WARN Please initialize the log4j system properly.

Jun 25, 2011 7:17:54 PM org.jboss.as.arquillian.container.managed.ManagedDeployableContainer

startInternal

JBoss AS 7.1

JBoss Community Documentation Page of 66 295

INFO: Starting container with: [java, -Djboss.home.dir=/Users/pmuir/development/jboss,

-Dorg.jboss.boot.log.file=/Users/pmuir/development/jboss/standalone/log/boot.log,

-Dlogging.configuration=file:/Users/pmuir/development/jboss/standalone/configuration/logging.properties,

-jar, /Users/pmuir/development/jboss/jboss-modules.jar, -mp,

/Users/pmuir/development/jboss/modules, -logmodule, org.jboss.logmanager, -jaxpmodule,

javax.xml.jaxp-provider, org.jboss.as.standalone, -server-config, standalone.xml]

19:17:55,107 INFO [org.jboss.modules] JBoss Modules version 1.0.0.CR4

19:17:55,329 INFO [org.jboss.msc] JBoss MSC version 1.0.0.CR2

19:17:55,386 INFO [org.jboss.as] JBoss AS 7.0.0.Beta4-SNAPSHOT "(TBD)" starting

19:17:56,159 INFO [org.jboss.as] creating http management service using network interface

(management) port (9990) securePort (-1)

19:17:56,181 INFO [org.jboss.as.logging] Removing bootstrap log handlers

19:17:56,189 INFO [org.jboss.as.naming] (Controller Boot Thread) Activating Naming Subsystem

19:17:56,203 INFO [org.jboss.as.naming] (MSC service thread 1-4) Starting Naming Service

19:17:56,269 INFO [org.jboss.as.security] (Controller Boot Thread) Activating Security

Subsystem

19:17:56,305 INFO [org.jboss.remoting] (MSC service thread 1-1) JBoss Remoting version

3.2.0.Beta2

19:17:56,317 INFO [org.xnio] (MSC service thread 1-1) XNIO Version 3.0.0.Beta3

19:17:56,331 INFO [org.xnio.nio] (MSC service thread 1-1) XNIO NIO Implementation Version

3.0.0.Beta3

19:17:56,522 INFO [org.jboss.as.connector.subsystems.datasources] (Controller Boot Thread)

Deploying JDBC-compliant driver class org.h2.Driver (version 1.2)

19:17:56,572 INFO [org.apache.catalina.core.AprLifecycleListener] (MSC service thread 1-7) The

Apache Tomcat Native library which allows optimal performance in production environments was not

found on the java.library.path:

.:/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java

19:17:56,627 INFO [org.jboss.as.remoting] (MSC service thread 1-3) Listening on /127.0.0.1:9999

19:17:56,641 INFO [org.jboss.as.jmx.JMXConnectorService] (MSC service thread 1-2) Starting

remote JMX connector

19:17:56,705 INFO [org.jboss.as.ee] (Controller Boot Thread) Activating EE subsystem

19:17:56,761 INFO [org.apache.coyote.http11.Http11Protocol] (MSC service thread 1-7) Starting

Coyote HTTP/1.1 on http--127.0.0.1-8080

19:17:56,793 INFO [org.jboss.as.connector] (MSC service thread 1-3) Starting JCA Subsystem

(JBoss IronJacamar 1.0.0.CR2)

19:17:56,837 INFO [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-2)

Bound data source [java:jboss/datasources/ExampleDS]

19:17:57,335 INFO [org.jboss.as.server.deployment] (MSC service thread 1-1) Starting deployment

of "arquillian-service"

19:17:57,348 INFO [org.jboss.as.deployment] (MSC service thread 1-7) Started

FileSystemDeploymentService for directory /Users/pmuir/development/jboss/standalone/deployments

19:17:57,693 INFO [org.jboss.as] (Controller Boot Thread) JBoss AS 7.0.0.Beta4-SNAPSHOT "(TBD)"

started in 2806ms - Started 111 of 138 services (27 services are passive or on-demand)

19:18:00,596 INFO [org.jboss.as.server.deployment] (MSC service thread 1-6) Stopped deployment

arquillian-service in 8ms

19:18:01,394 INFO [org.jboss.as.server.deployment] (pool-2-thread-7) Content added at location

/Users/pmuir/development/jboss/standalone/data/content/0a/9e20b7bc978fd2778b89c7c06e4d3e1f308dfe/content19:18:01,403

INFO [org.jboss.as.server.deployment] (MSC service thread 1-7) Starting deployment of

"arquillian-service"

19:18:01,650 INFO [org.jboss.as.server.deployment] (pool-2-thread-6) Content added at location

/Users/pmuir/development/jboss/standalone/data/content/94/8324ab8f5a693c67fa57b59323304d3947bbf6/content19:18:01,659

INFO [org.jboss.as.server.deployment] (MSC service thread 1-5) Starting deployment of

"test.war"

19:18:01,741 INFO [org.jboss.jpa] (MSC service thread 1-7) read persistence.xml for primary

19:18:01,764 INFO [org.jboss.weld] (MSC service thread 1-3) Processing CDI deployment: test.war

19:18:01,774 INFO

[org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service

thread 1-3) JNDI bindings for session bean named MemberRegistration in deployment unit

JBoss AS 7.1

JBoss Community Documentation Page of 67 295

deployment "test.war" are as follows:

java:global/test/MemberRegistration!org.jboss.as.quickstarts.kitchensink.controller.MemberRegistration

java:app/test/MemberRegistration!org.jboss.as.quickstarts.kitchensink.controller.MemberRegistration

java:module/MemberRegistration!org.jboss.as.quickstarts.kitchensink.controller.MemberRegistration

java:global/test/MemberRegistration

java:app/test/MemberRegistration

java:module/MemberRegistration

19:18:01,908 INFO [org.jboss.weld] (MSC service thread 1-5) Starting Services for CDI

deployment: test.war

19:18:02,131 INFO [org.jboss.weld.Version] (MSC service thread 1-5) WELD-000900 1.1.1 (Final)

19:18:02,169 INFO [org.jboss.weld] (MSC service thread 1-2) Starting weld service

19:18:02,174 INFO [org.jboss.as.arquillian] (MSC service thread 1-3) Arquillian deployment

detected:

ArquillianConfig[service=jboss.arquillian.config."test.war",unit=test.war,tests=[org.jboss.as.quickstarts.kitchensink.test.MemberRegistrationTest]]19:18:02,179

INFO [org.jboss.jpa] (MSC service thread 1-6) starting Persistence Unit Service

'test.war#primary'

19:18:02,322 INFO [org.hibernate.annotations.common.Version] (MSC service thread 1-6) Hibernate

Commons Annotations 3.2.0.Final

19:18:02,328 INFO [org.hibernate.cfg.Environment] (MSC service thread 1-6) HHH00412:Hibernate

[WORKING]

19:18:02,330 INFO [org.hibernate.cfg.Environment] (MSC service thread 1-6)

HHH00206:hibernate.properties not found

19:18:02,332 INFO [org.hibernate.cfg.Environment] (MSC service thread 1-6) HHH00021:Bytecode

provider name : javassist

19:18:02,354 INFO [org.hibernate.ejb.Ejb3Configuration] (MSC service thread 1-6)

HHH00204:Processing PersistenceUnitInfo [

name: primary

...]

19:18:02,400 WARN [org.hibernate.cfg.AnnotationBinder] (MSC service thread 1-6)

HHH00194:Package not found or wo package-info.java: org.jboss.as.quickstarts.kitchensink.test

19:18:02,400 WARN [org.hibernate.cfg.AnnotationBinder] (MSC service thread 1-6)

HHH00194:Package not found or wo package-info.java:

org.jboss.as.quickstarts.kitchensink.controller

19:18:02,401 WARN [org.hibernate.cfg.AnnotationBinder] (MSC service thread 1-6)

HHH00194:Package not found or wo package-info.java: org.jboss.as.quickstarts.kitchensink.util

19:18:02,401 WARN [org.hibernate.cfg.AnnotationBinder] (MSC service thread 1-6)

HHH00194:Package not found or wo package-info.java: org.jboss.as.quickstarts.kitchensink.model

19:18:02,592 INFO [org.hibernate.service.jdbc.connections.internal.ConnectionProviderInitiator]

(MSC service thread 1-6) HHH00130:Instantiating explicit connection provider:

org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider

19:18:02,852 INFO [org.hibernate.dialect.Dialect] (MSC service thread 1-6) HHH00400:Using

dialect: org.hibernate.dialect.H2Dialect

19:18:02,858 WARN [org.hibernate.dialect.H2Dialect] (MSC service thread 1-6) HHH00431:Unable to

determine H2 database version, certain features may not work

19:18:02,862 INFO [org.hibernate.engine.jdbc.internal.LobCreatorBuilder] (MSC service thread

1-6) HHH00423:Disabling contextual LOB creation as JDBC driver reported JDBC version [3] less

than 4

19:18:02,870 INFO [org.hibernate.engine.transaction.internal.TransactionFactoryInitiator] (MSC

service thread 1-6) HHH00268:Transaction strategy:

org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory

19:18:02,874 INFO [org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory] (MSC service

thread 1-6) HHH00397:Using ASTQueryTranslatorFactory

19:18:02,911 INFO [org.hibernate.validator.util.Version] (MSC service thread 1-6) Hibernate

Validator 4.1.0.Final

19:18:02,917 INFO [org.hibernate.validator.engine.resolver.DefaultTraversableResolver] (MSC

service thread 1-6) Instantiated an instance of

JBoss AS 7.1

JBoss Community Documentation Page of 68 295

org.hibernate.validator.engine.resolver.JPATraversableResolver.

19:18:03,079 INFO [org.hibernate.tool.hbm2ddl.SchemaExport] (MSC service thread 1-6)

HHH00227:Running hbm2ddl schema export

19:18:03,093 INFO [org.hibernate.tool.hbm2ddl.SchemaExport] (MSC service thread 1-6)

HHH00230:Schema export complete

19:18:03,217 INFO [org.jboss.web] (MSC service thread 1-5) registering web context: /test

19:18:03,407 WARN [org.jboss.weld.Bean] (RMI TCP Connection(3)-127.0.0.1) WELD-000018 Executing

producer field or method [method] @Produces public

org.jboss.as.quickstarts.kitchensink.test.MemberRegistrationTest.produceLog(InjectionPoint) on

incomplete declaring bean Managed Bean [class

org.jboss.as.quickstarts.kitchensink.test.MemberRegistrationTest] with qualifiers [@Any

@Default] due to circular injection

19:18:03,427 WARN [org.jboss.weld.Bean] (RMI TCP Connection(3)-127.0.0.1) WELD-000018 Executing

producer field or method [method] @Produces public

org.jboss.as.quickstarts.kitchensink.test.MemberRegistrationTest.produceLog(InjectionPoint) on

incomplete declaring bean Managed Bean [class

org.jboss.as.quickstarts.kitchensink.test.MemberRegistrationTest] with qualifiers [@Any

@Default] due to circular injection

19:18:03,450 WARN [org.jboss.as.ejb3.component.EJBComponent] (RMI TCP Connection(3)-127.0.0.1)

EJBTHREE-2120: deprecated getTransactionAttributeType method called (dev problem)

19:18:03,459 INFO [org.jboss.as.quickstarts.kitchensink.controller.MemberRegistration] (RMI TCP

Connection(3)-127.0.0.1) Registering Jane Doe

19:18:03,616 INFO [org.jboss.as.quickstarts.kitchensink.test.MemberRegistrationTest] (RMI TCP

Connection(3)-127.0.0.1) Jane Doe was persisted with id 1

19:18:03,686 INFO [org.jboss.jpa] (MSC service thread 1-1) stopping Persistence Unit Service

'test.war#primary'

19:18:03,687 INFO [org.hibernate.tool.hbm2ddl.SchemaExport] (MSC service thread 1-1)

HHH00227:Running hbm2ddl schema export

19:18:03,690 INFO [org.jboss.weld] (MSC service thread 1-3) Stopping weld service

19:18:03,692 INFO [org.hibernate.tool.hbm2ddl.SchemaExport] (MSC service thread 1-1)

HHH00230:Schema export complete

19:18:03,704 INFO [org.jboss.as.server.deployment] (MSC service thread 1-8) Stopped deployment

test.war in 52ms

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 14.859 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------

[INFO] BUILD SUCCESS

[INFO] ------------------------------------------------------------------------

[INFO] Total time: 22.305s

[INFO] Finished at: Sat Jun 25 19:18:04 BST 2011

[INFO] Final Memory: 17M/125M

[INFO] ------------------------------------------------------------------------

$ >

As you can see, that didn't take too long (approximately 15s), and is great for running in your QA

environment, but if you running locally, you might prefer to connect to a running JBoss AS. To do that, start

up JBoss AS (as described in ). Now, run your test, but use the Getting started with JBoss AS

profile:arq-jbossas-remote

mvn clean test -Parq-jbossas-remote

JBoss AS 7.1

JBoss Community Documentation Page of 69 295

$> mvn clean test -Parq-jbossas-remote

[INFO] Scanning for projects...

[INFO]

[INFO] ------------------------------------------------------------------------

[INFO] Building JBoss AS Quickstarts: Kitchensink 7.0.0-SNAPSHOT

[INFO] ------------------------------------------------------------------------

[INFO]

[INFO] --- maven-clean-plugin:2.4.1:clean (default-clean) @ jboss-as-kitchensink ---

[INFO] Deleting /Users/pmuir/workspace/jboss-as-docs/quickstarts/kitchensink/target

[INFO]

[INFO] --- maven-resources-plugin:2.4.3:resources (default-resources) @ jboss-as-kitchensink ---

[INFO] Using 'UTF-8' encoding to copy filtered resources.

[INFO] Copying 2 resources

[INFO]

[INFO] --- maven-compiler-plugin:2.3.1:compile (default-compile) @ jboss-as-kitchensink ---

[INFO] Compiling 6 source files to

/Users/pmuir/workspace/jboss-as-docs/quickstarts/kitchensink/target/classes

[INFO]

[INFO] --- maven-resources-plugin:2.4.3:testResources (default-testResources) @

jboss-as-kitchensink ---

[INFO] Using 'UTF-8' encoding to copy filtered resources.

[INFO] Copying 1 resource

[INFO]

[INFO] --- maven-compiler-plugin:2.3.1:testCompile (default-testCompile) @ jboss-as-kitchensink

---

[INFO] Compiling 1 source file to

/Users/pmuir/workspace/jboss-as-docs/quickstarts/kitchensink/target/test-classes

[INFO]

[INFO] --- maven-surefire-plugin:2.7.2:test (default-test) @ jboss-as-kitchensink ---

[INFO] Surefire report directory:

/Users/pmuir/workspace/jboss-as-docs/quickstarts/kitchensink/target/surefire-reports

-------------------------------------------------------

T E S T S

-------------------------------------------------------

Running org.jboss.as.quickstarts.kitchensink.test.MemberRegistrationTest

Jun 25, 2011 7:22:28 PM

org.jboss.arquillian.container.impl.client.container.ContainerRegistryCreator

getActivatedConfiguration

INFO: Could not read active container configuration: null

log4j:WARN No appenders could be found for logger

(org.jboss.as.arquillian.container.MBeanServerConnectionProvider).

log4j:WARN Please initialize the log4j system properly.

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 4.13 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------

[INFO] BUILD SUCCESS

[INFO] ------------------------------------------------------------------------

[INFO] Total time: 10.474s

[INFO] Finished at: Sat Jun 25 19:22:33 BST 2011

[INFO] Final Memory: 17M/125M

JBoss AS 7.1

JBoss Community Documentation Page of 70 295

[INFO] ------------------------------------------------------------------------

$ >

Arquillian defines two modes, and . The mode will take care of startingmanaged remote managed

and stopping the server for you, whilst the mode connects to an already running server.remote

This time you can see the test didn't start JBoss AS (if you check the instance you started, you will see the

application was deployed there), and the test ran a lot faster (approximately 4s).

We can also run the test from Eclipse, in both managed and remote modes. First, we'll run in in managed

mode. In order to set up the correct dependencies on your classpath, right click on the project, and select

:Properties

JBoss AS 7.1

JBoss Community Documentation Page of 71 295

Now, locate the Maven panel:

JBoss AS 7.1

JBoss Community Documentation Page of 72 295

And activate the profile:arq-jbossas-managed

JBoss AS 7.1

JBoss Community Documentation Page of 73 295

Finally, hit , and then confirm you want to update the project configuration:Ok

Once the project has built, locate the in , right click on theMemberRegistrationTest src/test/java

test, and choose :Run As -> JUnit Test...

JBoss AS 7.1

JBoss Community Documentation Page of 74 295

You should see JBoss AS start in the Eclipse Console, the test be deployed, and finally the JUnit View pop

up with the result (a pass of course!).

We can also run the test in an already running instance of Eclipse. Simply change the active profile to

:arq-jbossas-remote

JBoss AS 7.1

JBoss Community Documentation Page of 75 295

Now, make sure JBoss AS is running, right click on the test case and choose :Run As -> JUnit Test

JBoss AS 7.1

JBoss Community Documentation Page of 76 295

Again, you'll see the test run in the server, and the JUnit View pop up, with the test passing.

So far so good, the test is running in both Eclipse and from the command line. But what does the test look

like?

JBoss AS 7.1

JBoss Community Documentation Page of 77 295

MemberRegistrationTest.java

23. import javax.inject.Inject;

24.

25. import org.jboss.arquillian.container.test.api.Deployment;

26. import org.jboss.arquillian.junit.Arquillian;

27. import org.jboss.as.quickstarts.kitchensink.model.Member;

28. import org.jboss.as.quickstarts.kitchensink.service.MemberRegistration;

29. import org.jboss.as.quickstarts.kitchensink.util.Resources;

30. import org.jboss.shrinkwrap.api.Archive;

31. import org.jboss.shrinkwrap.api.ShrinkWrap;

32. import org.jboss.shrinkwrap.api.asset.EmptyAsset;

33. import org.jboss.shrinkwrap.api.spec.WebArchive;

34. import org.junit.Test;

35. import org.junit.runner.RunWith;

36.

37. @RunWith(Arquillian.class)

38. public class MemberRegistrationTest {

39. @Deployment

40. public static Archive<?> createTestArchive() {

41. return ShrinkWrap.create(WebArchive.class, "test.war")

42. .addClasses(Member.class, MemberRegistration.class, Resources.class)

43. .addAsResource("META-INF/test-persistence.xml", "META-INF/persistence.xml")

44. .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")

45. // Deploy our test datasource

46. .addAsWebInfResource("test-ds.xml", "test-ds.xml");

47. }

48.

49. @Inject

50. MemberRegistration memberRegistration;

51.

52. @Inject

53. Logger log;

54.

55. @Test

56. public void testRegister() throws Exception {

57. Member newMember = new Member();

58. newMember.setName("Jane Doe");

59. newMember.setEmail("[email protected]");

60. newMember.setPhoneNumber("2125551234");

61. memberRegistration.register(newMember);

62. assertNotNull(newMember.getId());

63. log.info(newMember.getName() + " was persisted with id " + newMember.getId());

64. }

65.

66. }

Line

number

Note

23 tells JUnit to hand control over to Arquillian when executing@RunWith(Arquillian.class)

tests

JBoss AS 7.1

JBoss Community Documentation Page of 78 295

25 The annotation identifies the static method to Arquillian@Deployment createTestArchive

as the one to use to determine which resources and classes to deploy

28 We add just the classes needed for the test, no more

29 We also add as our test is going to use the databasepersistence.xml

30 Of course, we must add to enable CDIbeans.xml

24 - 28 Arquillian allows us to inject beans into the test case

41 - 49 The test method works as you would expect - creates a new member, registers them, and then

verifies that the member was created

As you can see, Arquillian has lived up to the promise - the test case is focused on to test (the what

method) and to test (the method). It's also worth noting that this isn't a simplistic@Deployment how @Test

unit test - this is a fully fledged integration test that uses the database.

Now, let's look at how we configure Arquillian. First of all, let's take a look at in arquillian.xml

.src/test/resources

JBoss AS 7.1

JBoss Community Documentation Page of 79 295

arquillian.xml

02. <!-- JBoss, Home of Professional Open Source Copyright 2012, Red Hat, Inc.

03. and/or its affiliates, and individual contributors by the @authors tag. See

04. the copyright.txt in the distribution for a full listing of individual contributors.

05. Licensed under the Apache License, Version 2.0 (the "License"); you may not

06. use this file except in compliance with the License. You may obtain a copy

07. of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required

08. by applicable law or agreed to in writing, software distributed under the

09. License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS

10. OF ANY KIND, either express or implied. See the License for the specific

11. language governing permissions and limitations under the License. -->

12. <arquillian xmlns="http://jboss.org/schema/arquillian"

13. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

14. xsi:schemaLocation="http://jboss.org/schema/arquillian

15. http://jboss.org/schema/arquillian/arquillian_1_0.xsd">

16.

17. <!-- Uncomment to have test archives exported to the file system for inspection -->

18. <!-- <engine> -->

19. <!-- <property name="deploymentExportPath">target/</property> -->

20. <!-- </engine> -->

21.

22. <!-- Force the use of the Servlet 3.0 protocol with all containers, as it is the most

mature -->

23. <defaultProtocol type="Servlet 3.0" />

24.

25. <!-- Example configuration for a remote JBoss AS 7 instance -->

26. <container qualifier="jboss" default="true">

27. <!-- If you want to use the JBOSS_HOME environment variable, just delete the jbossHome

property -->

28. <configuration>

29. <property name="jbossHome">/path/to/jboss/as</property>

30. </configuration>

31. </container>

32.

33. </arquillian>

Line

number

Note

9 Arquillian deploys the test war to JBoss AS, and doesn't write it to disk. For debugging, it can be

very useful to see exactly what is in your war, so Arquillian allows you to export the war when

the tests runs

13 - 17 Arquillian currently needs configuring to use JMX to connect to JBoss AS

Now, we need to look at how we select between containers in the :pom.xml

JBoss AS 7.1

JBoss Community Documentation Page of 80 295

pom.xml

197. <source>1.6</source>

198. <target>1.6</target>

199. </configuration>

200. </plugin>

201. <plugin>

202. <artifactId>maven-war-plugin</artifactId>

203. <version>2.1.1</version>

204. <configuration>

205. <!-- Java EE 6 doesn't require web.xml, Maven needs to

206. catch up! -->

207. <failOnMissingWebXml>false</failOnMissingWebXml>

208. </configuration>

209. </plugin>

210. <!-- The JBoss AS plugin deploys your war to a local JBoss AS

211. container -->

212. <!-- To use, run: mvn package jboss-as:deploy -->

213. <plugin>

214. <groupId>org.jboss.as.plugins</groupId>

215. <artifactId>jboss-as-maven-plugin</artifactId>

216. <version>7.1.1.Final</version>

217. </plugin>

218. </plugins>

219. </build>

220.

221. <profiles>

222. <profile>

223. <!-- The default profile skips all tests, though you can tune

224. it to run just unit tests based on a custom pattern -->

225. <!-- Seperate profiles are provided for running all tests, including

226. Arquillian tests that execute in the specified container -->

227. <id>default</id>

Line

number

Note

204 The profile needs an id so we can activate from Eclipse or the command line

206 - 211 Arquillian decides which container to use depending on your classpath. Here we define the

managed JBoss AS container.

222 - 217 Arquillian decides which container to use depending on your classpath. Here we define the

remote JBoss AS container.

And that's it! As you can see Arquillian delivers simple and true testing. You can concentrate on writing your

test functionality, and run your tests in the same environment in which you will run your application.

Arquillian also offers other containers, allowing you to run your tests against Weld Embedded

(super fast, but your enterprise services are mocked), GlassFish, and more

JBoss AS 7.1

JBoss Community Documentation Page of 81 295

That concludes our tour of the kitchensink quickstart. If you would like to use this project as a basis for your

own application on JBoss AS, you can of course copy this application sources and modify it.

JBoss AS 7.1

JBoss Community Documentation Page of 82 295

7 OSGi: Helloworld OSGi quickstartThis quickstart shows you how to create and deploy a simple OSGi Bundle.

What is OSGi?

OSGi is a new feature in JBoss AS 7. It provides standards-based modularity and micro-services

as defined in the OSGi 4.2 Core Specifications. You can deploy OSGi bundles directly into JBoss

AS.

For more information on OSGi and on how to develop OSGi bundles, see the OSGi 4.2 Core

and the .Specification OSGi 4.2 Core Javadoc

More information on the OSGi component in JBoss AS can be found on the JBoss OSGi project

.pages

Switch to the directory and instruct Maven to build and deploy thequickstarts/helloworld-osgi

application:

mvn package jboss-as:deploy

Now, you should see the OSGi subsystem start up, and the bundle deployed and started:

JBoss AS 7.1

JBoss Community Documentation Page of 83 295

If you wish to undeploy the quickstart, or redeploy after making some changes, it's pretty easy:

- deploy any changes to the application to the application servermvn jboss-as:deploy

- undeploy the example from JBoss ASmvn jboss-as:undeploy

7.1 The Helloworld OSGi example in depth

The OSGi Bundle has one Java Source file, the Bundle Activator:

JBoss AS 7.1

JBoss Community Documentation Page of 84 295

Activator.java

01. package org.jboss.as.quickstarts.helloworld.osgi;

02.

03. import org.osgi.framework.BundleActivator;

04. import org.osgi.framework.BundleContext;

05.

06. public class Activator implements BundleActivator {

07. public void start(BundleContext context) throws Exception {

08. System.out.println("Hello AS7 World!!");

09. }

10.

11. public void stop(BundleContext context) throws Exception {

12. System.out.println("Bye AS7 World!!");

13. }

14. }

The bundle activator is very simple, and just prints out a message when the bundle starts and stops -

allowing you to verify that OSGi is working properly.

Now, let's look at the , where we create the bundle:pom.xml

pom.xml

002. <project xmlns="http://maven.apache.org/POM/4.0.0"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

003. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0

004. http://maven.apache.org/maven-v4_0_0.xsd">

005. <modelVersion>4.0.0</modelVersion>

006.

007. <groupId>org.jboss.as.quickstarts</groupId>

008. <artifactId>jboss-as-helloworld-osgi</artifactId>

009. <version>7.0.0-SNAPSHOT</version>

010. <packaging>bundle</packaging>

011. <name>JBoss AS Quickstarts: Helloworld OSGi</name>

012.

013. <url>http://jboss.org/jbossas/osgi</url>

014. <licenses>

015. <license>

016. <name>GNU Lesser General Public License</name>

017. <url>http://www.gnu.org/copyleft/lesser.html</url>

018. <distribution>repo</distribution>

019. </license>

020. </licenses>

021.

022. <properties>

023. <!-- Explicitly declaring the source encoding eliminates the following message: -->

024. <!-- [WARNING] Using platform encoding (UTF-8 actually) to copy filtered

025. resources, i.e. build is platform dependent! -->

026. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

027. </properties>

028.

029. <!-- Include the JBoss Maven repository so we can access JBoss artifacts -->

030. <repositories>

JBoss AS 7.1

JBoss Community Documentation Page of 85 295

031. <repository>

032. <id>jboss-public-repository</id>

033. <name>JBoss Repository</name>

034. <url>https://repository.jboss.org/nexus/content/groups/public

035. </url>

036. <releases>

037. <enabled>true</enabled>

038. </releases>

039. <snapshots>

040. <enabled>false</enabled>

041. </snapshots>

042. </repository>

043. </repositories>

044.

045. <pluginRepositories>

046. <pluginRepository>

047. <id>jboss-public-repository</id>

048. <name>JBoss Repository</name>

049. <url>https://repository.jboss.org/nexus/content/groups/public

050. </url>

051. <releases>

052. <enabled>true</enabled>

053. </releases>

054. <snapshots>

055. <enabled>false</enabled>

056. </snapshots>

057. </pluginRepository>

058. </pluginRepositories>

059.

060. <dependencies>

061. <dependency>

062. <groupId>org.osgi</groupId>

063. <artifactId>org.osgi.core</artifactId>

064. <version>4.2.0</version>

065. <scope>provided</scope>

066. </dependency>

067. </dependencies>

068.

069. <build>

070. <plugins>

071. <plugin>

072. <!-- This plugin takes care of packaging the artifact as an OSGi Bundle -->

073. <groupId>org.apache.felix</groupId>

074. <artifactId>maven-bundle-plugin</artifactId>

075. <version>2.3.4</version>

076. <extensions>true</extensions>

077. <configuration>

078. <instructions>

079. <!-- OSGi Manifest Metadata is specified here -->

080. <!-- The Bundle SymbolicName is the same as the artifact ID -->

081. <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>

082.

083. <!-- Specify the Bundle activator, which is invoked when

084. the Bundle is started -->

085.

<Bundle-Activator>org.jboss.as.quickstarts.helloworld.osgi.Activator</Bundle-Activator>

086.

087. <!-- Automatically compute all the necessary Import-Package statements

JBoss AS 7.1

JBoss Community Documentation Page of 86 295

-->

088. <Import-Package>*</Import-Package>

089.

090. <!-- This bundle does not export any packages -->

091. <Export-Package/>

092.

093. <!-- Packages that are not exported but need to be included

094. need to be listed as Private-Package -->

095.

<Private-Package>org.jboss.as.quickstarts.helloworld.osgi</Private-Package>

096. </instructions>

097. </configuration>

098. </plugin>

099.

100. <!-- JBoss AS plugin to deploy war -->

101. <plugin>

102. <groupId>org.jboss.as.plugins</groupId>

103. <artifactId>jboss-as-maven-plugin</artifactId>

104. <version>7.0.0.Beta5-SNAPSHOT</version>

105. <configuration>

106. <filename>${project.build.finalName}.jar</filename>

107. </configuration>

108. </plugin>

109. </plugins>

110. </build>

111. </project>

Line

numbers

Note

10 The packaging of the maven module is set to . This instructs maven and thebundle

maven-bundle-plugin to create an OSGi bundle.

62 - 67 Since the activator uses an OSGi interface, these are provided through the OSGi interfaces

artifact.

66 Use the scope for dependencies that are either provided by the OSGi frameworkprovided

(i.e. JBoss AS) itself or for dependencies that are provided through separate bundles.

71 - 98 The is used to create a bundle. You can configure it create importmaven-bundle-plugin

and export statements, and to specify the activator in use. You can read more about the OSGi

on the Apache Felix site.Bundle Maven Plugin

100 -

108

We can use the Maven plugin to deploy the bundle to JBoss AS as usual.jboss-as

As you can see, using OSGi with JBoss AS is pretty easy!

7.2 Creating a new OSGi bundle using Eclipse

Eclipse has built-in support for creating OSGi bundles. Eclipse is built on OSGi, therefore support for

developing OSGi bundles inside Eclipse is quite extensive.

JBoss AS 7.1

JBoss Community Documentation Page of 87 295

To quickly create an OSGi Bundle using Eclipse, follow these steps. In Eclipse do File -> New ->

:Project -> Plug-in Project

Select as the Target Platform a 'Standard' OSGi Framework and click .Next >

On the following page, you can specify the Bundle Symbolic Name, version, Bundle Activator and some

other details. You may use the defaults, or, for example, you could put the Activator in a different package,

e.g. .org.jboss.as.quickstarts.helloworld.osgi.Activator

Click again.Next >

On the Templates page select the 'Hello OSGi Bundle' template and click Finish:

JBoss AS 7.1

JBoss Community Documentation Page of 88 295

After clicking , the Plug-In Development perspective will open with the Manifest Editor. The ManifestFinish

Editor facilitates editing of the OSGi Metadata, such as the Imported Packages in the tab andDependencies

Exported Packages on the tab:Runtime

JBoss AS 7.1

JBoss Community Documentation Page of 89 295

Click on the link in the Manifest editor to open the Bundle Activator in the Java editor.Activator

JBoss AS 7.1

JBoss Community Documentation Page of 90 295

When finished making changes you can export your OSGi bundle so that it can be deployed directly into

JBoss AS. Click on :File -> Export -> Deployable plug-ins and fragments

JBoss AS 7.1

JBoss Community Documentation Page of 91 295

You have now created an OSGi Bundle, and the JAR can be found in the directory of the locationplugins

specified in the screen above. You can deploy it to JBoss AS using any of the standard deployment

mechanisms described in the .Getting Started Guide

JBoss AS 7.1

JBoss Community Documentation Page of 92 295

8 EJB: Invocation from remote clients using JNDI:

ejb-remote quickstartThis chapter explains how to invoke EJBs from a remote client by using the JNDI API to first lookup the bean

proxy and then invoke on that proxy.

After you have read this article, do remember to take a look at Remote EJB invocations via JNDI -

EJB client API or remote-naming project

Before getting into the details, we would like the users to know that we have introduced a new EJB client

API, which is a JBoss specific API and allows invocation on remote EJBs. This client API isn't based on

JNDI. So remote clients need not rely on JNDI API to invoke on EJBs. A separate document covering the

EJB remote client API will be made available. For now, you can refer to the javadocs of the EJB client

project at . In this document, we'll just concentrate on the traditional JNDIhttp://docs.jboss.org/ejbclient/

based invocation on EJBs. So let's get started:

8.1 Deploying your EJBs on the server side:

Users who already have EJBs deployed on the server side can just skip to the next section.

As a first step, you'll have to deploy your application containing the EJBs on the AS7 server. If you want

those EJBs to be remotely invocable, then you'll have to expose atleast one remote view for that bean. In

this example, let's consider a simple Calculator stateless bean which exposes a RemoteCalculator remote

business interface. We'll also have a simple stateful CounterBean which exposes a RemoteCounter remote

business interface. Here's the code:

package org.jboss.as.quickstarts.ejb.remote.stateless;

/**

* @author Jaikiran Pai

*/

public interface RemoteCalculator {

int add(int a, int b);

int subtract(int a, int b);

}

JBoss AS 7.1

JBoss Community Documentation Page of 93 295

package org.jboss.as.quickstarts.ejb.remote.stateless;

import javax.ejb.Remote;

import javax.ejb.Stateless;

/**

* @author Jaikiran Pai

*/

@Stateless

@Remote(RemoteCalculator.class)

public class CalculatorBean implements RemoteCalculator {

@Override

public int add(int a, int b) {

return a + b;

}

@Override

public int subtract(int a, int b) {

return a - b;

}

}

package org.jboss.as.quickstarts.ejb.remote.stateful;

/**

* @author Jaikiran Pai

*/

public interface RemoteCounter {

void increment();

void decrement();

int getCount();

}

JBoss AS 7.1

JBoss Community Documentation Page of 94 295

package org.jboss.as.quickstarts.ejb.remote.stateful;

import javax.ejb.Remote;

import javax.ejb.Stateful;

/**

* @author Jaikiran Pai

*/

@Stateful

@Remote(RemoteCounter.class)

public class CounterBean implements RemoteCounter {

private int count = 0;

@Override

public void increment() {

this.count++;

}

@Override

public void decrement() {

this.count--;

}

@Override

public int getCount() {

return this.count;

}

}

Let's package this in a jar (how you package it in a jar is out of scope of this chapter) named

"jboss-as-ejb-remote-app.jar" and deploy it to the server. Make sure that your deployment has been

processed successfully and there aren't any errors.

8.2 Writing a remote client application for accessing

and invoking the EJBs deployed on the server

The next step is to write an application which will invoke the EJBs that you deployed on the server. In AS7,

you can either choose to use the JBoss specific EJB client API to do the invocation or use JNDI to lookup a

proxy for your bean and invoke on that returned proxy. In this chapter we will concentrate on the JNDI

lookup and invocation and will leave the EJB client API for a separate chapter.

So let's take a look at what the client code looks like for looking up the JNDI proxy and invoking on it. Here's

the entire client code which invokes on a stateless bean:

package org.jboss.as.quickstarts.ejb.remote.client;

import javax.naming.Context;

import javax.naming.InitialContext;

JBoss AS 7.1

JBoss Community Documentation Page of 95 295

import javax.naming.NamingException;

import java.security.Security;

import java.util.Hashtable;

import org.jboss.as.quickstarts.ejb.remote.stateful.CounterBean;

import org.jboss.as.quickstarts.ejb.remote.stateful.RemoteCounter;

import org.jboss.as.quickstarts.ejb.remote.stateless.CalculatorBean;

import org.jboss.as.quickstarts.ejb.remote.stateless.RemoteCalculator;

import org.jboss.sasl.JBossSaslProvider;

/**

* A sample program which acts a remote client for a EJB deployed on AS7 server.

* This program shows how to lookup stateful and stateless beans via JNDI and then invoke on

them

*

* @author Jaikiran Pai

*/

public class RemoteEJBClient {

public static void main(String[] args) throws Exception {

// Invoke a stateless bean

invokeStatelessBean();

// Invoke a stateful bean

invokeStatefulBean();

}

/**

* Looks up a stateless bean and invokes on it

*

* @throws NamingException

*/

private static void invokeStatelessBean() throws NamingException {

// Let's lookup the remote stateless calculator

final RemoteCalculator statelessRemoteCalculator = lookupRemoteStatelessCalculator();

System.out.println("Obtained a remote stateless calculator for invocation");

// invoke on the remote calculator

int a = 204;

int b = 340;

System.out.println("Adding " + a + " and " + b + " via the remote stateless calculator

deployed on the server");

int sum = statelessRemoteCalculator.add(a, b);

System.out.println("Remote calculator returned sum = " + sum);

if (sum != a + b) {

throw new RuntimeException("Remote stateless calculator returned an incorrect sum "

+ sum + " ,expected sum was " + (a + b));

}

// try one more invocation, this time for subtraction

int num1 = 3434;

int num2 = 2332;

System.out.println("Subtracting " + num2 + " from " + num1 + " via the remote stateless

calculator deployed on the server");

int difference = statelessRemoteCalculator.subtract(num1, num2);

System.out.println("Remote calculator returned difference = " + difference);

if (difference != num1 - num2) {

throw new RuntimeException("Remote stateless calculator returned an incorrect

difference " + difference + " ,expected difference was " + (num1 - num2));

}

JBoss AS 7.1

JBoss Community Documentation Page of 96 295

}

/**

* Looks up a stateful bean and invokes on it

*

* @throws NamingException

*/

private static void invokeStatefulBean() throws NamingException {

// Let's lookup the remote stateful counter

final RemoteCounter statefulRemoteCounter = lookupRemoteStatefulCounter();

System.out.println("Obtained a remote stateful counter for invocation");

// invoke on the remote counter bean

final int NUM_TIMES = 20;

System.out.println("Counter will now be incremented " + NUM_TIMES + " times");

for (int i = 0; i < NUM_TIMES; i++) {

System.out.println("Incrementing counter");

statefulRemoteCounter.increment();

System.out.println("Count after increment is " + statefulRemoteCounter.getCount());

}

// now decrementing

System.out.println("Counter will now be decremented " + NUM_TIMES + " times");

for (int i = NUM_TIMES; i > 0; i--) {

System.out.println("Decrementing counter");

statefulRemoteCounter.decrement();

System.out.println("Count after decrement is " + statefulRemoteCounter.getCount());

}

}

/**

* Looks up and returns the proxy to remote stateless calculator bean

*

* @return

* @throws NamingException

*/

private static RemoteCalculator lookupRemoteStatelessCalculator() throws NamingException {

final Hashtable jndiProperties = new Hashtable();

jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");

final Context context = new InitialContext(jndiProperties);

// The app name is the application name of the deployed EJBs. This is typically the ear

name

// without the .ear suffix. However, the application name could be overridden in the

application.xml of the

// EJB deployment on the server.

// Since we haven't deployed the application as a .ear, the app name for us will be an

empty string

final String appName = "";

// This is the module name of the deployed EJBs on the server. This is typically the jar

name of the

// EJB deployment, without the .jar suffix, but can be overridden via the ejb-jar.xml

// In this example, we have deployed the EJBs in a jboss-as-ejb-remote-app.jar, so the

module name is

// jboss-as-ejb-remote-app

final String moduleName = "jboss-as-ejb-remote-app";

// AS7 allows each deployment to have an (optional) distinct name. We haven't specified

a distinct name for

// our EJB deployment, so this is an empty string

final String distinctName = "";

// The EJB name which by default is the simple class name of the bean implementation

JBoss AS 7.1

JBoss Community Documentation Page of 97 295

class

final String beanName = CalculatorBean.class.getSimpleName();

// the remote view fully qualified class name

final String viewClassName = RemoteCalculator.class.getName();

// let's do the lookup

return (RemoteCalculator) context.lookup("ejb:" + appName + "/" + moduleName + "/" +

distinctName + "/" + beanName + "!" + viewClassName);

}

/**

* Looks up and returns the proxy to remote stateful counter bean

*

* @return

* @throws NamingException

*/

private static RemoteCounter lookupRemoteStatefulCounter() throws NamingException {

final Hashtable jndiProperties = new Hashtable();

jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");

final Context context = new InitialContext(jndiProperties);

// The app name is the application name of the deployed EJBs. This is typically the ear

name

// without the .ear suffix. However, the application name could be overridden in the

application.xml of the

// EJB deployment on the server.

// Since we haven't deployed the application as a .ear, the app name for us will be an

empty string

final String appName = "";

// This is the module name of the deployed EJBs on the server. This is typically the jar

name of the

// EJB deployment, without the .jar suffix, but can be overridden via the ejb-jar.xml

// In this example, we have deployed the EJBs in a jboss-as-ejb-remote-app.jar, so the

module name is

// jboss-as-ejb-remote-app

final String moduleName = "jboss-as-ejb-remote-app";

// AS7 allows each deployment to have an (optional) distinct name. We haven't specified

a distinct name for

// our EJB deployment, so this is an empty string

final String distinctName = "";

// The EJB name which by default is the simple class name of the bean implementation

class

final String beanName = CounterBean.class.getSimpleName();

// the remote view fully qualified class name

final String viewClassName = RemoteCounter.class.getName();

// let's do the lookup (notice the ?stateful string as the last part of the jndi name

for stateful bean lookup)

return (RemoteCounter) context.lookup("ejb:" + appName + "/" + moduleName + "/" +

distinctName + "/" + beanName + "!" + viewClassName + "?stateful");

}

}

The entire server side and client side code is hosted at the github repo here

https://github.com/jbossas/quickstart/tree/master/ejb-remote

JBoss AS 7.1

JBoss Community Documentation Page of 98 295

The code has some comments which will help you understand each of those lines. But we'll explain here in

more detail what the code does. As a first step in the client code, we'll do a lookup of the EJB using a JNDI

name. In AS7, for remote access to EJBs, you use the ejb: namespace with the following syntax:

For stateless beans:

ejb:<app-name>/<module-name>/<distinct-name>/<bean-name>!<fully-qualified-classname-of-the-remote-interface>

For stateful beans:

ejb:<app-name>/<module-name>/<distinct-name>/<bean-name>!<fully-qualified-classname-of-the-remote-interface>?stateful

The ejb: namespace identifies it as a EJB lookup and is a constant (i.e. doesn't change) for doing EJB

lookups. The rest of the parts in the jndi name are as follows:

: This is the name of the .ear (without the .ear suffix) that you have deployed on the server andapp-name

contains your EJBs.

Java EE 6 allows you to override the application name, to a name of your choice by setting it in the

application.xml. If the deployment uses uses such an override then the app-name used in the JNDI

name should match that name.

EJBs can also be deployed in a .war or a plain .jar (like we did in step 1). In such cases where the

deployment isn't an .ear file, then the app-name must be an empty string, while doing the lookup.

: This is the name of the .jar (without the .jar suffix) that you have deployed on the server andmodule-name

the contains your EJBs. If the EJBs are deployed in a .war then the module name is the .war name (without

the .war suffix).

Java EE 6 allows you to override the module name, by setting it in the ejb-jar.xml/web.xml of your

deployment. If the deployment uses such an override then the module-name used in the JNDI name

should match that name.

Module name part cannot be an empty string in the JNDI name

: This is a JBoss AS7 specific name which can be optionally assigned to the deploymentsdistinct-name

that are deployed on the server. More about the purpose and usage of this will be explained in a separate

chapter. If a deployment doesn't use distinct-name then, use an empty string in the JNDI name, for

distinct-name

: This is the name of the bean for which you are doing the lookup. The bean name is typicallybean-name

the unqualified classname of the bean implementation class, but can be overriden through either ejb-jar.xml

or via annotations. The bean name part cannot be an empty string in the JNDI name.

: This is the fully qualified class name of the interfacefully-qualified-classname-of-the-remote-interface

for which you are doing the lookup. The interface should be one of the remote interfaces exposed by the

bean on the server. The fully qualified class name part cannot be an empty string in the JNDI name.

JBoss AS 7.1

JBoss Community Documentation Page of 99 295

For stateful beans, the JNDI name expects an additional "?stateful" to be appended after the fully qualified

interface name part. This is because for stateful beans, a new session gets created on JNDI lookup and the

EJB client API implementation doesn't contact the server during the JNDI lookup to know what kind of a

bean the JNDI name represents (we'll come to this in a while). So the JNDI name itself is expected to

indicate that the client is looking up a stateful bean, so that an appropriate session can be created.

Now that we know the syntax, let's see our code and check what JNDI name it uses. Since our stateless

EJB named CalculatorBean is deployed in a jboss-as-ejb-remote-app.jar (without any ear) and since we are

looking up the org.jboss.as.quickstarts.ejb.remote.stateless.RemoteCalculator remote interface, our JNDI

name will be:

ejb:/jboss-as-ejb-remote-app//CalculatorBean!org.jboss.as.quickstarts.ejb.remote.stateless.RemoteCalculator

That's what the lookupRemoteStatelessCalculator() method in the above client code uses.

For the stateful EJB named CounterBean which is deployed in hte same jboss-as-ejb-remote-app.jar and

which exposes the org.jboss.as.quickstarts.ejb.remote.stateful.RemoteCounter, the JNDI name will be:

ejb:/jboss-as-ejb-remote-app//CounterBean!org.jboss.as.quickstarts.ejb.remote.stateful.RemoteCounter?stateful

That's what the lookupRemoteStatefulCounter() method in the above client code uses.

Now that we know of the JNDI name, let's take a look at the following piece of code in the

lookupRemoteStatelessCalculator():

final Hashtable jndiProperties = new Hashtable();

jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");

final Context context = new InitialContext(jndiProperties);

Here we are creating a JNDI InitialContext object by passing it some JNDI properties. The

Context.URL_PKG_PREFIXES is set to org.jboss.ejb.client.naming. This is necessary because we should

let the JNDI API know what handles the ejb: namespace that we use in our JNDI names for lookup. The

"org.jboss.ejb.client.naming" has a URLContextFactory implementation which will be used by the JNDI APIs

to parse and return an object for ejb: namespace lookups. You can either pass these properties to the

constructor of the InitialContext class or have a jndi.properites file in the classpath of the client application,

which (atleast) contains the following property:

java.naming.factory.url.pkgs=org.jboss.ejb.client.naming

So at this point, we have setup the InitialContext and also have the JNDI name ready to do the lookup. You

can now do the lookup and the appropriate proxy which will be castable to the remote interface that you

used as the fully qualified class name in the JNDI name, will be returned. Some of you might be wondering,

how the JNDI implementation knew which server address to look, for your deployed EJBs. The answer is in

AS7, the proxies returned via JNDI name lookup for ejb: namespace do not connect to the server unless an

invocation on those proxies is done.

JBoss AS 7.1

JBoss Community Documentation Page of 100 295

Now let's get to the point where we invoke on this returned proxy:

// Let's lookup the remote stateless calculator

final RemoteCalculator statelessRemoteCalculator = lookupRemoteStatelessCalculator();

System.out.println("Obtained a remote stateless calculator for invocation");

// invoke on the remote calculator

int a = 204;

int b = 340;

System.out.println("Adding " + a + " and " + b + " via the remote stateless calculator

deployed on the server");

int sum = statelessRemoteCalculator.add(a, b);

We can see here that the proxy returned after the lookup is used to invoke the add(...) method of the bean.

It's at this point that the JNDI implementation (which is backed by the JBoss EJB client API) needs to know

the server details. So let's now get to the important part of setting up the EJB client context properties.

8.3 Setting up EJB client context properties

A EJB client context is a context which contains contextual information for carrying out remote invocations

on EJBs. This is a JBoss specific API. The EJB client context can be associated with multiple EJB receivers.

Each EJB receiver is capable of handling invocations on different EJBs. For example, an EJB receiver "Foo"

might be able to handle invocation on a bean identified by

app-A/module-A/distinctinctName-A/Bar!RemoteBar, whereas a EJB receiver named "Blah" might be able to

handle invocation on a bean identified by app-B/module-B/distinctName-B/BeanB!RemoteBean. Each such

EJB receiver knows about what set of EJBs it can handle and each of the EJB receiver knows which server

target to use for handling the invocations on the bean. For example, if you have a AS7 server at 10.20.30.40

IP address which has its remoting port opened at 4447 and if that's the server on which you deployed that

CalculatorBean, then you can setup a EJB receiver which knows its target address is 10.20.30.40:4447.

Such an EJB receiver will be capable enough to communicate to the server via the JBoss specific EJB

remote client protocol (details of which will be explained in-depth in a separate chapter).

Now that we know what a EJB client context is and what a EJB receiver is, let's see how we can setup a

client context with 1 EJB receiver which can connect to 10.20.30.40 IP address at port 4447. That EJB client

context will then be used (internally) by the JNDI implementation to handle invocations on the bean proxy.

The client will have to place a jboss-ejb-client.properties file in the classpath of the application. The

jboss-ejb-client.properties can contain the following properties:

JBoss AS 7.1

JBoss Community Documentation Page of 101 295

endpoint.name=client-endpoint

remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false

remote.connections=default

remote.connection.default.host=10.20.30.40

remote.connection.default.port = 4447

remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false

remote.connection.default.username=appuser

remote.connection.default.password=apppassword

The above properties file is just an example. The actual file that was used for this sample program

is available here for reference

https://github.com/jbossas/quickstart/blob/master/ejb-remote/client/src/main/resources/jboss-ejb-client.properties

We'll see what each of it means.

First the endpoint.name property. We mentioned earlier that the EJB receivers will communicate with the

server for EJB invocations. Internally, they use JBoss Remoting project to carry out the communication. The

endpoint.name property represents the name that will be used to create the client side of the enpdoint. The

endpoint.name property is optional and if not specified in the jboss-ejb-client.properties file, it will default to

"config-based-ejb-client-endpoint" name.

Next is the remote.connectionprovider.create.options.<....> properties:

remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false

The "remote.connectionprovider.create.options." property prefix can be used to pass the options that will be

used while create the connection provider which will handle the "remote:" protocol. In this example we use

the "remote.connectionprovider.create.options." property prefix to pass the

"org.xnio.Options.SSL_ENABLED" property value as false. That property will then be used during the

connection provider creation. Similarly other properties can be passed too, just append it to the

"remote.connectionprovider.create.options." prefix

Next we'll see:

remote.connections=default

This is where you define the connections that you want to setup for communication with the remote server.

The "remote.connections" property uses a comma separated value of connection "names". The connection

names are just logical and are used grouping together the connection configuration properties later on in the

properties file. The example above sets up a single remote connection named "default". There can be more

than one connections that are configured. For example:

JBoss AS 7.1

JBoss Community Documentation Page of 102 295

remote.connections=one, two

Here we are listing 2 connections named "one" and "two". Ultimately, each of the connections will map to a

EJB receiver. So if you have 2 connections, that will setup 2 EJB receivers that will be added to the EJB

client context. Each of these connections will be configured with the connection specific properties as

follows:

remote.connection.default.host=10.20.30.40

remote.connection.default.port = 4447

remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false

As you can see we are using the "remote.connection.<connection-name>." prefix for specifying the

connection specific property. The connection name here is "default" and we are setting the "host" property of

that connection to point to 10.20.30.40. Similarly we set the "port" for that connection to 4447.

By default AS7 uses 4447 as the remoting port. The EJB client API uses the remoting port for

communicating with the server for remote invocations, so that's the port we use in our client

programs (unless the server is configured for some other remoting port)

remote.connection.default.username=appuser

remote.connection.default.password=apppassword

The given user/password must be set by using the command bin/add-user.sh (or.bat).

The user and password must be set because the security-realm is enabled for the subsystem remoting (see

standalone*.xml or domain.xml) by default.

If you do not need the security for remoting you might remove the attribute security-realm in the

configuration.

security-realm is possible since 7.1.0.FINAL and enabled by default.

We then use the "remote.connection.<connection-name>.connect.options." property prefix to setup options

that will be used during the connection creation.

Here's an example of setting up multiple connections with different properties for each of those:

JBoss AS 7.1

JBoss Community Documentation Page of 103 295

remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false

remote.connections=one, two

remote.connection.one.host=localhost

remote.connection.one.port=6999

remote.connection.one.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false

remote.connection.two.host=localhost

remote.connection.two.port=7999

remote.connection.two.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false

As you can see we setup 2 connections "one" and "two" which both point to "localhost" as the "host" but

different ports. Each of these connections will internally be used to create the EJB receivers in the EJB client

context.

So that's how the jboss-ejb-client.properties file can be setup and placed in the classpath.

8.4 Using a different file for setting up EJB client

context

The EJB client code will by default look for jboss-ejb-client.properties in the classpath. However, you can

specify a different file of your choice by setting the "jboss.ejb.client.properties.file.path" system property

which points to a properties file on your filesystem, containing the client context configurations. An example

for that would be

"-Djboss.ejb.client.properties.file.path=/home/me/my-client/custom-jboss-ejb-client.properties"

8.5 Setting up the client classpath with the jars that are

required to run the client application

Starting JBoss AS 7.1.0.Final, a jboss-client jar is shipped in the distribution. It's available at

JBOSS_HOME/bin/client/jboss-client-7.1.0.Final.jar. Place this jar in the classpath of your client application.

If you are using Maven to build the client application, then please follow the instructions in the

JBOSS_HOME/bin/client/README.txt to add this jar as a Maven dependency.

8.6 Summary

In the above examples, we saw what it takes to invoke a EJB from a remote client. To summarize:

On the server side you need to deploy EJBs which expose the remote views.

JBoss AS 7.1

JBoss Community Documentation Page of 104 295

On the client side you need a client program which:

Has a jboss-ejb-client.properties in its classpath to setup the server connection information

Either has a jndi.properties to specify the java.naming.factory.url.pkgs property or passes that

as a property to the InitialContext constructor

Setup the client classpath to include the jboss-client jar that's required for remote invocation of

the EJBs. The location of the jar is mentioned above. You'll also need to have your

application's bean interface jars and other jars that are required by your application, in the

client classpath

JBoss AS 7.1

JBoss Community Documentation Page of 105 295

9 Creating your own applicationWhat we didn't tell you about the is that it is generated from a Maven archetype. UsingKitchensink quickstart

this archetype offers you the perfect opportunity to generate your own project.

Watch and learn

To use the archetype to generate a new project, you should run:

mvn archetype:generate \

-DarchetypeArtifactId=jboss-javaee6-webapp-archetype \

-DarchetypeGroupId=org.jboss.spec.archetypes \

-DarchetypeVersion=7.0.2.CR2 \

Maven will download the archetype and it's dependencies, and ask you some questions:

JBoss AS 7.1

JBoss Community Documentation Page of 106 295

$> mvn archetype:generate \

-DarchetypeArtifactId=jboss-javaee6-webapp-archetype \

-DarchetypeGroupId=org.jboss.spec.archetypes \

-DarchetypeVersion=7.0.2.CR2 \

[INFO] Scanning for projects...

[INFO]

[INFO] ------------------------------------------------------------------------

[INFO] Building Maven Stub Project (No POM) 1

[INFO] ------------------------------------------------------------------------

[INFO]

.........

Define value for property 'groupId': : com.acme.corp

Define value for property 'artifactId': : acme-sales

Define value for property 'version': 1.0-SNAPSHOT: :

Define value for property 'package': com.acme.corp: :

[INFO] Using property: name = Java EE 6 webapp project

Confirm properties configuration:

groupId: com.acme.corp

artifactId: acme-sales

version: 1.0-SNAPSHOT

package: com.acme.corp

name: Java EE 6 webapp project

Y: :

[WARNING] CP Don't override file

/Users/pmuir/tmp/acme-sales/.settings/org.eclipse.jdt.apt.core.prefs

[INFO] ------------------------------------------------------------------------

[INFO] BUILD SUCCESS

[INFO] ------------------------------------------------------------------------

[INFO] Total time: 14.774s

[INFO] Finished at: Mon Jun 06 18:53:38 BST 2011

[INFO] Final Memory: 7M/125M

[INFO] ------------------------------------------------------------------------

$>

  Instruction

1 Enter the you wish to usegroupId

2 Enter the you wish to useartifactId

3 Enter the version you wish to use, or just hit if you wish to accept the default Enter 1.0-SNAPSHOT

4 Enter the java package you wish to use, or just hit if you wish to accept the default (which isEnter

copied from ).groupId

5 Finally, if you are happy with your choices, hit and Maven will generate the project for you.Enter

And that's it, you now have a brand new project with the same functionality as , butkitchensink

customized with your details.

JBoss AS 7.1

JBoss Community Documentation Page of 107 295

A blank canvas?

The archetype contains some sample code to get you started. If you would prefer a blank canvas,

with only a project skeleton, then use as yourjboss-javaee6-webapp-archetype-blank

archetype id.

Prefer Enterprise Applications (EARs)?

The archetype generates a WAR project. With Java EE 6, you can include EJBs in your WAR,

meaning you won't need an EAR until you need to divide your code into modules. If you would like

to create an EAR based project then use as yourjboss-javaee6-webapp-ear-archetype

archetype id (or if you want a blank EAR, then

).jboss-javaee6-webapp-ear-archetype-blank

Of course, you can create a project from the archetype using Eclipse, saving you the step of importing it.

First, choose :File -> New -> Other

Select the wizard:Maven Project

JBoss AS 7.1

JBoss Community Documentation Page of 108 295

If you wish, customize the project creation, otherwise, just hit :Next >

JBoss AS 7.1

JBoss Community Documentation Page of 109 295

Locate the archetype:jboss-javaee6-webapp-archetype

The image below is out of date, and the archetype id has changed to

jboss-javaee6-webapp-archetype

JBoss AS 7.1

JBoss Community Documentation Page of 110 295

Now hit .Ok

Next, fill in the and , and hit :groupId artifactId Finish

JBoss AS 7.1

JBoss Community Documentation Page of 111 295

You should now have a brand new project:

JBoss AS 7.1

JBoss Community Documentation Page of 112 295

Enjoy!

JBoss AS 7.1

JBoss Community Documentation Page of 113 295

10 More Resources

Getting

Started

Guide

The Getting Started Guide covers topics such as server layout (what you can configure

where), data source definition, and using the web management interface.

Torquebox Torque Box allows you to use all the familiar services from JBoss AS 7, but with Ruby.

JBoss AS 7

FAQ

Frequently Asked Questions for JBoss AS 7

JBoss AS 7.1

JBoss Community Documentation Page of 114 295

11 All JBoss AS 7 documentationThere are several guides in the JBoss Application Server 7 documentation series. This list gives an overview

of each of the guides:

* - Explains how to download and start JBoss Application Server 7.Getting Started Guide

* - Talks you through developing your first applications onGetting Started Developing Applications Guide

JBoss Application Server 7, and introduces you to JBoss Tools and how to deploy your applications.

* - A Java EE 6 Tutorial.JavaEE 6 Tutorial

* - Tells you how to configure and manage your JBoss Application Server 7 instances.Admin Guide

* - Contains concepts that you need to be aware of when developing applications for JBossDeveloper Guide

Application Server 7. Classloading is explained in depth.

* - Reference guide for how to set up clustered JBoss Application Server 7 instances.High Availability Guide

* - A guide to adding new functionality to JBoss Application Server 7.Extending JBoss AS 7

JBoss AS 7.1

JBoss Community Documentation Page of 115 295

12 IntroductionThis guide will walk you through installing and starting up JBoss Application Server 7. It will then introduce

key features of the Java EE 6 (Web Profile) programming model, of which JBoss AS 7 is a certified

implementation.

Java EE 6

The Java EE 6 platform offers developers the ability to write distributed, transactional and portable

applications quickly and easily. We class applications that require these capabilities "enterprise

applications". These applications must be fast, secure and reliable.

Java EE has always offered strong messaging (JMS), transactional (JTA) and resource (JCA)

capabilities as well as exposing web services via SOAP (JAX-WS). Java EE 5 started a radical shift

for the programming model, offering a powerful, declarative and lightweight object-relational

mapper (JPA) and annotation-driven, lightweight access to enterprise services (EJB 3). Java EE 6

added a type-safe, loosely coupled programming model (CDI), declarative validation of constraints

(Bean Validation) and RESTful web services (JAX-RS) to produce a complete, modern

development environment.

JBoss AS 7 departs from the familiar structure of previous JBoss AS versions, so we recommend all

developers follow the steps in to install and start up the application server forGetting started with JBoss AS

the first time.

JBoss AS 7 comes with a series of quickstarts aimed to get you up to writing applications with minimal fuss.

We recommend that you work through the quickstarts in the order they are presented in this guide, however

if you have previous experience with Java EE 6, you may wish to skip some or all of the quickstarts:

Core  

Helloworld

quickstart

If you have previously developed applications using technologies such as JSF or Wicket,

and EJB or Spring, you may wish to skip this quickstart.

Numberguess

quickstart

If you have previously developed applications using technologies such as JSF or Wicket,

EJB or Spring, and JPA or Hibernate you may wish to skip this quickstart.

Login

quickstart

If you are a Java EE wizard you may wish to skip this quickstart.

Kitchensink

quickstart

A great starting point for your project.

Optional  

JBoss AS 7.1

JBoss Community Documentation Page of 116 295

Helloworld

OSGi

quickstart

If you want to get started with OSGi in JBoss AS, check out this quickstart.

12.1 Downloading the quickstarts

The quickstarts are distributed alongside JBoss AS (in a separate zip from the runtime) and are available for

download from . Make sure you download the latest zip!the JBoss AS download page

JBoss AS 7.1

JBoss Community Documentation Page of 117 295

13 Getting started with JBoss ASTo run the examples with the provided build scripts, you'll need the following:

Java 1.6, to run JBoss AS and Maven

Maven 3, to build and deploy the examples

the JBoss AS 7 distribution zip

the JBoss AS 7 quickstarts zip

If you already have any of these pieces of software, there is no need to install them again!

Choose your Java runtime, and follow their installation instructions. For example, you could choose one of:

OpenJDK

Oracle Java SE

Oracle JRockit

Follow the official Maven installation guide if you don't already have Maven 3 installed. You can check which

version of Maven you have installed (if any) by running . If you see a version newer thanmvn --version

3.0.0, you are ready to go.

You can also deploy the examples using your favorite IDE. We provide instructions for using Eclipse only.

Now, download JBoss AS 7 from the .JBoss AS download page

JBoss AS 7 offers the ability to manage multiple AS instances from a single control point. A

collection of such servers are referred to as members of a "domain", with a single Domain

Controller process acting as the management control point. Domains can span multiple physical (or

virtual) machines, with all AS instances on a given host under the control of a Host Controller

process. The Host Controllers interact with the Domain Controller to control the lifecycle of the AS

instances running on that host and to assist the Domain Controller in managing them.

JBoss AS 7 also offers a standalone mode, which is perfect for a single server. We use this

throughout the quickstart examples.

13.1 Installing and starting JBoss AS on Linux, Unix or

Mac OS X

First, let's verify that verify that both Java and Maven are correctly installed. In a console, type:

java -version

JBoss AS 7.1

JBoss Community Documentation Page of 118 295

You should see a version string (at least ) printed. If not, contact your provider of Java for assistance.1.6.0

Next, type:

mvn --version

You should see a version string (at lest ) printed. If not, contact the Maven community for assistance.3.0.0

Next, we need to choose a location for JBoss AS to live. By default, JBoss AS 7 will be extracted into

(where 7.x.x.x matches the version you downloaded):jboss-7.x.x.x

unzip jboss-7.x.x.x.zip

Now, let's start JBoss AS in standalone mode:

jboss-7.x.x.x/bin/standalone.sh

If you want to stop JBoss AS, simply press whilst the terminal has focus.Crtl-C

That's it, JBoss AS is installed and running! Visit to check the server has startedhttp://localhost:8080/

properly.

You can find the server log for standalone instances in

. The Getting Started Guide covers more onjboss-7.x.x.x/standalone/log/server.log

configuring logging.

13.2 Installing and starting JBoss AS on Windows

First, let's verify that verify that both Java and Maven are correctly installed. In a Command Prompt, type:

java -version

You should see a version string (at least ) printed. If not, contact your provider of Java for assistance.1.6.0

Next, type:

mvn --version

You should see a version string (at lest ) printed. If not, contact the Maven community for assistance.3.0.0

JBoss AS 7.1

JBoss Community Documentation Page of 119 295

Next, we need to choose a location for JBoss AS to live. By default, JBoss AS 7 will be extracted into

(where 7.x.x.x matches the version you downloaded). Unzip JBoss AS using your tool ofjboss-7.x.x.x

choice.

Finally, let's start JBoss AS in standalone mode. Locate your JBoss AS installation and run

located in .standalone.bat bin

If you want to stop JBoss AS, simply press whilst the terminal has focus.Crtl-C

That's it, JBoss AS is installed and running! Visit to check the server has startedhttp://localhost:8080/

properly.

You can find the server log for standalone instances in

. The Getting Started Guide covers more onjboss-7.x.x.x/standalone/log/server.log

configuring logging.

13.3 Starting JBoss AS from Eclipse with JBoss Tools

You may choose to use Eclipse rather than the command line to run JBoss AS, and to deploy the examples.

If you don't wish to use Eclipse, you should skip this section.

In order to use JBoss AS from Eclipse, you must first install JBoss AS for your operating system as

described in or Installing and starting JBoss AS on Linux, Unix or Mac OS X Installing and starting

.JBoss AS on Windows

In order use JBoss AS from Eclipse, you'll need Eclipse Indigo (Eclipse 3.7) and JBoss Tools 3.3 M2 or

newer. If you want to run the quickstarts from Eclipse, you will also need m2eclipse. You can find

instructions for installing Eclipse, m2eclipse and JBoss Tools on the . Make sure you installJBoss Tools Site

the and features.Maven Support Web and Java EE Development

Having successfully installed and started Eclipse, we need to add our JBoss AS instance to it. First, navigate

to :File -> New -> Other

JBoss AS 7.1

JBoss Community Documentation Page of 120 295

Now, locate the New Server Wizard:

JBoss AS 7.1

JBoss Community Documentation Page of 121 295

And choose JBoss AS 7.0:

JBoss AS 7.1

JBoss Community Documentation Page of 122 295

Hit , and locate the JBoss AS 7 installation by clicking on :Next > Browse ...

JBoss AS 7.1

JBoss Community Documentation Page of 123 295

Now, choose the JBoss AS 7 installation directory:

JBoss AS 7.1

JBoss Community Documentation Page of 124 295

Assuming you selected a valid installation, Eclipse should now allow you to hit :Finish

JBoss AS 7.1

JBoss Community Documentation Page of 125 295

Now, let's start JBoss AS from Eclipse. If you previously started JBoss AS from the command line, you

should stop it there first.

First, we need to make sure the tab is on view. Open the Server Window -> Show View -> Other...

dialog:

JBoss AS 7.1

JBoss Community Documentation Page of 126 295

And select the view:Server

JBoss AS 7.1

JBoss Community Documentation Page of 127 295

You should see the appear with the JBoss AS server:Server View

Now, we can start the server. Right click on the server in the view, and select :Server Start

JBoss AS 7.1

JBoss Community Documentation Page of 128 295

If you want to debug your application, you can simply select rather than . This willDebug Start

start the server in debug mode, and automatically attach the Eclipse debugger.

You'll see the server output in the :Console

That's it, we now have the server up and running in Eclipse!

13.4 Importing the quickstarts into Eclipse

In order to import the quickstarts into Eclipse, you will need m2eclipse installed. You can find instructions for

installing Eclipse, m2eclipse and JBoss Tools on the JBoss AS site.

JBoss AS 7.1

JBoss Community Documentation Page of 129 295

First, choose :File -> Import...

Select :Existing Maven Projects

JBoss AS 7.1

JBoss Community Documentation Page of 130 295

Click on , and navigate to the directory:Browse quickstarts/

JBoss AS 7.1

JBoss Community Documentation Page of 131 295

Finally, make sure all 4 quickstarts are found and selected, and click :Finish

JBoss AS 7.1

JBoss Community Documentation Page of 132 295

Eclipse should now successfully import 4 projects:

JBoss AS 7.1

JBoss Community Documentation Page of 133 295

It will take a short time to import the projects, as Maven needs to download the project's dependencies from

remote repositories.

13.5 Managing JBoss Application Server

Here we will quickly outline how you can access both the command line interface and the web management

interface for managing JBoss AS. Detailed information for both can be found in the .Admin Guide

When the server is running, the web management interface can be accessed at http://localhost:9990/console

. You can use the web management interface to create datasources, manage deployments and configure

the server.

JBoss AS also comes with a command line interface. To run it on Linux, Unix or Mac, execute:

jboss-7.x.x.x/bin/jboss-admin.sh --connect

Or, on Windows:

jboss-7.x.x.x/bin/jboss-admin.bat --connect

Once started, type to discover the commands available to you.help

Throughout this guide we use the maven plugin to deploy and undeploy applications. This pluginjboss-as

uses the JBoss AS Native Java Detyped Management API to communicate with the server. The Detyped

API is used by management tools to control an entire domain of servers, and exposes only a small number

of types, allowing for backwards and forwards compatibility.

JBoss AS 7.1

JBoss Community Documentation Page of 134 295

13.6 Installing and starting JBoss AS on Linux, Unix or

Mac OS X

First, let's verify that verify that both Java and Maven are correctly installed. In a console, type:

java -version

You should see a version string (at least ) printed. If not, contact your provider of Java for assistance.1.6.0

Next, type:

mvn --version

You should see a version string (at lest ) printed. If not, contact the Maven community for assistance.3.0.0

Next, we need to choose a location for JBoss AS to live. By default, JBoss AS 7 will be extracted into

(where 7.x.x.x matches the version you downloaded):jboss-7.x.x.x

unzip jboss-7.x.x.x.zip

Now, let's start JBoss AS in standalone mode:

jboss-7.x.x.x/bin/standalone.sh

If you want to stop JBoss AS, simply press whilst the terminal has focus.Crtl-C

That's it, JBoss AS is installed and running! Visit to check the server has startedhttp://localhost:8080/

properly.

You can find the server log for standalone instances in

. The Getting Started Guide covers more onjboss-7.x.x.x/standalone/log/server.log

configuring logging.

13.7 Installing and starting JBoss AS on Windows

First, let's verify that verify that both Java and Maven are correctly installed. In a Command Prompt, type:

java -version

JBoss AS 7.1

JBoss Community Documentation Page of 135 295

You should see a version string (at least ) printed. If not, contact your provider of Java for assistance.1.6.0

Next, type:

mvn --version

You should see a version string (at lest ) printed. If not, contact the Maven community for assistance.3.0.0

Next, we need to choose a location for JBoss AS to live. By default, JBoss AS 7 will be extracted into

(where 7.x.x.x matches the version you downloaded). Unzip JBoss AS using your tool ofjboss-7.x.x.x

choice.

Finally, let's start JBoss AS in standalone mode. Locate your JBoss AS installation and run

located in .standalone.bat bin

If you want to stop JBoss AS, simply press whilst the terminal has focus.Crtl-C

That's it, JBoss AS is installed and running! Visit to check the server has startedhttp://localhost:8080/

properly.

You can find the server log for standalone instances in

. The Getting Started Guide covers more onjboss-7.x.x.x/standalone/log/server.log

configuring logging.

13.8 Starting JBoss AS from Eclipse with JBoss Tools

You may choose to use Eclipse rather than the command line to run JBoss AS, and to deploy the examples.

If you don't wish to use Eclipse, you should skip this section.

In order to use JBoss AS from Eclipse, you must first install JBoss AS for your operating system as

described in or Installing and starting JBoss AS on Linux, Unix or Mac OS X Installing and starting

.JBoss AS on Windows

In order use JBoss AS from Eclipse, you'll need Eclipse Indigo (Eclipse 3.7) and JBoss Tools 3.3 M2 or

newer. If you want to run the quickstarts from Eclipse, you will also need m2eclipse. You can find

instructions for installing Eclipse, m2eclipse and JBoss Tools on the . Make sure you installJBoss Tools Site

the and features.Maven Support Web and Java EE Development

Having successfully installed and started Eclipse, we need to add our JBoss AS instance to it. First, navigate

to :File -> New -> Other

JBoss AS 7.1

JBoss Community Documentation Page of 136 295

Now, locate the New Server Wizard:

JBoss AS 7.1

JBoss Community Documentation Page of 137 295

And choose JBoss AS 7.0:

JBoss AS 7.1

JBoss Community Documentation Page of 138 295

Hit , and locate the JBoss AS 7 installation by clicking on :Next > Browse ...

JBoss AS 7.1

JBoss Community Documentation Page of 139 295

Now, choose the JBoss AS 7 installation directory:

JBoss AS 7.1

JBoss Community Documentation Page of 140 295

Assuming you selected a valid installation, Eclipse should now allow you to hit :Finish

JBoss AS 7.1

JBoss Community Documentation Page of 141 295

Now, let's start JBoss AS from Eclipse. If you previously started JBoss AS from the command line, you

should stop it there first.

First, we need to make sure the tab is on view. Open the Server Window -> Show View -> Other...

dialog:

JBoss AS 7.1

JBoss Community Documentation Page of 142 295

And select the view:Server

JBoss AS 7.1

JBoss Community Documentation Page of 143 295

You should see the appear with the JBoss AS server:Server View

Now, we can start the server. Right click on the server in the view, and select :Server Start

JBoss AS 7.1

JBoss Community Documentation Page of 144 295

If you want to debug your application, you can simply select rather than . This willDebug Start

start the server in debug mode, and automatically attach the Eclipse debugger.

You'll see the server output in the :Console

That's it, we now have the server up and running in Eclipse!

13.9 Importing the quickstarts into Eclipse

In order to import the quickstarts into Eclipse, you will need m2eclipse installed. You can find instructions for

installing Eclipse, m2eclipse and JBoss Tools on the JBoss AS site.

JBoss AS 7.1

JBoss Community Documentation Page of 145 295

First, choose :File -> Import...

Select :Existing Maven Projects

JBoss AS 7.1

JBoss Community Documentation Page of 146 295

Click on , and navigate to the directory:Browse quickstarts/

JBoss AS 7.1

JBoss Community Documentation Page of 147 295

Finally, make sure all 4 quickstarts are found and selected, and click :Finish

JBoss AS 7.1

JBoss Community Documentation Page of 148 295

Eclipse should now successfully import 4 projects:

JBoss AS 7.1

JBoss Community Documentation Page of 149 295

It will take a short time to import the projects, as Maven needs to download the project's dependencies from

remote repositories.

13.10 Managing JBoss Application Server

Here we will quickly outline how you can access both the command line interface and the web management

interface for managing JBoss AS. Detailed information for both can be found in the .Admin Guide

When the server is running, the web management interface can be accessed at http://localhost:9990/console

. You can use the web management interface to create datasources, manage deployments and configure

the server.

JBoss AS also comes with a command line interface. To run it on Linux, Unix or Mac, execute:

jboss-7.x.x.x/bin/jboss-admin.sh --connect

Or, on Windows:

jboss-7.x.x.x/bin/jboss-admin.bat --connect

Once started, type to discover the commands available to you.help

Throughout this guide we use the maven plugin to deploy and undeploy applications. This pluginjboss-as

uses the JBoss AS Native Java Detyped Management API to communicate with the server. The Detyped

API is used by management tools to control an entire domain of servers, and exposes only a small number

of types, allowing for backwards and forwards compatibility.

JBoss AS 7.1

JBoss Community Documentation Page of 150 295

14 Helloworld quickstartThis quickstart shows you how to deploy a simple servlet to JBoss AS. The business logic is encapsulated in

a service, which is provided as a CDI bean, and injected into the Servlet.

Contexts and Dependency Injection for Java EE

CDI is a new specification in Java EE 6, inspired by JBoss Seam and Google Guice, and also

drawing on lessons learned from frameworks such as Spring. It allows application developers to

concentrate on developing their application logic by providing the ability to wire services together,

and abstract out orthogonal concerns, all in a type safe manner.

Switch to the directory and instruct Maven to build and deploy the application:quickstarts/helloworld

mvn package jboss-as:deploy

The quickstart uses a Maven plugin to deploy the application. The plugin requires JBoss AS to be running

(you can find out how to start the server in or Installing and starting JBoss AS on Linux, Unix or Mac OS X

).Installing and starting JBoss AS on Windows

Now, check if the application has deployed properly by clicking . Ifhttp://localhost:8080/jboss-as-helloworld

you see a "Hello World" message it's all working!

Should you wish to undeploy the quickstart, or redeploy after making some changes, it's pretty

easy:

- deploy any changes to the application to the application servermvn jboss-as:deploy

- undeploy the example from JBoss ASmvn jboss-as:undeploy

It's time to pull the covers back and dive into the internals of the example application.

14.1 Deploying the Helloworld example using Eclipse

You may choose to deploy the example using Eclipse. You'll need to have JBoss AS started in Eclipse (as

described in ) and to have imported the quickstarts intoStarting JBoss AS from Eclipse with JBoss Tools

Eclipse (as described in ).Importing the quickstarts into Eclipse

With the quickstarts imported, you can deploy the example by right clicking on the jboss-as-helloworld

project, and choosing :Run As -> Run On Server

JBoss AS 7.1

JBoss Community Documentation Page of 151 295

Make sure the JBoss AS server is selected, and hit :Finish

JBoss AS 7.1

JBoss Community Documentation Page of 152 295

You should see JBoss AS start up (unless you already started it in Starting JBoss AS from Eclipse with

) and the application deploy in the Console log:JBoss Tools

14.2 The helloworld example in depth

JBoss AS 7.1

JBoss Community Documentation Page of 153 295

The helloworld is very simple - all it does is print "Hello World" onto a web page.

The helloworld example is comprised a servlet and a CDI bean. We also include an empty file,beans.xml

which tells JBoss AS to look for beans in this application and to activate the CDI. is located in beans.xml

, which can be found in the directory of the example. Also in this directory weWEB-INF src/main/webapp

include which uses a simple meta refresh to send the users browser to the Servlet, which isindex.html

located at .http://localhost:8080/jboss-as-helloworld/HelloWorld

All the configuration files for this example are located in , which can be found in the WEB-INF/

directory of the example.src/main/webapp

Notice that we don't even need a !web.xml

Let's start by taking a look at the servlet:

HelloWorldServlet.java

27. import javax.servlet.http.HttpServletResponse;

28.

29. /**

30. * <p>

31. * A simple servlet taking advantage of features added in 3.0.

32. * </p>

33. *

34. * <p>

35. * The servlet is registered and mapped to /HelloServlet using the {@linkplain WebServlet

36. * @HttpServlet}. The {@link HelloService} is injected by CDI.

37. * </p>

38. *

39. * @author Pete Muir

40. *

41. */

42. @SuppressWarnings("serial")

43. @WebServlet("/HelloWorld")

44. public class HelloWorldServlet extends HttpServlet {

45.

46. static String PAGE_HEADER = "<html><head><title>helloworld</title><body>";

47.

48. static String PAGE_FOOTER = "</body></html>";

49.

50. @Inject

51. HelloService helloService;

52.

53. @Override

54. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws

ServletException, IOException {

55. PrintWriter writer = resp.getWriter();

56. writer.println(PAGE_HEADER);

57. writer.println("<h1>" + helloService.createHelloMessage("World") + "</h1>");

58. writer.println(PAGE_FOOTER);

59. writer.close();

60. }

61.

62. }

JBoss AS 7.1

JBoss Community Documentation Page of 154 295

Line Note

27 If you've used Servlet before, then you'll remember having to use xml to register your servlets.

Fortunately, this is a thing of the past. Now all you need to do is add the annotation,@WebServlet

and provide a mapping to a URL used to access the servlet. Much cleaner!

30-32 Every web page needs to be correctly formed HTML. We've created static Strings to hold the

minimum header and footer to write out.

34,35 We inject the HelloService (a CDI bean) which generates the actual message. This allows to alter

the implementation of at a later date without changing the view layer at allHelloService

(assuming we don't alter the API of ).HelloService

41 We call into the service to generate the message "Hello World", and write it out to the HTTP

request.

The package declaration and imports have been excluded from these listings. The complete listing

is

available in the example source code.

Now we understand how the information is sent to the browser, let's take a look at the service.

HelloService.java

public class HelloService {

String createHelloMessage(String name) {

return "Hello " + name + "!";

}

}

The service is very simple - no registration (XML or annotation) is required!

14.3 Deploying the Helloworld example using Eclipse

You may choose to deploy the example using Eclipse. You'll need to have JBoss AS started in Eclipse (as

described in ) and to have imported the quickstarts intoStarting JBoss AS from Eclipse with JBoss Tools

Eclipse (as described in ).Importing the quickstarts into Eclipse

With the quickstarts imported, you can deploy the example by right clicking on the jboss-as-helloworld

project, and choosing :Run As -> Run On Server

JBoss AS 7.1

JBoss Community Documentation Page of 155 295

Make sure the JBoss AS server is selected, and hit :Finish

JBoss AS 7.1

JBoss Community Documentation Page of 156 295

You should see JBoss AS start up (unless you already started it in Starting JBoss AS from Eclipse with

) and the application deploy in the Console log:JBoss Tools

14.4 The helloworld example in depth

JBoss AS 7.1

JBoss Community Documentation Page of 157 295

The helloworld is very simple - all it does is print "Hello World" onto a web page.

The helloworld example is comprised a servlet and a CDI bean. We also include an empty file,beans.xml

which tells JBoss AS to look for beans in this application and to activate the CDI. is located in beans.xml

, which can be found in the directory of the example. Also in this directory weWEB-INF src/main/webapp

include which uses a simple meta refresh to send the users browser to the Servlet, which isindex.html

located at .http://localhost:8080/jboss-as-helloworld/HelloWorld

All the configuration files for this example are located in , which can be found in the WEB-INF/

directory of the example.src/main/webapp

Notice that we don't even need a !web.xml

Let's start by taking a look at the servlet:

HelloWorldServlet.java

27. import javax.servlet.http.HttpServletResponse;

28.

29. /**

30. * <p>

31. * A simple servlet taking advantage of features added in 3.0.

32. * </p>

33. *

34. * <p>

35. * The servlet is registered and mapped to /HelloServlet using the {@linkplain WebServlet

36. * @HttpServlet}. The {@link HelloService} is injected by CDI.

37. * </p>

38. *

39. * @author Pete Muir

40. *

41. */

42. @SuppressWarnings("serial")

43. @WebServlet("/HelloWorld")

44. public class HelloWorldServlet extends HttpServlet {

45.

46. static String PAGE_HEADER = "<html><head><title>helloworld</title><body>";

47.

48. static String PAGE_FOOTER = "</body></html>";

49.

50. @Inject

51. HelloService helloService;

52.

53. @Override

54. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws

ServletException, IOException {

55. PrintWriter writer = resp.getWriter();

56. writer.println(PAGE_HEADER);

57. writer.println("<h1>" + helloService.createHelloMessage("World") + "</h1>");

58. writer.println(PAGE_FOOTER);

59. writer.close();

60. }

61.

62. }

JBoss AS 7.1

JBoss Community Documentation Page of 158 295

Line Note

27 If you've used Servlet before, then you'll remember having to use xml to register your servlets.

Fortunately, this is a thing of the past. Now all you need to do is add the annotation,@WebServlet

and provide a mapping to a URL used to access the servlet. Much cleaner!

30-32 Every web page needs to be correctly formed HTML. We've created static Strings to hold the

minimum header and footer to write out.

34,35 We inject the HelloService (a CDI bean) which generates the actual message. This allows to alter

the implementation of at a later date without changing the view layer at allHelloService

(assuming we don't alter the API of ).HelloService

41 We call into the service to generate the message "Hello World", and write it out to the HTTP

request.

The package declaration and imports have been excluded from these listings. The complete listing

is

available in the example source code.

Now we understand how the information is sent to the browser, let's take a look at the service.

HelloService.java

public class HelloService {

String createHelloMessage(String name) {

return "Hello " + name + "!";

}

}

The service is very simple - no registration (XML or annotation) is required!

JBoss AS 7.1

JBoss Community Documentation Page of 159 295

15 Numberguess quickstartThis quickstart shows you how to create and deploy a simple application to JBoss AS; the application does

not persist any information. Information is displayed using a JSF view, and business logic is encapsulated in

two CDI beans.

Switch to the directory and instruct Maven to build and deploy thequickstarts/numberguess

application:

mvn package jboss-as:deploy

The quickstart uses a Maven plugin to deploy the application. The plugin requires JBoss AS to be running

(you can find out how to start the server in or Installing and starting JBoss AS on Linux, Unix or Mac OS X

).Installing and starting JBoss AS on Windows

Or you can start the server using an IDE, like Eclipse.

Now, see if you can determine the most efficient approach to pinpoint the random number at the URL

.http://localhost:8080/jboss-as-numberguess

Should you wish to undeploy the quickstart, or redeploy after making some changes, it's pretty

easy:

- deploy any changes to the application to the application servermvn jboss-as:deploy

- undeploy the example from JBoss ASmvn jboss-as:undeploy

It's time to pull the covers back and dive into the internals of the example application.

15.1 Deploying the Numberguess example using

Eclipse

You may choose to deploy the example using Eclipse. You'll need to have JBoss AS started in Eclipse (as

described in ) and to have imported the quickstarts intoStarting JBoss AS from Eclipse with JBoss Tools

Eclipse (as described in ).Importing the quickstarts into Eclipse

With the quickstarts imported, you can deploy the example by right clicking on the

project, and choosing :jboss-as-numberguess Run As -> Run On Server

JBoss AS 7.1

JBoss Community Documentation Page of 160 295

Make sure the JBoss AS server is selected, and hit :Finish

JBoss AS 7.1

JBoss Community Documentation Page of 161 295

You should see JBoss AS start up (unless you already started it in Starting JBoss AS from Eclipse with

) and the application deploy in the Console log:JBoss Tools

15.2 The numberguess example in depth

JBoss AS 7.1

JBoss Community Documentation Page of 162 295

In the numberguess application you get 10 attempts to guess a number between 1 and 100. After each

attempt, you're told whether your guess was too high or too low.

The numberguess example is comprised of a number of beans, configuration files and Facelets (JSF) views,

packaged as a war module. Let's start by examining the configuration files.

All the configuration files for this example are located in , which can be found in the WEB-INF/

directory of the example. First, we have the JSF 2.0 version of . Asrc/main/webapp faces-config.xml

standardized version of Facelets is the default view handler in JSF 2.0, so there's really nothing that we have

to configure. JBoss AS goes above and beyond Java EE here, and will automatically configure JSF for you if

you include this file. Thus, the configuration consists of only the root element.

faces-config.xml

03. the copyright.txt in the distribution for a full listing of individual contributors.

04. Licensed under the Apache License, Version 2.0 (the "License"); you may not

05. use this file except in compliance with the License. You may obtain a copy

06. of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required

07. by applicable law or agreed to in writing, software distributed under the

08. License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS

09. OF ANY KIND, either express or implied. See the License for the specific

10. language governing permissions and limitations under the License. -->

11. <!-- Marker file indicating JSF 2.0 should be enabled in the application -->

12.

13. <faces-config version="2.0"

14. xmlns="http://java.sun.com/xml/ns/javaee"

15. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

16. xsi:schemaLocation="

17. http://java.sun.com/xml/ns/javaee

18. http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">

19.

20. </faces-config>

There's also an empty file, which tells JBoss AS to look for beans in this application and tobeans.xml

activate the CDI.

Notice that we don't even need a !web.xml

Let's take a look at the main JSF view, .src/main/webapp/home.xhtml

JSF uses the extension for source files, but serves up the rendered views with the .xhtml .jsf

extension.

home.xhtml

JBoss AS 7.1

JBoss Community Documentation Page of 163 295

03. <html xmlns="http://www.w3.org/1999/xhtml"

04. xmlns:ui="http://java.sun.com/jsf/facelets"

05. xmlns:h="http://java.sun.com/jsf/html"

06. xmlns:f="http://java.sun.com/jsf/core">

07.

08. <head>

09. <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />

10. <title>numberguess</title>

11. </head>

12.

13. <body>

14. <div id="content">

15. <h1>Guess a number...</h1>

16. <h:form id="numberGuess">

17.

18. <!-- Feedback for the user on their guess -->

19. <div style="color: red">

20. <h:messages id="messages" globalOnly="false" />

21. <h:outputText id="Higher" value="Higher!"

22. rendered="#{game.number gt game.guess and game.guess ne 0}" />

23. <h:outputText id="Lower" value="Lower!"

24. rendered="#{game.number lt game.guess and game.guess ne 0}" />

25. </div>

26.

27. <!-- Instructions for the user -->

28. <div>

29. I'm thinking of a number between <span

30. id="numberGuess:smallest">#{game.smallest}</span> and <span

31. id="numberGuess:biggest">#{game.biggest}</span>. You have

32. #{game.remainingGuesses} guesses remaining.

33. </div>

34.

35. <!-- Input box for the users guess, plus a button to submit, and reset -->

36. <!-- These are bound using EL to our CDI beans -->

37. <div>

38. Your guess:

39. <h:inputText id="inputGuess" value="#{game.guess}"

40. required="true" size="3"

41. disabled="#{game.number eq game.guess}"

42. validator="#{game.validateNumberRange}" />

43. <h:commandButton id="guessButton" value="Guess"

44. action="#{game.check}"

45. disabled="#{game.number eq game.guess}" />

46. </div>

47. <div>

48. <h:commandButton id="restartButton" value="Reset"

49. action="#{game.reset}" immediate="true" />

50. </div>

51. </h:form>

52.

53. </div>

54.

55. <br style="clear: both" />

56.

57. </body>

58. </html>

JBoss AS 7.1

JBoss Community Documentation Page of 164 295

Line

number

Note

20 - 24 There are a number of messages which can be sent to the user, "Higher!" and "Lower!"

29 - 32 As the user guesses, the range of numbers they can guess gets smaller - this sentence changes

to make sure they know the number range of a valid guess.

38 - 42 This input field is bound to a bean property using a value expression.

42 A validator binding is used to make sure the user doesn't accidentally input a number outside of

the range in which they can guess - if the validator wasn't here, the user might use up a guess

on an out of bounds number.

43 - 45 There must be a way for the user to send their guess to the server. Here we bind to an action

method on the bean.

The example consists of 4 classes, the first two of which are qualifiers. First, there is the

qualifier, used for injecting a random number:@Random

A is used to disambiguate between two beans both of which are eligible for injection basedqualifier

on their type. For more, see the .Weld Reference Guide

Random.java

21. import static java.lang.annotation.ElementType.PARAMETER;

22. import static java.lang.annotation.ElementType.TYPE;

23. import static java.lang.annotation.RetentionPolicy.RUNTIME;

24.

25. import java.lang.annotation.Documented;

26. import java.lang.annotation.Retention;

27. import java.lang.annotation.Target;

28.

29. import javax.inject.Qualifier;

30.

31. /**

32. * Qualifier for random numbers

33. *

34. * @author Pete Muir

35. *

36. */

37. @Target({ TYPE, METHOD, PARAMETER, FIELD })

38. @Retention(RUNTIME)

39. @Documented

40. @Qualifier

41. public @interface Random {

42.

43. }

There is also the qualifier, used for injecting the maximum number that can be injected:@MaxNumber

JBoss AS 7.1

JBoss Community Documentation Page of 165 295

MaxNumber.java

21. import static java.lang.annotation.ElementType.PARAMETER;

22. import static java.lang.annotation.ElementType.TYPE;

23. import static java.lang.annotation.RetentionPolicy.RUNTIME;

24.

25. import java.lang.annotation.Documented;

26. import java.lang.annotation.Retention;

27. import java.lang.annotation.Target;

28.

29. import javax.inject.Qualifier;

30.

31. /**

32. * Qualifier for the maximum number

33. *

34. * @author Pete Muir

35. *

36. */

37. @Target({ TYPE, METHOD, PARAMETER, FIELD })

38. @Retention(RUNTIME)

39. @Documented

40. @Qualifier

41. public @interface MaxNumber {

42.

43. }

The application-scoped class is responsible for creating the random number, via a producerGenerator

method. It also exposes the maximum possible number via a producer method:

JBoss AS 7.1

JBoss Community Documentation Page of 166 295

Generator.java

28. *

29. * <p>

30. * Placing the random number generation, as well as the configuring the maximum number

allows for a

31. * more loosely coupled application. We can now change out the implementation of number

generation

32. * without any effect on the client code. We also produce a more intuitive design - both are

33. * identifed by the fact they are numbers (int) and that they are qualified as the maximum

number or

34. * a random number.

35. * </p>

36. *

37. * <p>

38. * We use the application scope to store the random number generator so that we use the same

seed.

39. * </p>

40. *

41. * @author Pete Muir

42. *

43. */

44. @ApplicationScoped

45. public class Generator implements Serializable {

46. private static final long serialVersionUID = -7213673465118041882L;

47.

48. private java.util.Random random = new java.util.Random(System.currentTimeMillis());

49.

50. private int maxNumber = 100;

51.

52. java.util.Random getRandom() {

53. return random;

54. }

55.

56. @Produces

57. @Random

58. int next() {

59. // a number between 1 and 100

60. return getRandom().nextInt(maxNumber - 1) + 1;

61. }

62.

63. @Produces

64. @MaxNumber

65. int getMaxNumber() {

66. return maxNumber;

67. }

68. }

The is application scoped, so we don't get a different random each time.Generator

The final bean in the application is the session-scoped class. This is the primary entry point of theGame

application. It's responsible for setting up or resetting the game, capturing and validating the user's guess

and providing feedback to the user with a . We've used the post-construct lifecycle methodFacesMessage

to initialize the game by retrieving a random number from the bean.@RandomInstance<Integer>

JBoss AS 7.1

JBoss Community Documentation Page of 167 295

You'll notice that we've also added the annotation to this class. This annotation is only required@Named

when you want to make the bean accessible to a JSF view via EL (i.e., }).#{game

Game.java

035. * </p>

036. * <p>

037. * It contains properties for the <code>number</code> to be guessed, the current

<code>guess</code>,

038. * the <code>smallest</code> and <code>biggest</code> numbers guessed so far (as this is a

039. * higher/lower game we can prevent them entering numbers that they should know are wrong),

and the

040. * number of <code>remainingGuesses</code>.

041. * </p>

042. * <p>

043. * The {@link #check()} method, and {@link #reset()} methods provide the business logic

whilst the

044. * {@link #validateNumberRange(FacesContext, UIComponent, Object)} method provides feedback

to the

045. * user.

046. * </p>

047. *

048. * @author Pete Muir

049. *

050. */

051. @Named

052. @SessionScoped

053. public class Game implements Serializable {

054.

055. private static final long serialVersionUID = 991300443278089016L;

056.

057. /**

058. * The number that the user needs to guess

059. */

060. private int number;

061.

062. /**

063. * The users latest guess

064. */

065. private int guess;

066.

067. /**

068. * The smallest number guessed so far (so we can track the valid guess range).

069. */

070. private int smallest;

071.

072. /**

073. * The largest number guessed so far

074. */

075. private int biggest;

076.

077. /**

078. * The number of guesses remaining

079. */

080. private int remainingGuesses;

081.

082. /**

JBoss AS 7.1

JBoss Community Documentation Page of 168 295

083. * The maximum number we should ask them to guess

084. */

085. @Inject

086. @MaxNumber

087. private int maxNumber;

088.

089. /**

090. * The random number to guess

091. */

092. @Inject

093. @Random

094. Instance<Integer> randomNumber;

095.

096. public Game() {

097. }

098.

099. public int getNumber() {

100. return number;

101. }

102.

103. public int getGuess() {

104. return guess;

105. }

106.

107. public void setGuess(int guess) {

108. this.guess = guess;

109. }

110.

111. public int getSmallest() {

112. return smallest;

113. }

114.

115. public int getBiggest() {

116. return biggest;

117. }

118.

119. public int getRemainingGuesses() {

120. return remainingGuesses;

121. }

122.

123. /**

124. * Check whether the current guess is correct, and update the biggest/smallest guesses

as needed.

125. * Give feedback to the user if they are correct.

126. */

127. public void check() {

128. if (guess > number) {

129. biggest = guess - 1;

130. } else if (guess < number) {

131. smallest = guess + 1;

132. } else if (guess == number) {

133. FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Correct!"));

134. }

135. remainingGuesses--;

136. }

137.

138. /**

139. * Reset the game, by putting all values back to their defaults, and getting a new

JBoss AS 7.1

JBoss Community Documentation Page of 169 295

random number.

140. * We also call this method when the user starts playing for the first time using

141. * {@linkplain PostConstruct @PostConstruct} to set the initial values.

142. */

143. @PostConstruct

144. public void reset() {

145. this.smallest = 0;

146. this.guess = 0;

147. this.remainingGuesses = 10;

148. this.biggest = maxNumber;

149. this.number = randomNumber.get();

150. }

151.

152. /**

153. * A JSF validation method which checks whether the guess is valid. It might not be

valid because

154. * there are no guesses left, or because the guess is not in range.

155. *

156. */

157. public void validateNumberRange(FacesContext context, UIComponent toValidate, Object

value) {

158. if (remainingGuesses <= 0) {

159. FacesMessage message = new FacesMessage("No guesses left!");

160. context.addMessage(toValidate.getClientId(context), message);

161. ((UIInput) toValidate).setValid(false);

162. return;

163. }

164. int input = (Integer) value;

165.

166. if (input < smallest || input > biggest) {

167. ((UIInput) toValidate).setValid(false);

168.

169. FacesMessage message = new FacesMessage("Invalid guess");

170. context.addMessage(toValidate.getClientId(context), message);

171. }

172. }

173. }

15.3 Deploying the Numberguess example using

Eclipse

You may choose to deploy the example using Eclipse. You'll need to have JBoss AS started in Eclipse (as

described in ) and to have imported the quickstarts intoStarting JBoss AS from Eclipse with JBoss Tools

Eclipse (as described in ).Importing the quickstarts into Eclipse

With the quickstarts imported, you can deploy the example by right clicking on the

project, and choosing :jboss-as-numberguess Run As -> Run On Server

JBoss AS 7.1

JBoss Community Documentation Page of 170 295

Make sure the JBoss AS server is selected, and hit :Finish

JBoss AS 7.1

JBoss Community Documentation Page of 171 295

You should see JBoss AS start up (unless you already started it in Starting JBoss AS from Eclipse with

) and the application deploy in the Console log:JBoss Tools

15.4 The numberguess example in depth

JBoss AS 7.1

JBoss Community Documentation Page of 172 295

In the numberguess application you get 10 attempts to guess a number between 1 and 100. After each

attempt, you're told whether your guess was too high or too low.

The numberguess example is comprised of a number of beans, configuration files and Facelets (JSF) views,

packaged as a war module. Let's start by examining the configuration files.

All the configuration files for this example are located in , which can be found in the WEB-INF/

directory of the example. First, we have the JSF 2.0 version of . Asrc/main/webapp faces-config.xml

standardized version of Facelets is the default view handler in JSF 2.0, so there's really nothing that we have

to configure. JBoss AS goes above and beyond Java EE here, and will automatically configure JSF for you if

you include this file. Thus, the configuration consists of only the root element.

faces-config.xml

03. the copyright.txt in the distribution for a full listing of individual contributors.

04. Licensed under the Apache License, Version 2.0 (the "License"); you may not

05. use this file except in compliance with the License. You may obtain a copy

06. of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required

07. by applicable law or agreed to in writing, software distributed under the

08. License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS

09. OF ANY KIND, either express or implied. See the License for the specific

10. language governing permissions and limitations under the License. -->

11. <!-- Marker file indicating JSF 2.0 should be enabled in the application -->

12.

13. <faces-config version="2.0"

14. xmlns="http://java.sun.com/xml/ns/javaee"

15. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

16. xsi:schemaLocation="

17. http://java.sun.com/xml/ns/javaee

18. http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">

19.

20. </faces-config>

There's also an empty file, which tells JBoss AS to look for beans in this application and tobeans.xml

activate the CDI.

Notice that we don't even need a !web.xml

Let's take a look at the main JSF view, .src/main/webapp/home.xhtml

JSF uses the extension for source files, but serves up the rendered views with the .xhtml .jsf

extension.

home.xhtml

JBoss AS 7.1

JBoss Community Documentation Page of 173 295

03. <html xmlns="http://www.w3.org/1999/xhtml"

04. xmlns:ui="http://java.sun.com/jsf/facelets"

05. xmlns:h="http://java.sun.com/jsf/html"

06. xmlns:f="http://java.sun.com/jsf/core">

07.

08. <head>

09. <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />

10. <title>numberguess</title>

11. </head>

12.

13. <body>

14. <div id="content">

15. <h1>Guess a number...</h1>

16. <h:form id="numberGuess">

17.

18. <!-- Feedback for the user on their guess -->

19. <div style="color: red">

20. <h:messages id="messages" globalOnly="false" />

21. <h:outputText id="Higher" value="Higher!"

22. rendered="#{game.number gt game.guess and game.guess ne 0}" />

23. <h:outputText id="Lower" value="Lower!"

24. rendered="#{game.number lt game.guess and game.guess ne 0}" />

25. </div>

26.

27. <!-- Instructions for the user -->

28. <div>

29. I'm thinking of a number between <span

30. id="numberGuess:smallest">#{game.smallest}</span> and <span

31. id="numberGuess:biggest">#{game.biggest}</span>. You have

32. #{game.remainingGuesses} guesses remaining.

33. </div>

34.

35. <!-- Input box for the users guess, plus a button to submit, and reset -->

36. <!-- These are bound using EL to our CDI beans -->

37. <div>

38. Your guess:

39. <h:inputText id="inputGuess" value="#{game.guess}"

40. required="true" size="3"

41. disabled="#{game.number eq game.guess}"

42. validator="#{game.validateNumberRange}" />

43. <h:commandButton id="guessButton" value="Guess"

44. action="#{game.check}"

45. disabled="#{game.number eq game.guess}" />

46. </div>

47. <div>

48. <h:commandButton id="restartButton" value="Reset"

49. action="#{game.reset}" immediate="true" />

50. </div>

51. </h:form>

52.

53. </div>

54.

55. <br style="clear: both" />

56.

57. </body>

58. </html>

JBoss AS 7.1

JBoss Community Documentation Page of 174 295

Line

number

Note

20 - 24 There are a number of messages which can be sent to the user, "Higher!" and "Lower!"

29 - 32 As the user guesses, the range of numbers they can guess gets smaller - this sentence changes

to make sure they know the number range of a valid guess.

38 - 42 This input field is bound to a bean property using a value expression.

42 A validator binding is used to make sure the user doesn't accidentally input a number outside of

the range in which they can guess - if the validator wasn't here, the user might use up a guess

on an out of bounds number.

43 - 45 There must be a way for the user to send their guess to the server. Here we bind to an action

method on the bean.

The example consists of 4 classes, the first two of which are qualifiers. First, there is the

qualifier, used for injecting a random number:@Random

A is used to disambiguate between two beans both of which are eligible for injection basedqualifier

on their type. For more, see the .Weld Reference Guide

Random.java

21. import static java.lang.annotation.ElementType.PARAMETER;

22. import static java.lang.annotation.ElementType.TYPE;

23. import static java.lang.annotation.RetentionPolicy.RUNTIME;

24.

25. import java.lang.annotation.Documented;

26. import java.lang.annotation.Retention;

27. import java.lang.annotation.Target;

28.

29. import javax.inject.Qualifier;

30.

31. /**

32. * Qualifier for random numbers

33. *

34. * @author Pete Muir

35. *

36. */

37. @Target({ TYPE, METHOD, PARAMETER, FIELD })

38. @Retention(RUNTIME)

39. @Documented

40. @Qualifier

41. public @interface Random {

42.

43. }

There is also the qualifier, used for injecting the maximum number that can be injected:@MaxNumber

JBoss AS 7.1

JBoss Community Documentation Page of 175 295

MaxNumber.java

21. import static java.lang.annotation.ElementType.PARAMETER;

22. import static java.lang.annotation.ElementType.TYPE;

23. import static java.lang.annotation.RetentionPolicy.RUNTIME;

24.

25. import java.lang.annotation.Documented;

26. import java.lang.annotation.Retention;

27. import java.lang.annotation.Target;

28.

29. import javax.inject.Qualifier;

30.

31. /**

32. * Qualifier for the maximum number

33. *

34. * @author Pete Muir

35. *

36. */

37. @Target({ TYPE, METHOD, PARAMETER, FIELD })

38. @Retention(RUNTIME)

39. @Documented

40. @Qualifier

41. public @interface MaxNumber {

42.

43. }

The application-scoped class is responsible for creating the random number, via a producerGenerator

method. It also exposes the maximum possible number via a producer method:

JBoss AS 7.1

JBoss Community Documentation Page of 176 295

Generator.java

28. *

29. * <p>

30. * Placing the random number generation, as well as the configuring the maximum number

allows for a

31. * more loosely coupled application. We can now change out the implementation of number

generation

32. * without any effect on the client code. We also produce a more intuitive design - both are

33. * identifed by the fact they are numbers (int) and that they are qualified as the maximum

number or

34. * a random number.

35. * </p>

36. *

37. * <p>

38. * We use the application scope to store the random number generator so that we use the same

seed.

39. * </p>

40. *

41. * @author Pete Muir

42. *

43. */

44. @ApplicationScoped

45. public class Generator implements Serializable {

46. private static final long serialVersionUID = -7213673465118041882L;

47.

48. private java.util.Random random = new java.util.Random(System.currentTimeMillis());

49.

50. private int maxNumber = 100;

51.

52. java.util.Random getRandom() {

53. return random;

54. }

55.

56. @Produces

57. @Random

58. int next() {

59. // a number between 1 and 100

60. return getRandom().nextInt(maxNumber - 1) + 1;

61. }

62.

63. @Produces

64. @MaxNumber

65. int getMaxNumber() {

66. return maxNumber;

67. }

68. }

The is application scoped, so we don't get a different random each time.Generator

The final bean in the application is the session-scoped class. This is the primary entry point of theGame

application. It's responsible for setting up or resetting the game, capturing and validating the user's guess

and providing feedback to the user with a . We've used the post-construct lifecycle methodFacesMessage

to initialize the game by retrieving a random number from the bean.@RandomInstance<Integer>

JBoss AS 7.1

JBoss Community Documentation Page of 177 295

You'll notice that we've also added the annotation to this class. This annotation is only required@Named

when you want to make the bean accessible to a JSF view via EL (i.e., }).#{game

Game.java

035. * </p>

036. * <p>

037. * It contains properties for the <code>number</code> to be guessed, the current

<code>guess</code>,

038. * the <code>smallest</code> and <code>biggest</code> numbers guessed so far (as this is a

039. * higher/lower game we can prevent them entering numbers that they should know are wrong),

and the

040. * number of <code>remainingGuesses</code>.

041. * </p>

042. * <p>

043. * The {@link #check()} method, and {@link #reset()} methods provide the business logic

whilst the

044. * {@link #validateNumberRange(FacesContext, UIComponent, Object)} method provides feedback

to the

045. * user.

046. * </p>

047. *

048. * @author Pete Muir

049. *

050. */

051. @Named

052. @SessionScoped

053. public class Game implements Serializable {

054.

055. private static final long serialVersionUID = 991300443278089016L;

056.

057. /**

058. * The number that the user needs to guess

059. */

060. private int number;

061.

062. /**

063. * The users latest guess

064. */

065. private int guess;

066.

067. /**

068. * The smallest number guessed so far (so we can track the valid guess range).

069. */

070. private int smallest;

071.

072. /**

073. * The largest number guessed so far

074. */

075. private int biggest;

076.

077. /**

078. * The number of guesses remaining

079. */

080. private int remainingGuesses;

081.

082. /**

JBoss AS 7.1

JBoss Community Documentation Page of 178 295

083. * The maximum number we should ask them to guess

084. */

085. @Inject

086. @MaxNumber

087. private int maxNumber;

088.

089. /**

090. * The random number to guess

091. */

092. @Inject

093. @Random

094. Instance<Integer> randomNumber;

095.

096. public Game() {

097. }

098.

099. public int getNumber() {

100. return number;

101. }

102.

103. public int getGuess() {

104. return guess;

105. }

106.

107. public void setGuess(int guess) {

108. this.guess = guess;

109. }

110.

111. public int getSmallest() {

112. return smallest;

113. }

114.

115. public int getBiggest() {

116. return biggest;

117. }

118.

119. public int getRemainingGuesses() {

120. return remainingGuesses;

121. }

122.

123. /**

124. * Check whether the current guess is correct, and update the biggest/smallest guesses

as needed.

125. * Give feedback to the user if they are correct.

126. */

127. public void check() {

128. if (guess > number) {

129. biggest = guess - 1;

130. } else if (guess < number) {

131. smallest = guess + 1;

132. } else if (guess == number) {

133. FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Correct!"));

134. }

135. remainingGuesses--;

136. }

137.

138. /**

139. * Reset the game, by putting all values back to their defaults, and getting a new

JBoss AS 7.1

JBoss Community Documentation Page of 179 295

random number.

140. * We also call this method when the user starts playing for the first time using

141. * {@linkplain PostConstruct @PostConstruct} to set the initial values.

142. */

143. @PostConstruct

144. public void reset() {

145. this.smallest = 0;

146. this.guess = 0;

147. this.remainingGuesses = 10;

148. this.biggest = maxNumber;

149. this.number = randomNumber.get();

150. }

151.

152. /**

153. * A JSF validation method which checks whether the guess is valid. It might not be

valid because

154. * there are no guesses left, or because the guess is not in range.

155. *

156. */

157. public void validateNumberRange(FacesContext context, UIComponent toValidate, Object

value) {

158. if (remainingGuesses <= 0) {

159. FacesMessage message = new FacesMessage("No guesses left!");

160. context.addMessage(toValidate.getClientId(context), message);

161. ((UIInput) toValidate).setValid(false);

162. return;

163. }

164. int input = (Integer) value;

165.

166. if (input < smallest || input > biggest) {

167. ((UIInput) toValidate).setValid(false);

168.

169. FacesMessage message = new FacesMessage("Invalid guess");

170. context.addMessage(toValidate.getClientId(context), message);

171. }

172. }

173. }

JBoss AS 7.1

JBoss Community Documentation Page of 180 295

16 Login quickstartThis quickstart shows you how to create and deploy an application which persists information to a database

to JBoss AS. Information is displayed using JSF views, business logic is encapsulated in CDI beans,

information is persisted using JPA, and transactions can be controlled manually or using EJB.

Switch to the directory and instruct Maven to build and deploy the application:quickstarts/login

mvn package jboss-as:deploy

The quickstart uses a Maven plugin to deploy the application. The plugin requires JBoss AS to be running

(you can find out how to start the server in or Installing and starting JBoss AS on Linux, Unix or Mac OS X

).Installing and starting JBoss AS on Windows

Or you can start the server using an IDE, like Eclipse.

Visit and try logging in with the username and password .http://localhost:8080/jboss-as-login demo demo

Now, click on and then on . From this screen you can add yourself as a user, and thenLogout View Users

login as this user.

Should you wish to undeploy the quickstart, or redeploy after making some changes, it's pretty

easy:

- deploy any changes to the application to the application servermvn jboss-as:deploy

- undeploy the example from JBoss ASmvn jboss-as:undeploy

It's time to pull the covers back and dive into the internals of the example application.

16.1 Deploying the Login example using Eclipse

You may choose to deploy the example using Eclipse. You'll need to have JBoss AS started in Eclipse (as

described in ) and to have imported the quickstarts intoStarting JBoss AS from Eclipse with JBoss Tools

Eclipse (as described in [Importing the quickstarts into Eclipse).

With the quickstarts imported, you can deploy the example by right clicking on the jboss-as-login

project, and choosing :Run As -> Run On Server

JBoss AS 7.1

JBoss Community Documentation Page of 181 295

Make sure the JBoss AS server is selected, and hit :Finish

JBoss AS 7.1

JBoss Community Documentation Page of 182 295

You should see JBoss AS start up (unless you already started it in Starting JBoss AS from Eclipse with

) and the application deploy in the Console log:JBoss Tools

16.2 The login example in depth

JBoss AS 7.1

JBoss Community Documentation Page of 183 295

In the login example, all users are stored in an H2 database (an in-memory, embedded database provided

out of the box in JBoss AS). Each user is stored as an entity, and entities are mapped to the database using

JPA. By default, transactions are managed manually, using the JTA API. Optionally, you can use EJB to

manage transactions (we'll look at how to enable that later). We need a transaction in progress in order to

read and write any entities.

The login example is comprised of two JSF views, an entity, and a number of CDI beans. Additionally, there

are the usual configuration files in (which can be found in the directory of theWEB-INF/ src/main/webapp

example). Here we find and tell JBoss AS to enable CDI and JSF for thebeans.xml face-config.xml

application. Notice that we don't need a . There are two new configuration files in web.xml

(which can be found in the directory of theWEB-INF/classes/META-INF src/main/resources

example) — , which sets up JPA, and which Hibernate, the JPA providerpersistence.xml import.sql

in JBoss AS, will use to load the initial users into the application when the application starts.

is pretty straight forward, and links JPA to a datasource: Unable topersistence.xml Code Snippet error:

retrieve the URL:

https://github.com/jbossas/quickstart/raw/master/login/src/main/resources/META-INF/persistence.xml status

code: 404.

Line

number

Note

6 The persistence unit is given a name, so that the application can use multiple if needed. If only

one is defined, JPA will automatically use it.

8 The persistence unit references a data source. Here we are using the built in, sample, data

source.

10 JPA allows us to configure the JPA provider specific properties. Here we tell Hibernate to

automatically create any needed tables when the application starts (and drop them when the

application is stopped).

JBoss AS ships with a sample datasource . This datajava:jboss/datasources/ExampleDS

source is backed by H2, an in-memory database. Whilst this datasource is great for quickstarts,

you will probably want to use a different datasource in your application. The Getting Started Guide

tells you how to create a new datasource.

Let's take a look at the JSF views. First up is :src/main/webapp/home.xhtml Code Snippet error:

Unable to retrieve the URL:

https://github.com/jbossas/quickstart/raw/master/login/src/main/webapp/home.xhtml status code: 404.

Line

number

Note

JBoss AS 7.1

JBoss Community Documentation Page of 184 295

7 As we have multiple views in this application, we've created a template that defines the common

elements. We'll examine this next. Here we define the "content" section of the page, which will

be inserted into the template.

9 We output any messages for the user at the top of the form, such as the welcome message

when you login.

11 - 16 The login form fields are only rendered if there is no logged in user. This allows us to prevent

someone from logging in twice.

17, 18 Depending on whether the user is logged in or not, we display a log out or log in button. We also

display a link to the page which shows the available users.

Now let's take a look at the template. It defines common elements for the page, and allows pages which use

it to insert content in various places. Unable to retrieve the URL:Code Snippet error:

https://github.com/jbossas/quickstart/raw/master/login/src/main/webapp/template.xhtml status code: 404.

Line number Note

9 The head, defined in case a page wants to add some content to the head of the page.

28 The content, defined by a page using this template, will be inserted here

Finally, let's take a look at the user management page. It uses a table to display all existing users, and

provides a form to add users Unable to retrieve the URL:Code Snippet error:

https://github.com/jbossas/quickstart/raw/master/login/src/main/webapp/users.xhtml status code: 404.

Line

number

Note

11 The table which displays the current users in the database. The datatable references the ,users

and iterates over each one. Each user is assigned to the variable , which we can use whenu

laying out the table structure.

13 - 15 Each column in the table is given a header, plus content.

Finally, we provide a simple form that allows you to add a new user.

The example has one entity, which is mapped via JPA to the relational database:Code Snippet error:

Unable to retrieve the URL:

https://github.com/jbossas/quickstart/raw/master/login/src/main/java/org/jboss/as/quickstarts/login/User.java

status code: 404.

Line

number

Note

6 The annotation used on the class tells JPA that this class should be mapped as a@Entity

table in the database.

JBoss AS 7.1

JBoss Community Documentation Page of 185 295

8, 9 Every entity requires an id, the annotation placed on a field (or a JavaBean@Id

mutator/accessor) tells JPA that this property is the id. You can use a synthetic id, or a natural id

(as we do here).

10, 11 The entity also stores the real name of the user, and their password.

13 - 35 As this is Java, every property needs an accessor/mutator!

Next up, let's take a look at , a data structure used to temporarily hold the credentialsCredentials.java

the user has entered whilst logging in. Unable to retrieve the URL:Code Snippet error:

https://github.com/jbossas/quickstart/raw/master/login/src/main/java/org/jboss/as/quickstarts/login/Credentials.java

status code: 404.

Line

number

Note

6 The bean is request scoped, as entered data is naturally scoped to a request.

7 The bean is given a name, so we can access it from JSF.

10 - 27 The bean needs to store the username and password entered, and also make them usable via

accessors and mutators.

The logic allowing a user to log in, and storing who is currently logged in, is encoded in :Login.java Code

Unable to retrieve the URL:Snippet error:

https://github.com/jbossas/quickstart/raw/master/login/src/main/java/org/jboss/as/quickstarts/login/Login.java

status code: 404.

Line

number

Note

12 The bean is session scoped, meaning that the currently logged user is kept until the session

ends.

13 The bean is given a name, so we can access it from JSF.

18, 19 We inject the credentials filled in on the web page so we can check them in the login()

method.

21, 22 We inject the user manager, which takes care of loading and adding users from the database.

26 - 33 The login method is triggered when the button is pressed. It asks the toLogin userManager

find a user with matching username and password, and if a user is found, sets the

and displays a message to the user.currentUser

35 - 39 The logout method is triggered when the button is pressed. It clearsthe Logout currentUser

and displays a message to the user.

45 - 49 The current user is exposed to the application using a producer method, which means that there

is no coupling between a class wanting to know the current user, and the class. The Login

qualifier is used to indicate that this is special.LoggedIn User

JBoss AS 7.1

JBoss Community Documentation Page of 186 295

Now, let's look at the most interesting part of the application, how we interact with the database. As we

mentioned earlier, by default the application uses the JTA API to manually control transactions. To

implement both approaches, we've defined a interface, with two implementations, one ofUserManager

which (the EJB variant) is as an alternative which can be enabled via a deployment descriptor. Let's first look

at the interface, and the manual transaction control variant. Unable to retrieve the URL:Code Snippet error:

https://github.com/jbossas/quickstart/raw/master/login/src/main/java/org/jboss/as/quickstarts/login/UserManager.java

status code: 404.

The methods are fairly self explanatory, so let's move on quickly to the implementation,

: Unable to retrieve the URL:ManagedBeanUserManager Code Snippet error:

https://github.com/jbossas/quickstart/raw/master/login/src/main/java/org/jboss/as/quickstarts/login/ManagedBeanUserManager.java

status code: 404.

Line

number

Note

13 The bean is given a name, so we can access it from JSF.

14 The bean is request scoped, meaning that the new user object being added is the same for

every invocation of during the request.userManager

17 - 18 We inject a JDK logger so that we can log when a user is added

20 - 21 We inject the entity manager. This was set up in .persistence.xml

29 - 45 We create a named producer method that uses JPA to expose all the users currently in the

database. This allows JSF to access this list. We also make this request scoped so that the

database isn't hit every time we need to display the users list.

47 - 61 takes the and persists it to the database.addUser newUser

63 - 88 The method can check whether a user with a matching username and passwordfindUser()

exists, and return it if it does.

90 - 95 The is exposed to JSF by using a named producer method.newUser

You've probably noticed two things as you've read through this. Firstly, that manually managing transactions

is a real pain. Secondly, you may be wondering how the entity manager and the logger are injected. First,

let's tidy up the transaction manager, and use EJB to provide us with declarative transaction support.

The class provides this, and is defined as an alternative. Alternatives are disabled byEJBUserManager

default, and when enabled replace the original implementation. In order to enable this variant of

, edit and uncomment the alternative. Your should now look like:UserManager beans.xml beans.xml

JBoss AS 7.1

JBoss Community Documentation Page of 187 295

<beans xmlns="http://java.sun.com/xml/ns/javaee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="

http://java.sun.com/xml/ns/javaee

http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">

<!-- Uncomment this alternative to see EJB declarative transactions in use -->

<alternatives>

<class>org.jboss.as.quickstarts.login.EJBUserManager</class>

</alternatives>

</beans>

Now, let's look at : Unable to retrieve the URL:EJBUserManager Code Snippet error:

https://github.com/jbossas/quickstart/raw/master/login/src/main/java/org/jboss/as/quickstarts/login/EJBUserManager.java

status code: 404.

Using declarative transaction management has allowed us to remove a third of the lines of code from the

class, but more importantly emphasizes the functionality of the class. Much better!

Sharp eyed developers who are used to Java EE will have noticed that we have added this EJB to

a war. This is the key improvement offered in EJB 3.1 (which was first included in Java EE 6).

Finally, let's take a look at the class, which provides resources such as the entity manager. CDIResources

recommends using "resource producers", as we do in this example, to alias resources to CDI beans,

allowing for a consistent style throughout our application: Unable to retrieve the URL:Code Snippet error:

https://github.com/jbossas/quickstart/raw/master/login/src/main/java/org/jboss/as/quickstarts/login/Resources.java

status code: 404.

Line

number

Note

13 - 16 We use the "resource producer" pattern, from CDI, to "alias" the old fashioned

injection of the entity manager to a CDI style injection. This allows us@PersistenceContext

to use a consistent injection style ( ) throughout the application.@Inject

18 - 22 We expose a JDK logger for injection. In order to save a bit more boiler plate, we automatically

set the logger category as the class name!

That concludes our tour of the login application!

16.3 Deploying the Login example using Eclipse

You may choose to deploy the example using Eclipse. You'll need to have JBoss AS started in Eclipse (as

described in ) and to have imported the quickstarts intoStarting JBoss AS from Eclipse with JBoss Tools

Eclipse (as described in [Importing the quickstarts into Eclipse).

JBoss AS 7.1

JBoss Community Documentation Page of 188 295

With the quickstarts imported, you can deploy the example by right clicking on the jboss-as-login

project, and choosing :Run As -> Run On Server

Make sure the JBoss AS server is selected, and hit :Finish

JBoss AS 7.1

JBoss Community Documentation Page of 189 295

You should see JBoss AS start up (unless you already started it in Starting JBoss AS from Eclipse with

) and the application deploy in the Console log:JBoss Tools

16.4 The login example in depth

JBoss AS 7.1

JBoss Community Documentation Page of 190 295

In the login example, all users are stored in an H2 database (an in-memory, embedded database provided

out of the box in JBoss AS). Each user is stored as an entity, and entities are mapped to the database using

JPA. By default, transactions are managed manually, using the JTA API. Optionally, you can use EJB to

manage transactions (we'll look at how to enable that later). We need a transaction in progress in order to

read and write any entities.

The login example is comprised of two JSF views, an entity, and a number of CDI beans. Additionally, there

are the usual configuration files in (which can be found in the directory of theWEB-INF/ src/main/webapp

example). Here we find and tell JBoss AS to enable CDI and JSF for thebeans.xml face-config.xml

application. Notice that we don't need a . There are two new configuration files in web.xml

(which can be found in the directory of theWEB-INF/classes/META-INF src/main/resources

example) — , which sets up JPA, and which Hibernate, the JPA providerpersistence.xml import.sql

in JBoss AS, will use to load the initial users into the application when the application starts.

is pretty straight forward, and links JPA to a datasource: Unable topersistence.xml Code Snippet error:

retrieve the URL:

https://github.com/jbossas/quickstart/raw/master/login/src/main/resources/META-INF/persistence.xml status

code: 404.

Line

number

Note

6 The persistence unit is given a name, so that the application can use multiple if needed. If only

one is defined, JPA will automatically use it.

8 The persistence unit references a data source. Here we are using the built in, sample, data

source.

10 JPA allows us to configure the JPA provider specific properties. Here we tell Hibernate to

automatically create any needed tables when the application starts (and drop them when the

application is stopped).

JBoss AS ships with a sample datasource . This datajava:jboss/datasources/ExampleDS

source is backed by H2, an in-memory database. Whilst this datasource is great for quickstarts,

you will probably want to use a different datasource in your application. The Getting Started Guide

tells you how to create a new datasource.

Let's take a look at the JSF views. First up is :src/main/webapp/home.xhtml Code Snippet error:

Unable to retrieve the URL:

https://github.com/jbossas/quickstart/raw/master/login/src/main/webapp/home.xhtml status code: 404.

Line

number

Note

JBoss AS 7.1

JBoss Community Documentation Page of 191 295

7 As we have multiple views in this application, we've created a template that defines the common

elements. We'll examine this next. Here we define the "content" section of the page, which will

be inserted into the template.

9 We output any messages for the user at the top of the form, such as the welcome message

when you login.

11 - 16 The login form fields are only rendered if there is no logged in user. This allows us to prevent

someone from logging in twice.

17, 18 Depending on whether the user is logged in or not, we display a log out or log in button. We also

display a link to the page which shows the available users.

Now let's take a look at the template. It defines common elements for the page, and allows pages which use

it to insert content in various places. Unable to retrieve the URL:Code Snippet error:

https://github.com/jbossas/quickstart/raw/master/login/src/main/webapp/template.xhtml status code: 404.

Line number Note

9 The head, defined in case a page wants to add some content to the head of the page.

28 The content, defined by a page using this template, will be inserted here

Finally, let's take a look at the user management page. It uses a table to display all existing users, and

provides a form to add users Unable to retrieve the URL:Code Snippet error:

https://github.com/jbossas/quickstart/raw/master/login/src/main/webapp/users.xhtml status code: 404.

Line

number

Note

11 The table which displays the current users in the database. The datatable references the ,users

and iterates over each one. Each user is assigned to the variable , which we can use whenu

laying out the table structure.

13 - 15 Each column in the table is given a header, plus content.

Finally, we provide a simple form that allows you to add a new user.

The example has one entity, which is mapped via JPA to the relational database:Code Snippet error:

Unable to retrieve the URL:

https://github.com/jbossas/quickstart/raw/master/login/src/main/java/org/jboss/as/quickstarts/login/User.java

status code: 404.

Line

number

Note

6 The annotation used on the class tells JPA that this class should be mapped as a@Entity

table in the database.

JBoss AS 7.1

JBoss Community Documentation Page of 192 295

8, 9 Every entity requires an id, the annotation placed on a field (or a JavaBean@Id

mutator/accessor) tells JPA that this property is the id. You can use a synthetic id, or a natural id

(as we do here).

10, 11 The entity also stores the real name of the user, and their password.

13 - 35 As this is Java, every property needs an accessor/mutator!

Next up, let's take a look at , a data structure used to temporarily hold the credentialsCredentials.java

the user has entered whilst logging in. Unable to retrieve the URL:Code Snippet error:

https://github.com/jbossas/quickstart/raw/master/login/src/main/java/org/jboss/as/quickstarts/login/Credentials.java

status code: 404.

Line

number

Note

6 The bean is request scoped, as entered data is naturally scoped to a request.

7 The bean is given a name, so we can access it from JSF.

10 - 27 The bean needs to store the username and password entered, and also make them usable via

accessors and mutators.

The logic allowing a user to log in, and storing who is currently logged in, is encoded in :Login.java Code

Unable to retrieve the URL:Snippet error:

https://github.com/jbossas/quickstart/raw/master/login/src/main/java/org/jboss/as/quickstarts/login/Login.java

status code: 404.

Line

number

Note

12 The bean is session scoped, meaning that the currently logged user is kept until the session

ends.

13 The bean is given a name, so we can access it from JSF.

18, 19 We inject the credentials filled in on the web page so we can check them in the login()

method.

21, 22 We inject the user manager, which takes care of loading and adding users from the database.

26 - 33 The login method is triggered when the button is pressed. It asks the toLogin userManager

find a user with matching username and password, and if a user is found, sets the

and displays a message to the user.currentUser

35 - 39 The logout method is triggered when the button is pressed. It clearsthe Logout currentUser

and displays a message to the user.

45 - 49 The current user is exposed to the application using a producer method, which means that there

is no coupling between a class wanting to know the current user, and the class. The Login

qualifier is used to indicate that this is special.LoggedIn User

JBoss AS 7.1

JBoss Community Documentation Page of 193 295

Now, let's look at the most interesting part of the application, how we interact with the database. As we

mentioned earlier, by default the application uses the JTA API to manually control transactions. To

implement both approaches, we've defined a interface, with two implementations, one ofUserManager

which (the EJB variant) is as an alternative which can be enabled via a deployment descriptor. Let's first look

at the interface, and the manual transaction control variant. Unable to retrieve the URL:Code Snippet error:

https://github.com/jbossas/quickstart/raw/master/login/src/main/java/org/jboss/as/quickstarts/login/UserManager.java

status code: 404.

The methods are fairly self explanatory, so let's move on quickly to the implementation,

: Unable to retrieve the URL:ManagedBeanUserManager Code Snippet error:

https://github.com/jbossas/quickstart/raw/master/login/src/main/java/org/jboss/as/quickstarts/login/ManagedBeanUserManager.java

status code: 404.

Line

number

Note

13 The bean is given a name, so we can access it from JSF.

14 The bean is request scoped, meaning that the new user object being added is the same for

every invocation of during the request.userManager

17 - 18 We inject a JDK logger so that we can log when a user is added

20 - 21 We inject the entity manager. This was set up in .persistence.xml

29 - 45 We create a named producer method that uses JPA to expose all the users currently in the

database. This allows JSF to access this list. We also make this request scoped so that the

database isn't hit every time we need to display the users list.

47 - 61 takes the and persists it to the database.addUser newUser

63 - 88 The method can check whether a user with a matching username and passwordfindUser()

exists, and return it if it does.

90 - 95 The is exposed to JSF by using a named producer method.newUser

You've probably noticed two things as you've read through this. Firstly, that manually managing transactions

is a real pain. Secondly, you may be wondering how the entity manager and the logger are injected. First,

let's tidy up the transaction manager, and use EJB to provide us with declarative transaction support.

The class provides this, and is defined as an alternative. Alternatives are disabled byEJBUserManager

default, and when enabled replace the original implementation. In order to enable this variant of

, edit and uncomment the alternative. Your should now look like:UserManager beans.xml beans.xml

JBoss AS 7.1

JBoss Community Documentation Page of 194 295

<beans xmlns="http://java.sun.com/xml/ns/javaee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="

http://java.sun.com/xml/ns/javaee

http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">

<!-- Uncomment this alternative to see EJB declarative transactions in use -->

<alternatives>

<class>org.jboss.as.quickstarts.login.EJBUserManager</class>

</alternatives>

</beans>

Now, let's look at : Unable to retrieve the URL:EJBUserManager Code Snippet error:

https://github.com/jbossas/quickstart/raw/master/login/src/main/java/org/jboss/as/quickstarts/login/EJBUserManager.java

status code: 404.

Using declarative transaction management has allowed us to remove a third of the lines of code from the

class, but more importantly emphasizes the functionality of the class. Much better!

Sharp eyed developers who are used to Java EE will have noticed that we have added this EJB to

a war. This is the key improvement offered in EJB 3.1 (which was first included in Java EE 6).

Finally, let's take a look at the class, which provides resources such as the entity manager. CDIResources

recommends using "resource producers", as we do in this example, to alias resources to CDI beans,

allowing for a consistent style throughout our application: Unable to retrieve the URL:Code Snippet error:

https://github.com/jbossas/quickstart/raw/master/login/src/main/java/org/jboss/as/quickstarts/login/Resources.java

status code: 404.

Line

number

Note

13 - 16 We use the "resource producer" pattern, from CDI, to "alias" the old fashioned

injection of the entity manager to a CDI style injection. This allows us@PersistenceContext

to use a consistent injection style ( ) throughout the application.@Inject

18 - 22 We expose a JDK logger for injection. In order to save a bit more boiler plate, we automatically

set the logger category as the class name!

That concludes our tour of the login application!

JBoss AS 7.1

JBoss Community Documentation Page of 195 295

17 Kitchensink quickstartThis quickstart shows off all the new features of Java EE 6, and makes a great starting point for your project.

Bean Validation

Bean Validation is a new specification in Java EE 6, inspired by Hibernate Validator. It allows

application developers to specify constraints once (often in their domain model), and have them

applied in all layers of the application, protecting data and giving useful feedback to users.

JAX-RS: The Java API for RESTful Web Services

JAX-RS is a new specification in Java EE 6. It allows application developers to easily expose Java

services as RESTful web services.

Switch to the directory and instruct Maven to build and deploy thequickstarts/kitchensink

application:

mvn package jboss-as:deploy

The quickstart uses a Maven plugin to deploy the application. The plugin requires JBoss AS to be running

(you can find out how to start the server in or Installing and starting JBoss AS on Linux, Unix or Mac OS X

).Installing and starting JBoss AS on Windows

Or you can start the server using an IDE, like Eclipse.

Now, check if the application has deployed properly by clicking . Ifhttp://localhost:8080/jboss-as-kitchensink

you see a splash page it's all working!

Should you wish to undeploy the quickstart, or redeploy after making some changes, it's pretty

easy:

- deploy any changes to the application to the application servermvn jboss-as:deploy

- undeploy the example from JBoss ASmvn jboss-as:undeploy

It's time to pull the covers back and dive into the internals of the example application.

17.1 Deploying the Kitchensink example using Eclipse

JBoss AS 7.1

JBoss Community Documentation Page of 196 295

You may choose to deploy the example using Eclipse. You'll need to have JBoss AS started in Eclipse (as

described in ) and to have imported the quickstarts intoStarting JBoss AS from Eclipse with JBoss Tools

Eclipse (as described in ).Importing the quickstarts into Eclipse

With the quickstarts imported, you can deploy the example by right clicking on the

project, and choosing :jboss-as-kitchensink Run As -> Run On Server

Make sure the JBoss AS server is selected, and hit :Finish

JBoss AS 7.1

JBoss Community Documentation Page of 197 295

You should see JBoss AS start up (unless you already started it in Starting JBoss AS from Eclipse with

) and the application deploy in the Console log:JBoss Tools

17.2 The kitchensink example in depth

JBoss AS 7.1

JBoss Community Documentation Page of 198 295

The kitchensink application shows off a number of Java EE technologies such as CDI, JSF, EJB, JTA,

JAX-RS and Arquillian. It does this by providing a member registration database, available via JSF and

JAX-RS.

As usual, let's start by looking at the necessary deployment descriptors. By now, we're very used to seeing

and in (which can be found in the beans.xml faces-config.xml WEB-INF/ src/main/webapp

directory of the example). Notice that, once again, we don't need a . There are two configurationweb.xml

files in (which can be found in the directory of theWEB-INF/classes/META-INF src/main/resources

example) — , which sets up JPA, and which Hibernate, the JPA providerpersistence.xml import.sql

in JBoss AS 7, will use to load the initial users into the application when the application starts. We discussed

both of these files in detail in , and these are largely the same.The login example in depth

Next, let's take a look at the JSF view the user sees. As usual, we use a template to provide the sidebar and

footer. This one lives in :WEB-INF/templates/default.xhtml

JBoss AS 7.1

JBoss Community Documentation Page of 199 295

default.xhtml

03. <html xmlns="http://www.w3.org/1999/xhtml"

04. xmlns:h="http://java.sun.com/jsf/html"

05. xmlns:ui="http://java.sun.com/jsf/facelets">

06. <h:head>

07. <title>kitchensink</title>

08. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

09. <h:outputStylesheet name="css/screen.css" />

10. </h:head>

11. <h:body>

12. <div id="container">

13. <div class="dualbrand">

14. <img src="resources/gfx/dualbrand_logo.png" />

15. </div>

16. <div id="content">

17. <ui:insert name="content">

18. [Template content will be inserted here]

19. </ui:insert>

20. </div>

21. <div id="aside">

22. <p>Learn more about JBoss Enterprise Application Platform 6.</p>

23. <ul>

24. <li><a

25. href="http://red.ht/jbeap-6-docs">Documentation</a></li>

26. <li><a href="http://red.ht/jbeap-6">Product Information</a></li>

27. </ul>

28. <p>Learn more about JBoss AS 7.</p>

29. <ul>

30. <li><a

31.

href="https://docs.jboss.org/author/display/AS7/Getting+Started+Developing+Applications+Guide">Getting

Started Developing Applications Guide</a></li>

32. <li><a href="http://jboss.org/jbossas">Community Project Information</a></li>

33. </ul>

34. </div>

35. <div id="footer">

36. <p>

37. This project was generated from a Maven archetype from

38. JBoss.<br />

39. </p>

40. </div>

41. </div>

42. </h:body>

43. </html>

Line

number

Note

6 - 10 We have a common element, where we define styles and more.<head>

14 - 51, 56

- 61

This application defines a common sidebar and footer, putting them in the template means we

only have to define them once/

JBoss AS 7.1

JBoss Community Documentation Page of 200 295

52 - 54 The content is inserted here, and defined by views using this template.

That leaves the main page, , in which we place the content unique to the main page:index.xhtml

index.xhtml

02. <ui:composition xmlns="http://www.w3.org/1999/xhtml"

03. xmlns:ui="http://java.sun.com/jsf/facelets"

04. xmlns:f="http://java.sun.com/jsf/core"

05. xmlns:h="http://java.sun.com/jsf/html"

06. template="/WEB-INF/templates/default.xhtml">

07. <ui:define name="content">

08. <h1>Welcome to JBoss!</h1>

09.

10. d

11.

12. <h:form id="reg">

13. <h2>Member Registration</h2>

14. <p>Enforces annotation-based constraints defined on the model class.</p>

15. <h:panelGrid columns="3" columnClasses="titleCell">

16. <h:outputLabel for="name" value="Name:"/>

17. <h:inputText id="name" value="#{newMember.name}" />

18. <h:message for="name" errorClass="invalid"/>

19.

20. <h:outputLabel for="email" value="Email:"/>

21. <h:inputText id="email" value="#{newMember.email}"/>

22. <h:message for="email" errorClass="invalid"/>

23.

24. <h:outputLabel for="phoneNumber" value="Phone #:"/>

25. <h:inputText id="phoneNumber" value="#{newMember.phoneNumber}"/>

26. <h:message for="phoneNumber" errorClass="invalid"/>

27. </h:panelGrid>

28.

29. <p>

30. <h:panelGrid columns="2">

31. <h:commandButton id="register" action="#{memberController.register}"

value="Register" styleClass="register"/>

32. <h:messages styleClass="messages" errorClass="invalid" infoClass="valid"

warnClass="warning"

33. globalOnly="true"/>

34. </h:panelGrid>

35. </p>

36. </h:form>

37. <h2>Members</h2>

38. <h:panelGroup rendered="#{empty members}">

39. <em>No registered members.</em>

40. </h:panelGroup>

41. <h:dataTable var="_member" value="#{members}" rendered="#{not empty members}"

styleClass="simpletablestyle">

42. <h:column>

43. <f:facet name="header">Id</f:facet>

44. #{_member.id}

45. </h:column>

46. <h:column>

47. <f:facet name="header">Name</f:facet>

48. #{_member.name}

JBoss AS 7.1

JBoss Community Documentation Page of 201 295

49. </h:column>

50. <h:column>

51. <f:facet name="header">Email</f:facet>

52. #{_member.email}

53. </h:column>

54. <h:column>

55. <f:facet name="header">Phone #</f:facet>

56. #{_member.phoneNumber}

57. </h:column>

58. <h:column>

59. <f:facet name="header">REST URL</f:facet>

60. <a

href="#{request.contextPath}/rest/members/#{_member.id}">/rest/members/#{_member.id}</a>

61. </h:column>

62. <f:facet name="footer">

63. REST URL for all members: <a

href="#{request.contextPath}/rest/members">/rest/members</a>

64. </f:facet>

65. </h:dataTable>

66. </ui:define>

67. </ui:composition>

Line

number

Note

12 - 48 The JSF form allows us to register new users. There should be one already created when the

application started.

22, 31,

40

The application uses Bean Validation to validate data entry. The error messages from Bean

Validation are automatically attached to the relevant field by JSF, and adding a JSFmessages

component will display them.

53 - 77 This application exposes REST endpoints for each registered member. The application helpfully

displays the URL to the REST endpoint on this page.

Next, let's take a look at the entity, before we look at how the application is wired together:Member

Memberjava

20.

21. import javax.persistence.Column;

22. import javax.persistence.Entity;

23. import javax.persistence.GeneratedValue;

24. import javax.persistence.Id;

25. import javax.persistence.Table;

26. import javax.persistence.UniqueConstraint;

27. import javax.validation.constraints.Digits;

28. import javax.validation.constraints.NotNull;

29. import javax.validation.constraints.Pattern;

30. import javax.validation.constraints.Size;

31. import javax.xml.bind.annotation.XmlRootElement;

32.

33. import org.hibernate.validator.constraints.Email;

34. import org.hibernate.validator.constraints.NotEmpty;

JBoss AS 7.1

JBoss Community Documentation Page of 202 295

35.

36. @Entity

37. @XmlRootElement

38. @Table(uniqueConstraints = @UniqueConstraint(columnNames = "email"))

39. public class Member implements Serializable {

40. /** Default value included to remove warning. Remove or modify at will. **/

41. private static final long serialVersionUID = 1L;

42.

43. @Id

44. @GeneratedValue

45. private Long id;

46.

47. @NotNull

48. @Size(min = 1, max = 25)

49. @Pattern(regexp = "[A-Za-z ]*", message = "must contain only letters and spaces")

50. private String name;

51.

52. @NotNull

53. @NotEmpty

54. @Email

55. private String email;

56.

57. @NotNull

58. @Size(min = 10, max = 12)

59. @Digits(fraction = 0, integer = 12)

60. @Column(name = "phone_number")

61. private String phoneNumber;

62.

63. public Long getId() {

64. return id;

65. }

66.

67. public void setId(Long id) {

68. this.id = id;

69. }

70.

71. public String getName() {

72. return name;

73. }

74.

75. public void setName(String name) {

76. this.name = name;

77. }

78.

79. public String getEmail() {

80. return email;

81. }

82.

83. public void setEmail(String email) {

84. this.email = email;

85. }

86.

87. public String getPhoneNumber() {

88. return phoneNumber;

89. }

90.

91. public void setPhoneNumber(String phoneNumber) {

92. this.phoneNumber = phoneNumber;

JBoss AS 7.1

JBoss Community Documentation Page of 203 295

93. }

94. }

Line

number

Note

20 As usual with JPA, we define that the class is an entity by adding @Entity

21 Members are exposed as a RESTful service using JAX-RS. We can use JAXB to map the object

to XML and to do this we need to add .@XmlRootElement

31 - 33 Bean Validation allows constraints to be defined once (on the entity) and applied everywhere.

Here we constrain the person's name to a certain size and regular expression.

38 Hibernate Validator also offers some extra validations such as .@Email

41 - 43 , and are further examples of constraints.@Digits @NotNull @Size

Next, let's take a look at , which is responsible for building the list of members,MemberListProducer

ordered by name. It uses JPA 2 criteria to do this.

JBoss AS 7.1

JBoss Community Documentation Page of 204 295

MemberListProducer.java

18.

19. import javax.annotation.PostConstruct;

20. import javax.enterprise.context.RequestScoped;

21. import javax.enterprise.event.Observes;

22. import javax.enterprise.event.Reception;

23. import javax.enterprise.inject.Produces;

24. import javax.inject.Inject;

25. import javax.inject.Named;

26. import java.util.List;

27.

28. import org.jboss.as.quickstarts.kitchensink.model.Member;

29.

30. @RequestScoped

31. public class MemberListProducer {

32.

33. @Inject

34. private MemberRepository memberRepository;

35.

36. private List<Member> members;

37.

38. // @Named provides access the return value via the EL variable name "members" in the UI

(e.g.,

39. // Facelets or JSP view)

40. @Produces

41. @Named

42. public List<Member> getMembers() {

43. return members;

44. }

45.

46. public void onMemberListChanged(@Observes(notifyObserver = Reception.IF_EXISTS) final

Member member) {

47. retrieveAllMembersOrderedByName();

48. }

49.

50. @PostConstruct

51. public void retrieveAllMembersOrderedByName() {

52. members = memberRepository.findAllOrderedByName();

53. }

54. }

Line

number

Note

18 This bean is request scoped, meaning that any fields (such as ) will be stored for themembers

entire request.

26 - 30 The list of members is exposed as a producer method, it's also available via EL.

32 - 34 The observer method is notified whenever a member is created, removed, or updated. This

allows us to refresh the list of members whenever they are needed. This is a good approach as

it allows us to cache the list of members, but keep it up to date at the same time.

JBoss AS 7.1

JBoss Community Documentation Page of 205 295

36 - 45 JPA 2's criteria API is used to create a list of members sorted by name. You can try out the type

safe criteria API as well by swapping the criteria statements as described.

Let's now look at , the class that allows us to create new members from the JSFMemberRegistration

page Unable to retrieve the URL:Code Snippet error:

https://github.com/jbossas/quickstart/raw/master/kitchensink/src/main/java/org/jboss/as/quickstarts/kitchensink/controller/MemberRegistration.java

status code: 404.

Line

number

Note

18 This bean requires transactions as it needs to write to the database. Making this an EJB gives

us access to declarative transactions - much simpler than manual transaction control!

21 Stereotypes, such as allow grouping of common functionality. Here we use the built in @Model

stereotype to give us a request scoped, named bean.@Model

26 - 28 Seam Solder, used in this project offers an injectable logger based on JBoss Logging.

47 An event is sent every time a member is updated. This allows other pieces of code (in this

example the member list is refreshed) to react to changes in the member list without any

coupling to this class.

Seam Solder is a swiss army knife for any CDI based application. It offers some basic additions to

the CDI programming model (such as an injectable, type-safe, logger) as well as utilities for

developing CDI extensions. You can read more on the .Solder project page

Now, let's take a look at the class, which provides resources such as the entity manager. CDIResources

recommends using "resource producers", as we do in this example, to alias resources to CDI beans,

allowing for a consistent style throughout our application:

JBoss AS 7.1

JBoss Community Documentation Page of 206 295

Resources.java

19. import java.util.logging.Logger;

20.

21. import javax.enterprise.context.RequestScoped;

22. import javax.enterprise.inject.Produces;

23. import javax.enterprise.inject.spi.InjectionPoint;

24. import javax.faces.context.FacesContext;

25. import javax.persistence.EntityManager;

26. import javax.persistence.PersistenceContext;

27.

28. /**

29. * This class uses CDI to alias Java EE resources, such as the persistence context, to CDI

beans

30. *

31. * <p>

32. * Example injection on a managed bean field:

33. * </p>

34. *

35. * <pre>

36. * &#064;Inject

37. * private EntityManager em;

38. * </pre>

39. */

40. public class Resources {

41. // use @SuppressWarnings to tell IDE to ignore warnings about field not being referenced

directly

42. @SuppressWarnings("unused")

43. @Produces

44. @PersistenceContext

45. private EntityManager em;

46.

47. @Produces

48. public Logger produceLog(InjectionPoint injectionPoint) {

49. return Logger.getLogger(injectionPoint.getMember().getDeclaringClass().getName());

50. }

51.

52. @Produces

53. @RequestScoped

54. public FacesContext produceFacesContext() {

55. return FacesContext.getCurrentInstance();

56. }

57.

58. }

Line

number

Note

21 - 24 We use the "resource producer" pattern, from CDI, to "alias" the old fashioned

injection of the entity manager to a CDI style injection. This allows us@PersistenceContext

to use.

If you want to define your own datasource, take a look at the or at .Getting Started Guide the JBoss AS wiki

JBoss AS 7.1

JBoss Community Documentation Page of 207 295

Before we wrap up our tour of the kitchensink example application, let's take a look at how the JAX-RS

endpoints are created. Firstly, {JaxRSActivator}}, which extends and is annotated with Application

, is the Java EE 6 "no XML" approach to activating JAX-RS.@ApplicationPath

The real work goes in , which produces the endpoint:MemberResourceRESTService

MembeResourceRESTService.java

020. import java.util.HashSet;

021. import java.util.List;

022. import java.util.Map;

023. import java.util.Set;

024. import java.util.logging.Logger;

025.

026. import javax.enterprise.context.RequestScoped;

027. import javax.inject.Inject;

028. import javax.persistence.NoResultException;

029. import javax.validation.ConstraintViolation;

030. import javax.validation.ConstraintViolationException;

031. import javax.validation.ValidationException;

032. import javax.validation.Validator;

033. import javax.ws.rs.Consumes;

034. import javax.ws.rs.GET;

035. import javax.ws.rs.POST;

036. import javax.ws.rs.Path;

037. import javax.ws.rs.PathParam;

038. import javax.ws.rs.Produces;

039. import javax.ws.rs.WebApplicationException;

040. import javax.ws.rs.core.MediaType;

041. import javax.ws.rs.core.Response;

042.

043. import org.jboss.as.quickstarts.kitchensink.data.MemberRepository;

044. import org.jboss.as.quickstarts.kitchensink.model.Member;

045. import org.jboss.as.quickstarts.kitchensink.service.MemberRegistration;

046.

047. /**

048. * JAX-RS Example

049. * <p/>

050. * This class produces a RESTful service to read/write the contents of the members table.

051. */

052. @Path("/members")

053. @RequestScoped

054. public class MemberResourceRESTService {

055. @Inject

056. private Logger log;

057.

058. @Inject

059. private Validator validator;

060.

061. @Inject

062. private MemberRepository repository;

063.

064. @Inject

065. MemberRegistration registration;

066.

067. @GET

JBoss AS 7.1

JBoss Community Documentation Page of 208 295

068. @Produces(MediaType.APPLICATION_JSON)

069. public List<Member> listAllMembers() {

070. return repository.findAllOrderedByName();

071. }

072.

073. @GET

074. @Path("/{id:[0-9][0-9]*}")

075. @Produces(MediaType.APPLICATION_JSON)

076. public Member lookupMemberById(@PathParam("id") long id) {

077. Member member = repository.findById(id);

078. if (member == null) {

079. throw new WebApplicationException(Response.Status.NOT_FOUND);

080. }

081. return member;

082. }

083.

084. /**

085. * Creates a new member from the values provided. Performs validation, and will return

a JAX-RS response with either

086. * 200 ok, or with a map of fields, and related errors.

087. */

088. @POST

089. @Consumes(MediaType.APPLICATION_JSON)

090. @Produces(MediaType.APPLICATION_JSON)

091. public Response createMember(Member member) {

092.

093. Response.ResponseBuilder builder = null;

094.

095. try {

096. //Validates member using bean validation

097. validateMember(member);

098.

099. registration.register(member);

100.

101. //Create an "ok" response

102. builder = Response.ok();

103. } catch (ConstraintViolationException ce) {

104. //Handle bean validation issues

105. builder = createViolationResponse(ce.getConstraintViolations());

106. } catch (ValidationException e) {

107. //Handle the unique constrain violation

108. Map<String, String> responseObj = new HashMap<String, String>();

109. responseObj.put("email", "Email taken");

110. builder = Response.status(Response.Status.CONFLICT).entity(responseObj);

111. } catch (Exception e) {

112. // Handle generic exceptions

113. Map<String, String> responseObj = new HashMap<String, String>();

114. responseObj.put("error", e.getMessage());

115. builder = Response.status(Response.Status.BAD_REQUEST).entity(responseObj);

116. }

117.

118. return builder.build();

119. }

120.

121.

122. /**

123. * <p>Validates the given Member variable and throws validation exceptions based on the

type of error.

JBoss AS 7.1

JBoss Community Documentation Page of 209 295

124. * If the error is standard bean validation errors then it will throw a

ConstraintValidationException

125. * with the set of the constraints violated.</p>

126. * <p>If the error is caused because an existing member with the same email is

registered it throws a regular

127. * validation exception so that it can be interpreted separately.</p>

128. *

129. * @param member Member to be validated

130. * @throws ConstraintViolationException If Bean Validation errors exist

131. * @throws ValidationException If member with the same email already exists

132. */

133. private void validateMember(Member member) throws ConstraintViolationException,

ValidationException {

134. //Create a bean validator and check for issues.

135. Set<ConstraintViolation<Member>> violations = validator.validate(member);

136.

137. if (!violations.isEmpty()) {

138. throw new ConstraintViolationException(new

HashSet<ConstraintViolation<?>>(violations));

139. }

140.

141. //Check the uniqueness of the email address

142. if (emailAlreadyExists(member.getEmail())) {

143. throw new ValidationException("Unique Email Violation");

144. }

145. }

146.

147. /**

148. * Creates a JAX-RS "Bad Request" response including a map of all violation fields, and

their message.

149. * This can then be used by clients to show violations.

150. *

151. * @param violations A set of violations that needs to be reported

152. * @return JAX-RS response containing all violations

153. */

154. private Response.ResponseBuilder createViolationResponse(Set<ConstraintViolation<?>>

violations) {

155. log.fine("Validation completed. violations found: " + violations.size());

156.

157. Map<String, String> responseObj = new HashMap<String, String>();

158.

159. for (ConstraintViolation<?> violation : violations) {

160. responseObj.put(violation.getPropertyPath().toString(),

violation.getMessage());

161. }

162.

163. return Response.status(Response.Status.BAD_REQUEST).entity(responseObj);

164. }

165.

166. /**

167. * Checks if a member with the same email address is already registered. This is the

only way to

168. * easily capture the "@UniqueConstraint(columnNames = "email")" constraint from the

Member class.

169. *

170. * @param email The email to check

171. * @return True if the email already exists, and false otherwise

172. */

JBoss AS 7.1

JBoss Community Documentation Page of 210 295

173. public boolean emailAlreadyExists(String email) {

174. Member member = null;

175. try {

176. member = repository.findByEmail(email);

177. } catch (NoResultException e) {

178. // ignore

179. }

180. return member != null;

181. }

182. }

Line

number

Note

20 The annotation tells JAX-RS that this class provides a REST endpoint mapped to @Path

(concatenating the path from the activator with the path for this endpoint).rest/members

23, 24 JAX-RS endpoints are CDI enabled, and can use CDI-style injection.

26 - 35 The method is called when the raw endpoint is accessed and offers up alistAllMembers()

list of endpoints. Notice that the object is automatically mapped to XML by JAXB.

37 - 42 The method is called when the endpoint is accessed with a member idlookupMemberById()

parameter appended (for example rest/members/1). Again, the object is automatically mapped

to XML by JAXB.

17.2.1 Arquillian

If you've been following along with the Test Driven Development craze of the past few years, you're probably

getting a bit nervous by now, wondering how on earth you are going to test your application. Lucky for you,

the Arquillian project is here to help!

Arquillian provides all the boiler plate for running your test inside JBoss AS, allowing you to concentrate on

testing your application. In order to do that, it utilizes Shrinkwrap, a fluent API for defining packaging, to

create an archive to deploy. We'll go through the testcase, and how you configure Arquillian in just a

moment, but first let's run the test.

Before we start, we need to let Arquillian know the path to our JBoss AS install. Open up

and set the property to the path to your JBoss ASsrc/test/resources/arquillian.xml jbossHome

install:

JBoss AS 7.1

JBoss Community Documentation Page of 211 295

Now, make sure JBoss AS is not running (so that the instance started for running the test does not interfere),

and then run the tests from the command line by typing:

mvn clean test -Parq-jbossas-managed

You should see JBoss AS start up, a deployed, test executed, and then the results displayed totest.war

you on the console:

$ > mvn clean test -Parq-jbossas-managed

[INFO] Scanning for projects...

[INFO]

[INFO] ------------------------------------------------------------------------

[INFO] Building JBoss AS Quickstarts: Kitchensink 7.0.0-SNAPSHOT

[INFO] ------------------------------------------------------------------------

[INFO]

[INFO] --- maven-clean-plugin:2.4.1:clean (default-clean) @ jboss-as-kitchensink ---

[INFO] Deleting /Users/pmuir/workspace/jboss-as-docs/quickstarts/kitchensink/target

[INFO]

[INFO] --- maven-resources-plugin:2.4.3:resources (default-resources) @ jboss-as-kitchensink ---

[INFO] Using 'UTF-8' encoding to copy filtered resources.

[INFO] Copying 2 resources

[INFO]

[INFO] --- maven-compiler-plugin:2.3.1:compile (default-compile) @ jboss-as-kitchensink ---

[INFO] Compiling 6 source files to

/Users/pmuir/workspace/jboss-as-docs/quickstarts/kitchensink/target/classes

[INFO]

[INFO] --- maven-resources-plugin:2.4.3:testResources (default-testResources) @

jboss-as-kitchensink ---

[INFO] Using 'UTF-8' encoding to copy filtered resources.

[INFO] Copying 1 resource

[INFO]

[INFO] --- maven-compiler-plugin:2.3.1:testCompile (default-testCompile) @ jboss-as-kitchensink

---

[INFO] Compiling 1 source file to

/Users/pmuir/workspace/jboss-as-docs/quickstarts/kitchensink/target/test-classes

[INFO]

[INFO] --- maven-surefire-plugin:2.7.2:test (default-test) @ jboss-as-kitchensink ---

[INFO] Surefire report directory:

/Users/pmuir/workspace/jboss-as-docs/quickstarts/kitchensink/target/surefire-reports

-------------------------------------------------------

T E S T S

-------------------------------------------------------

Running org.jboss.as.quickstarts.kitchensink.test.MemberRegistrationTest

Jun 25, 2011 7:17:49 PM

org.jboss.arquillian.container.impl.client.container.ContainerRegistryCreator

getActivatedConfiguration

INFO: Could not read active container configuration: null

log4j:WARN No appenders could be found for logger (org.jboss.remoting).

log4j:WARN Please initialize the log4j system properly.

Jun 25, 2011 7:17:54 PM org.jboss.as.arquillian.container.managed.ManagedDeployableContainer

startInternal

JBoss AS 7.1

JBoss Community Documentation Page of 212 295

INFO: Starting container with: [java, -Djboss.home.dir=/Users/pmuir/development/jboss,

-Dorg.jboss.boot.log.file=/Users/pmuir/development/jboss/standalone/log/boot.log,

-Dlogging.configuration=file:/Users/pmuir/development/jboss/standalone/configuration/logging.properties,

-jar, /Users/pmuir/development/jboss/jboss-modules.jar, -mp,

/Users/pmuir/development/jboss/modules, -logmodule, org.jboss.logmanager, -jaxpmodule,

javax.xml.jaxp-provider, org.jboss.as.standalone, -server-config, standalone.xml]

19:17:55,107 INFO [org.jboss.modules] JBoss Modules version 1.0.0.CR4

19:17:55,329 INFO [org.jboss.msc] JBoss MSC version 1.0.0.CR2

19:17:55,386 INFO [org.jboss.as] JBoss AS 7.0.0.Beta4-SNAPSHOT "(TBD)" starting

19:17:56,159 INFO [org.jboss.as] creating http management service using network interface

(management) port (9990) securePort (-1)

19:17:56,181 INFO [org.jboss.as.logging] Removing bootstrap log handlers

19:17:56,189 INFO [org.jboss.as.naming] (Controller Boot Thread) Activating Naming Subsystem

19:17:56,203 INFO [org.jboss.as.naming] (MSC service thread 1-4) Starting Naming Service

19:17:56,269 INFO [org.jboss.as.security] (Controller Boot Thread) Activating Security

Subsystem

19:17:56,305 INFO [org.jboss.remoting] (MSC service thread 1-1) JBoss Remoting version

3.2.0.Beta2

19:17:56,317 INFO [org.xnio] (MSC service thread 1-1) XNIO Version 3.0.0.Beta3

19:17:56,331 INFO [org.xnio.nio] (MSC service thread 1-1) XNIO NIO Implementation Version

3.0.0.Beta3

19:17:56,522 INFO [org.jboss.as.connector.subsystems.datasources] (Controller Boot Thread)

Deploying JDBC-compliant driver class org.h2.Driver (version 1.2)

19:17:56,572 INFO [org.apache.catalina.core.AprLifecycleListener] (MSC service thread 1-7) The

Apache Tomcat Native library which allows optimal performance in production environments was not

found on the java.library.path:

.:/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java

19:17:56,627 INFO [org.jboss.as.remoting] (MSC service thread 1-3) Listening on /127.0.0.1:9999

19:17:56,641 INFO [org.jboss.as.jmx.JMXConnectorService] (MSC service thread 1-2) Starting

remote JMX connector

19:17:56,705 INFO [org.jboss.as.ee] (Controller Boot Thread) Activating EE subsystem

19:17:56,761 INFO [org.apache.coyote.http11.Http11Protocol] (MSC service thread 1-7) Starting

Coyote HTTP/1.1 on http--127.0.0.1-8080

19:17:56,793 INFO [org.jboss.as.connector] (MSC service thread 1-3) Starting JCA Subsystem

(JBoss IronJacamar 1.0.0.CR2)

19:17:56,837 INFO [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-2)

Bound data source [java:jboss/datasources/ExampleDS]

19:17:57,335 INFO [org.jboss.as.server.deployment] (MSC service thread 1-1) Starting deployment

of "arquillian-service"

19:17:57,348 INFO [org.jboss.as.deployment] (MSC service thread 1-7) Started

FileSystemDeploymentService for directory /Users/pmuir/development/jboss/standalone/deployments

19:17:57,693 INFO [org.jboss.as] (Controller Boot Thread) JBoss AS 7.0.0.Beta4-SNAPSHOT "(TBD)"

started in 2806ms - Started 111 of 138 services (27 services are passive or on-demand)

19:18:00,596 INFO [org.jboss.as.server.deployment] (MSC service thread 1-6) Stopped deployment

arquillian-service in 8ms

19:18:01,394 INFO [org.jboss.as.server.deployment] (pool-2-thread-7) Content added at location

/Users/pmuir/development/jboss/standalone/data/content/0a/9e20b7bc978fd2778b89c7c06e4d3e1f308dfe/content19:18:01,403

INFO [org.jboss.as.server.deployment] (MSC service thread 1-7) Starting deployment of

"arquillian-service"

19:18:01,650 INFO [org.jboss.as.server.deployment] (pool-2-thread-6) Content added at location

/Users/pmuir/development/jboss/standalone/data/content/94/8324ab8f5a693c67fa57b59323304d3947bbf6/content19:18:01,659

INFO [org.jboss.as.server.deployment] (MSC service thread 1-5) Starting deployment of

"test.war"

19:18:01,741 INFO [org.jboss.jpa] (MSC service thread 1-7) read persistence.xml for primary

19:18:01,764 INFO [org.jboss.weld] (MSC service thread 1-3) Processing CDI deployment: test.war

19:18:01,774 INFO

[org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service

thread 1-3) JNDI bindings for session bean named MemberRegistration in deployment unit

JBoss AS 7.1

JBoss Community Documentation Page of 213 295

deployment "test.war" are as follows:

java:global/test/MemberRegistration!org.jboss.as.quickstarts.kitchensink.controller.MemberRegistration

java:app/test/MemberRegistration!org.jboss.as.quickstarts.kitchensink.controller.MemberRegistration

java:module/MemberRegistration!org.jboss.as.quickstarts.kitchensink.controller.MemberRegistration

java:global/test/MemberRegistration

java:app/test/MemberRegistration

java:module/MemberRegistration

19:18:01,908 INFO [org.jboss.weld] (MSC service thread 1-5) Starting Services for CDI

deployment: test.war

19:18:02,131 INFO [org.jboss.weld.Version] (MSC service thread 1-5) WELD-000900 1.1.1 (Final)

19:18:02,169 INFO [org.jboss.weld] (MSC service thread 1-2) Starting weld service

19:18:02,174 INFO [org.jboss.as.arquillian] (MSC service thread 1-3) Arquillian deployment

detected:

ArquillianConfig[service=jboss.arquillian.config."test.war",unit=test.war,tests=[org.jboss.as.quickstarts.kitchensink.test.MemberRegistrationTest]]19:18:02,179

INFO [org.jboss.jpa] (MSC service thread 1-6) starting Persistence Unit Service

'test.war#primary'

19:18:02,322 INFO [org.hibernate.annotations.common.Version] (MSC service thread 1-6) Hibernate

Commons Annotations 3.2.0.Final

19:18:02,328 INFO [org.hibernate.cfg.Environment] (MSC service thread 1-6) HHH00412:Hibernate

[WORKING]

19:18:02,330 INFO [org.hibernate.cfg.Environment] (MSC service thread 1-6)

HHH00206:hibernate.properties not found

19:18:02,332 INFO [org.hibernate.cfg.Environment] (MSC service thread 1-6) HHH00021:Bytecode

provider name : javassist

19:18:02,354 INFO [org.hibernate.ejb.Ejb3Configuration] (MSC service thread 1-6)

HHH00204:Processing PersistenceUnitInfo [

name: primary

...]

19:18:02,400 WARN [org.hibernate.cfg.AnnotationBinder] (MSC service thread 1-6)

HHH00194:Package not found or wo package-info.java: org.jboss.as.quickstarts.kitchensink.test

19:18:02,400 WARN [org.hibernate.cfg.AnnotationBinder] (MSC service thread 1-6)

HHH00194:Package not found or wo package-info.java:

org.jboss.as.quickstarts.kitchensink.controller

19:18:02,401 WARN [org.hibernate.cfg.AnnotationBinder] (MSC service thread 1-6)

HHH00194:Package not found or wo package-info.java: org.jboss.as.quickstarts.kitchensink.util

19:18:02,401 WARN [org.hibernate.cfg.AnnotationBinder] (MSC service thread 1-6)

HHH00194:Package not found or wo package-info.java: org.jboss.as.quickstarts.kitchensink.model

19:18:02,592 INFO [org.hibernate.service.jdbc.connections.internal.ConnectionProviderInitiator]

(MSC service thread 1-6) HHH00130:Instantiating explicit connection provider:

org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider

19:18:02,852 INFO [org.hibernate.dialect.Dialect] (MSC service thread 1-6) HHH00400:Using

dialect: org.hibernate.dialect.H2Dialect

19:18:02,858 WARN [org.hibernate.dialect.H2Dialect] (MSC service thread 1-6) HHH00431:Unable to

determine H2 database version, certain features may not work

19:18:02,862 INFO [org.hibernate.engine.jdbc.internal.LobCreatorBuilder] (MSC service thread

1-6) HHH00423:Disabling contextual LOB creation as JDBC driver reported JDBC version [3] less

than 4

19:18:02,870 INFO [org.hibernate.engine.transaction.internal.TransactionFactoryInitiator] (MSC

service thread 1-6) HHH00268:Transaction strategy:

org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory

19:18:02,874 INFO [org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory] (MSC service

thread 1-6) HHH00397:Using ASTQueryTranslatorFactory

19:18:02,911 INFO [org.hibernate.validator.util.Version] (MSC service thread 1-6) Hibernate

Validator 4.1.0.Final

19:18:02,917 INFO [org.hibernate.validator.engine.resolver.DefaultTraversableResolver] (MSC

service thread 1-6) Instantiated an instance of

JBoss AS 7.1

JBoss Community Documentation Page of 214 295

org.hibernate.validator.engine.resolver.JPATraversableResolver.

19:18:03,079 INFO [org.hibernate.tool.hbm2ddl.SchemaExport] (MSC service thread 1-6)

HHH00227:Running hbm2ddl schema export

19:18:03,093 INFO [org.hibernate.tool.hbm2ddl.SchemaExport] (MSC service thread 1-6)

HHH00230:Schema export complete

19:18:03,217 INFO [org.jboss.web] (MSC service thread 1-5) registering web context: /test

19:18:03,407 WARN [org.jboss.weld.Bean] (RMI TCP Connection(3)-127.0.0.1) WELD-000018 Executing

producer field or method [method] @Produces public

org.jboss.as.quickstarts.kitchensink.test.MemberRegistrationTest.produceLog(InjectionPoint) on

incomplete declaring bean Managed Bean [class

org.jboss.as.quickstarts.kitchensink.test.MemberRegistrationTest] with qualifiers [@Any

@Default] due to circular injection

19:18:03,427 WARN [org.jboss.weld.Bean] (RMI TCP Connection(3)-127.0.0.1) WELD-000018 Executing

producer field or method [method] @Produces public

org.jboss.as.quickstarts.kitchensink.test.MemberRegistrationTest.produceLog(InjectionPoint) on

incomplete declaring bean Managed Bean [class

org.jboss.as.quickstarts.kitchensink.test.MemberRegistrationTest] with qualifiers [@Any

@Default] due to circular injection

19:18:03,450 WARN [org.jboss.as.ejb3.component.EJBComponent] (RMI TCP Connection(3)-127.0.0.1)

EJBTHREE-2120: deprecated getTransactionAttributeType method called (dev problem)

19:18:03,459 INFO [org.jboss.as.quickstarts.kitchensink.controller.MemberRegistration] (RMI TCP

Connection(3)-127.0.0.1) Registering Jane Doe

19:18:03,616 INFO [org.jboss.as.quickstarts.kitchensink.test.MemberRegistrationTest] (RMI TCP

Connection(3)-127.0.0.1) Jane Doe was persisted with id 1

19:18:03,686 INFO [org.jboss.jpa] (MSC service thread 1-1) stopping Persistence Unit Service

'test.war#primary'

19:18:03,687 INFO [org.hibernate.tool.hbm2ddl.SchemaExport] (MSC service thread 1-1)

HHH00227:Running hbm2ddl schema export

19:18:03,690 INFO [org.jboss.weld] (MSC service thread 1-3) Stopping weld service

19:18:03,692 INFO [org.hibernate.tool.hbm2ddl.SchemaExport] (MSC service thread 1-1)

HHH00230:Schema export complete

19:18:03,704 INFO [org.jboss.as.server.deployment] (MSC service thread 1-8) Stopped deployment

test.war in 52ms

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 14.859 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------

[INFO] BUILD SUCCESS

[INFO] ------------------------------------------------------------------------

[INFO] Total time: 22.305s

[INFO] Finished at: Sat Jun 25 19:18:04 BST 2011

[INFO] Final Memory: 17M/125M

[INFO] ------------------------------------------------------------------------

$ >

As you can see, that didn't take too long (approximately 15s), and is great for running in your QA

environment, but if you running locally, you might prefer to connect to a running JBoss AS. To do that, start

up JBoss AS (as described in ). Now, run your test, but use the Getting started with JBoss AS

profile:arq-jbossas-remote

mvn clean test -Parq-jbossas-remote

JBoss AS 7.1

JBoss Community Documentation Page of 215 295

$> mvn clean test -Parq-jbossas-remote

[INFO] Scanning for projects...

[INFO]

[INFO] ------------------------------------------------------------------------

[INFO] Building JBoss AS Quickstarts: Kitchensink 7.0.0-SNAPSHOT

[INFO] ------------------------------------------------------------------------

[INFO]

[INFO] --- maven-clean-plugin:2.4.1:clean (default-clean) @ jboss-as-kitchensink ---

[INFO] Deleting /Users/pmuir/workspace/jboss-as-docs/quickstarts/kitchensink/target

[INFO]

[INFO] --- maven-resources-plugin:2.4.3:resources (default-resources) @ jboss-as-kitchensink ---

[INFO] Using 'UTF-8' encoding to copy filtered resources.

[INFO] Copying 2 resources

[INFO]

[INFO] --- maven-compiler-plugin:2.3.1:compile (default-compile) @ jboss-as-kitchensink ---

[INFO] Compiling 6 source files to

/Users/pmuir/workspace/jboss-as-docs/quickstarts/kitchensink/target/classes

[INFO]

[INFO] --- maven-resources-plugin:2.4.3:testResources (default-testResources) @

jboss-as-kitchensink ---

[INFO] Using 'UTF-8' encoding to copy filtered resources.

[INFO] Copying 1 resource

[INFO]

[INFO] --- maven-compiler-plugin:2.3.1:testCompile (default-testCompile) @ jboss-as-kitchensink

---

[INFO] Compiling 1 source file to

/Users/pmuir/workspace/jboss-as-docs/quickstarts/kitchensink/target/test-classes

[INFO]

[INFO] --- maven-surefire-plugin:2.7.2:test (default-test) @ jboss-as-kitchensink ---

[INFO] Surefire report directory:

/Users/pmuir/workspace/jboss-as-docs/quickstarts/kitchensink/target/surefire-reports

-------------------------------------------------------

T E S T S

-------------------------------------------------------

Running org.jboss.as.quickstarts.kitchensink.test.MemberRegistrationTest

Jun 25, 2011 7:22:28 PM

org.jboss.arquillian.container.impl.client.container.ContainerRegistryCreator

getActivatedConfiguration

INFO: Could not read active container configuration: null

log4j:WARN No appenders could be found for logger

(org.jboss.as.arquillian.container.MBeanServerConnectionProvider).

log4j:WARN Please initialize the log4j system properly.

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 4.13 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------

[INFO] BUILD SUCCESS

[INFO] ------------------------------------------------------------------------

[INFO] Total time: 10.474s

[INFO] Finished at: Sat Jun 25 19:22:33 BST 2011

[INFO] Final Memory: 17M/125M

JBoss AS 7.1

JBoss Community Documentation Page of 216 295

[INFO] ------------------------------------------------------------------------

$ >

Arquillian defines two modes, and . The mode will take care of startingmanaged remote managed

and stopping the server for you, whilst the mode connects to an already running server.remote

This time you can see the test didn't start JBoss AS (if you check the instance you started, you will see the

application was deployed there), and the test ran a lot faster (approximately 4s).

We can also run the test from Eclipse, in both managed and remote modes. First, we'll run in in managed

mode. In order to set up the correct dependencies on your classpath, right click on the project, and select

:Properties

JBoss AS 7.1

JBoss Community Documentation Page of 217 295

Now, locate the Maven panel:

JBoss AS 7.1

JBoss Community Documentation Page of 218 295

And activate the profile:arq-jbossas-managed

JBoss AS 7.1

JBoss Community Documentation Page of 219 295

Finally, hit , and then confirm you want to update the project configuration:Ok

Once the project has built, locate the in , right click on theMemberRegistrationTest src/test/java

test, and choose :Run As -> JUnit Test...

JBoss AS 7.1

JBoss Community Documentation Page of 220 295

You should see JBoss AS start in the Eclipse Console, the test be deployed, and finally the JUnit View pop

up with the result (a pass of course!).

We can also run the test in an already running instance of Eclipse. Simply change the active profile to

:arq-jbossas-remote

JBoss AS 7.1

JBoss Community Documentation Page of 221 295

Now, make sure JBoss AS is running, right click on the test case and choose :Run As -> JUnit Test

JBoss AS 7.1

JBoss Community Documentation Page of 222 295

Again, you'll see the test run in the server, and the JUnit View pop up, with the test passing.

So far so good, the test is running in both Eclipse and from the command line. But what does the test look

like?

JBoss AS 7.1

JBoss Community Documentation Page of 223 295

MemberRegistrationTest.java

23. import javax.inject.Inject;

24.

25. import org.jboss.arquillian.container.test.api.Deployment;

26. import org.jboss.arquillian.junit.Arquillian;

27. import org.jboss.as.quickstarts.kitchensink.model.Member;

28. import org.jboss.as.quickstarts.kitchensink.service.MemberRegistration;

29. import org.jboss.as.quickstarts.kitchensink.util.Resources;

30. import org.jboss.shrinkwrap.api.Archive;

31. import org.jboss.shrinkwrap.api.ShrinkWrap;

32. import org.jboss.shrinkwrap.api.asset.EmptyAsset;

33. import org.jboss.shrinkwrap.api.spec.WebArchive;

34. import org.junit.Test;

35. import org.junit.runner.RunWith;

36.

37. @RunWith(Arquillian.class)

38. public class MemberRegistrationTest {

39. @Deployment

40. public static Archive<?> createTestArchive() {

41. return ShrinkWrap.create(WebArchive.class, "test.war")

42. .addClasses(Member.class, MemberRegistration.class, Resources.class)

43. .addAsResource("META-INF/test-persistence.xml", "META-INF/persistence.xml")

44. .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")

45. // Deploy our test datasource

46. .addAsWebInfResource("test-ds.xml", "test-ds.xml");

47. }

48.

49. @Inject

50. MemberRegistration memberRegistration;

51.

52. @Inject

53. Logger log;

54.

55. @Test

56. public void testRegister() throws Exception {

57. Member newMember = new Member();

58. newMember.setName("Jane Doe");

59. newMember.setEmail("[email protected]");

60. newMember.setPhoneNumber("2125551234");

61. memberRegistration.register(newMember);

62. assertNotNull(newMember.getId());

63. log.info(newMember.getName() + " was persisted with id " + newMember.getId());

64. }

65.

66. }

Line

number

Note

23 tells JUnit to hand control over to Arquillian when executing@RunWith(Arquillian.class)

tests

JBoss AS 7.1

JBoss Community Documentation Page of 224 295

25 The annotation identifies the static method to Arquillian@Deployment createTestArchive

as the one to use to determine which resources and classes to deploy

28 We add just the classes needed for the test, no more

29 We also add as our test is going to use the databasepersistence.xml

30 Of course, we must add to enable CDIbeans.xml

24 - 28 Arquillian allows us to inject beans into the test case

41 - 49 The test method works as you would expect - creates a new member, registers them, and then

verifies that the member was created

As you can see, Arquillian has lived up to the promise - the test case is focused on to test (the what

method) and to test (the method). It's also worth noting that this isn't a simplistic@Deployment how @Test

unit test - this is a fully fledged integration test that uses the database.

Now, let's look at how we configure Arquillian. First of all, let's take a look at in arquillian.xml

.src/test/resources

JBoss AS 7.1

JBoss Community Documentation Page of 225 295

arquillian.xml

02. <!-- JBoss, Home of Professional Open Source Copyright 2012, Red Hat, Inc.

03. and/or its affiliates, and individual contributors by the @authors tag. See

04. the copyright.txt in the distribution for a full listing of individual contributors.

05. Licensed under the Apache License, Version 2.0 (the "License"); you may not

06. use this file except in compliance with the License. You may obtain a copy

07. of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required

08. by applicable law or agreed to in writing, software distributed under the

09. License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS

10. OF ANY KIND, either express or implied. See the License for the specific

11. language governing permissions and limitations under the License. -->

12. <arquillian xmlns="http://jboss.org/schema/arquillian"

13. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

14. xsi:schemaLocation="http://jboss.org/schema/arquillian

15. http://jboss.org/schema/arquillian/arquillian_1_0.xsd">

16.

17. <!-- Uncomment to have test archives exported to the file system for inspection -->

18. <!-- <engine> -->

19. <!-- <property name="deploymentExportPath">target/</property> -->

20. <!-- </engine> -->

21.

22. <!-- Force the use of the Servlet 3.0 protocol with all containers, as it is the most

mature -->

23. <defaultProtocol type="Servlet 3.0" />

24.

25. <!-- Example configuration for a remote JBoss AS 7 instance -->

26. <container qualifier="jboss" default="true">

27. <!-- If you want to use the JBOSS_HOME environment variable, just delete the jbossHome

property -->

28. <configuration>

29. <property name="jbossHome">/path/to/jboss/as</property>

30. </configuration>

31. </container>

32.

33. </arquillian>

Line

number

Note

9 Arquillian deploys the test war to JBoss AS, and doesn't write it to disk. For debugging, it can be

very useful to see exactly what is in your war, so Arquillian allows you to export the war when

the tests runs

13 - 17 Arquillian currently needs configuring to use JMX to connect to JBoss AS

Now, we need to look at how we select between containers in the :pom.xml

JBoss AS 7.1

JBoss Community Documentation Page of 226 295

pom.xml

197. <source>1.6</source>

198. <target>1.6</target>

199. </configuration>

200. </plugin>

201. <plugin>

202. <artifactId>maven-war-plugin</artifactId>

203. <version>2.1.1</version>

204. <configuration>

205. <!-- Java EE 6 doesn't require web.xml, Maven needs to

206. catch up! -->

207. <failOnMissingWebXml>false</failOnMissingWebXml>

208. </configuration>

209. </plugin>

210. <!-- The JBoss AS plugin deploys your war to a local JBoss AS

211. container -->

212. <!-- To use, run: mvn package jboss-as:deploy -->

213. <plugin>

214. <groupId>org.jboss.as.plugins</groupId>

215. <artifactId>jboss-as-maven-plugin</artifactId>

216. <version>7.1.1.Final</version>

217. </plugin>

218. </plugins>

219. </build>

220.

221. <profiles>

222. <profile>

223. <!-- The default profile skips all tests, though you can tune

224. it to run just unit tests based on a custom pattern -->

225. <!-- Seperate profiles are provided for running all tests, including

226. Arquillian tests that execute in the specified container -->

227. <id>default</id>

Line

number

Note

204 The profile needs an id so we can activate from Eclipse or the command line

206 - 211 Arquillian decides which container to use depending on your classpath. Here we define the

managed JBoss AS container.

222 - 217 Arquillian decides which container to use depending on your classpath. Here we define the

remote JBoss AS container.

And that's it! As you can see Arquillian delivers simple and true testing. You can concentrate on writing your

test functionality, and run your tests in the same environment in which you will run your application.

Arquillian also offers other containers, allowing you to run your tests against Weld Embedded

(super fast, but your enterprise services are mocked), GlassFish, and more

JBoss AS 7.1

JBoss Community Documentation Page of 227 295

That concludes our tour of the kitchensink quickstart. If you would like to use this project as a basis for your

own application on JBoss AS, you can of course copy this application sources and modify it.

17.3 Deploying the Kitchensink example using Eclipse

You may choose to deploy the example using Eclipse. You'll need to have JBoss AS started in Eclipse (as

described in ) and to have imported the quickstarts intoStarting JBoss AS from Eclipse with JBoss Tools

Eclipse (as described in ).Importing the quickstarts into Eclipse

With the quickstarts imported, you can deploy the example by right clicking on the

project, and choosing :jboss-as-kitchensink Run As -> Run On Server

Make sure the JBoss AS server is selected, and hit :Finish

JBoss AS 7.1

JBoss Community Documentation Page of 228 295

You should see JBoss AS start up (unless you already started it in Starting JBoss AS from Eclipse with

) and the application deploy in the Console log:JBoss Tools

17.4 The kitchensink example in depth

JBoss AS 7.1

JBoss Community Documentation Page of 229 295

The kitchensink application shows off a number of Java EE technologies such as CDI, JSF, EJB, JTA,

JAX-RS and Arquillian. It does this by providing a member registration database, available via JSF and

JAX-RS.

As usual, let's start by looking at the necessary deployment descriptors. By now, we're very used to seeing

and in (which can be found in the beans.xml faces-config.xml WEB-INF/ src/main/webapp

directory of the example). Notice that, once again, we don't need a . There are two configurationweb.xml

files in (which can be found in the directory of theWEB-INF/classes/META-INF src/main/resources

example) — , which sets up JPA, and which Hibernate, the JPA providerpersistence.xml import.sql

in JBoss AS 7, will use to load the initial users into the application when the application starts. We discussed

both of these files in detail in , and these are largely the same.The login example in depth

Next, let's take a look at the JSF view the user sees. As usual, we use a template to provide the sidebar and

footer. This one lives in :WEB-INF/templates/default.xhtml

JBoss AS 7.1

JBoss Community Documentation Page of 230 295

default.xhtml

03. <html xmlns="http://www.w3.org/1999/xhtml"

04. xmlns:h="http://java.sun.com/jsf/html"

05. xmlns:ui="http://java.sun.com/jsf/facelets">

06. <h:head>

07. <title>kitchensink</title>

08. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

09. <h:outputStylesheet name="css/screen.css" />

10. </h:head>

11. <h:body>

12. <div id="container">

13. <div class="dualbrand">

14. <img src="resources/gfx/dualbrand_logo.png" />

15. </div>

16. <div id="content">

17. <ui:insert name="content">

18. [Template content will be inserted here]

19. </ui:insert>

20. </div>

21. <div id="aside">

22. <p>Learn more about JBoss Enterprise Application Platform 6.</p>

23. <ul>

24. <li><a

25. href="http://red.ht/jbeap-6-docs">Documentation</a></li>

26. <li><a href="http://red.ht/jbeap-6">Product Information</a></li>

27. </ul>

28. <p>Learn more about JBoss AS 7.</p>

29. <ul>

30. <li><a

31.

href="https://docs.jboss.org/author/display/AS7/Getting+Started+Developing+Applications+Guide">Getting

Started Developing Applications Guide</a></li>

32. <li><a href="http://jboss.org/jbossas">Community Project Information</a></li>

33. </ul>

34. </div>

35. <div id="footer">

36. <p>

37. This project was generated from a Maven archetype from

38. JBoss.<br />

39. </p>

40. </div>

41. </div>

42. </h:body>

43. </html>

Line

number

Note

6 - 10 We have a common element, where we define styles and more.<head>

14 - 51, 56

- 61

This application defines a common sidebar and footer, putting them in the template means we

only have to define them once/

JBoss AS 7.1

JBoss Community Documentation Page of 231 295

52 - 54 The content is inserted here, and defined by views using this template.

That leaves the main page, , in which we place the content unique to the main page:index.xhtml

index.xhtml

02. <ui:composition xmlns="http://www.w3.org/1999/xhtml"

03. xmlns:ui="http://java.sun.com/jsf/facelets"

04. xmlns:f="http://java.sun.com/jsf/core"

05. xmlns:h="http://java.sun.com/jsf/html"

06. template="/WEB-INF/templates/default.xhtml">

07. <ui:define name="content">

08. <h1>Welcome to JBoss!</h1>

09.

10. d

11.

12. <h:form id="reg">

13. <h2>Member Registration</h2>

14. <p>Enforces annotation-based constraints defined on the model class.</p>

15. <h:panelGrid columns="3" columnClasses="titleCell">

16. <h:outputLabel for="name" value="Name:"/>

17. <h:inputText id="name" value="#{newMember.name}" />

18. <h:message for="name" errorClass="invalid"/>

19.

20. <h:outputLabel for="email" value="Email:"/>

21. <h:inputText id="email" value="#{newMember.email}"/>

22. <h:message for="email" errorClass="invalid"/>

23.

24. <h:outputLabel for="phoneNumber" value="Phone #:"/>

25. <h:inputText id="phoneNumber" value="#{newMember.phoneNumber}"/>

26. <h:message for="phoneNumber" errorClass="invalid"/>

27. </h:panelGrid>

28.

29. <p>

30. <h:panelGrid columns="2">

31. <h:commandButton id="register" action="#{memberController.register}"

value="Register" styleClass="register"/>

32. <h:messages styleClass="messages" errorClass="invalid" infoClass="valid"

warnClass="warning"

33. globalOnly="true"/>

34. </h:panelGrid>

35. </p>

36. </h:form>

37. <h2>Members</h2>

38. <h:panelGroup rendered="#{empty members}">

39. <em>No registered members.</em>

40. </h:panelGroup>

41. <h:dataTable var="_member" value="#{members}" rendered="#{not empty members}"

styleClass="simpletablestyle">

42. <h:column>

43. <f:facet name="header">Id</f:facet>

44. #{_member.id}

45. </h:column>

46. <h:column>

47. <f:facet name="header">Name</f:facet>

48. #{_member.name}

JBoss AS 7.1

JBoss Community Documentation Page of 232 295

49. </h:column>

50. <h:column>

51. <f:facet name="header">Email</f:facet>

52. #{_member.email}

53. </h:column>

54. <h:column>

55. <f:facet name="header">Phone #</f:facet>

56. #{_member.phoneNumber}

57. </h:column>

58. <h:column>

59. <f:facet name="header">REST URL</f:facet>

60. <a

href="#{request.contextPath}/rest/members/#{_member.id}">/rest/members/#{_member.id}</a>

61. </h:column>

62. <f:facet name="footer">

63. REST URL for all members: <a

href="#{request.contextPath}/rest/members">/rest/members</a>

64. </f:facet>

65. </h:dataTable>

66. </ui:define>

67. </ui:composition>

Line

number

Note

12 - 48 The JSF form allows us to register new users. There should be one already created when the

application started.

22, 31,

40

The application uses Bean Validation to validate data entry. The error messages from Bean

Validation are automatically attached to the relevant field by JSF, and adding a JSFmessages

component will display them.

53 - 77 This application exposes REST endpoints for each registered member. The application helpfully

displays the URL to the REST endpoint on this page.

Next, let's take a look at the entity, before we look at how the application is wired together:Member

Memberjava

20.

21. import javax.persistence.Column;

22. import javax.persistence.Entity;

23. import javax.persistence.GeneratedValue;

24. import javax.persistence.Id;

25. import javax.persistence.Table;

26. import javax.persistence.UniqueConstraint;

27. import javax.validation.constraints.Digits;

28. import javax.validation.constraints.NotNull;

29. import javax.validation.constraints.Pattern;

30. import javax.validation.constraints.Size;

31. import javax.xml.bind.annotation.XmlRootElement;

32.

33. import org.hibernate.validator.constraints.Email;

34. import org.hibernate.validator.constraints.NotEmpty;

JBoss AS 7.1

JBoss Community Documentation Page of 233 295

35.

36. @Entity

37. @XmlRootElement

38. @Table(uniqueConstraints = @UniqueConstraint(columnNames = "email"))

39. public class Member implements Serializable {

40. /** Default value included to remove warning. Remove or modify at will. **/

41. private static final long serialVersionUID = 1L;

42.

43. @Id

44. @GeneratedValue

45. private Long id;

46.

47. @NotNull

48. @Size(min = 1, max = 25)

49. @Pattern(regexp = "[A-Za-z ]*", message = "must contain only letters and spaces")

50. private String name;

51.

52. @NotNull

53. @NotEmpty

54. @Email

55. private String email;

56.

57. @NotNull

58. @Size(min = 10, max = 12)

59. @Digits(fraction = 0, integer = 12)

60. @Column(name = "phone_number")

61. private String phoneNumber;

62.

63. public Long getId() {

64. return id;

65. }

66.

67. public void setId(Long id) {

68. this.id = id;

69. }

70.

71. public String getName() {

72. return name;

73. }

74.

75. public void setName(String name) {

76. this.name = name;

77. }

78.

79. public String getEmail() {

80. return email;

81. }

82.

83. public void setEmail(String email) {

84. this.email = email;

85. }

86.

87. public String getPhoneNumber() {

88. return phoneNumber;

89. }

90.

91. public void setPhoneNumber(String phoneNumber) {

92. this.phoneNumber = phoneNumber;

JBoss AS 7.1

JBoss Community Documentation Page of 234 295

93. }

94. }

Line

number

Note

20 As usual with JPA, we define that the class is an entity by adding @Entity

21 Members are exposed as a RESTful service using JAX-RS. We can use JAXB to map the object

to XML and to do this we need to add .@XmlRootElement

31 - 33 Bean Validation allows constraints to be defined once (on the entity) and applied everywhere.

Here we constrain the person's name to a certain size and regular expression.

38 Hibernate Validator also offers some extra validations such as .@Email

41 - 43 , and are further examples of constraints.@Digits @NotNull @Size

Next, let's take a look at , which is responsible for building the list of members,MemberListProducer

ordered by name. It uses JPA 2 criteria to do this.

JBoss AS 7.1

JBoss Community Documentation Page of 235 295

MemberListProducer.java

18.

19. import javax.annotation.PostConstruct;

20. import javax.enterprise.context.RequestScoped;

21. import javax.enterprise.event.Observes;

22. import javax.enterprise.event.Reception;

23. import javax.enterprise.inject.Produces;

24. import javax.inject.Inject;

25. import javax.inject.Named;

26. import java.util.List;

27.

28. import org.jboss.as.quickstarts.kitchensink.model.Member;

29.

30. @RequestScoped

31. public class MemberListProducer {

32.

33. @Inject

34. private MemberRepository memberRepository;

35.

36. private List<Member> members;

37.

38. // @Named provides access the return value via the EL variable name "members" in the UI

(e.g.,

39. // Facelets or JSP view)

40. @Produces

41. @Named

42. public List<Member> getMembers() {

43. return members;

44. }

45.

46. public void onMemberListChanged(@Observes(notifyObserver = Reception.IF_EXISTS) final

Member member) {

47. retrieveAllMembersOrderedByName();

48. }

49.

50. @PostConstruct

51. public void retrieveAllMembersOrderedByName() {

52. members = memberRepository.findAllOrderedByName();

53. }

54. }

Line

number

Note

18 This bean is request scoped, meaning that any fields (such as ) will be stored for themembers

entire request.

26 - 30 The list of members is exposed as a producer method, it's also available via EL.

32 - 34 The observer method is notified whenever a member is created, removed, or updated. This

allows us to refresh the list of members whenever they are needed. This is a good approach as

it allows us to cache the list of members, but keep it up to date at the same time.

JBoss AS 7.1

JBoss Community Documentation Page of 236 295

36 - 45 JPA 2's criteria API is used to create a list of members sorted by name. You can try out the type

safe criteria API as well by swapping the criteria statements as described.

Let's now look at , the class that allows us to create new members from the JSFMemberRegistration

page Unable to retrieve the URL:Code Snippet error:

https://github.com/jbossas/quickstart/raw/master/kitchensink/src/main/java/org/jboss/as/quickstarts/kitchensink/controller/MemberRegistration.java

status code: 404.

Line

number

Note

18 This bean requires transactions as it needs to write to the database. Making this an EJB gives

us access to declarative transactions - much simpler than manual transaction control!

21 Stereotypes, such as allow grouping of common functionality. Here we use the built in @Model

stereotype to give us a request scoped, named bean.@Model

26 - 28 Seam Solder, used in this project offers an injectable logger based on JBoss Logging.

47 An event is sent every time a member is updated. This allows other pieces of code (in this

example the member list is refreshed) to react to changes in the member list without any

coupling to this class.

Seam Solder is a swiss army knife for any CDI based application. It offers some basic additions to

the CDI programming model (such as an injectable, type-safe, logger) as well as utilities for

developing CDI extensions. You can read more on the .Solder project page

Now, let's take a look at the class, which provides resources such as the entity manager. CDIResources

recommends using "resource producers", as we do in this example, to alias resources to CDI beans,

allowing for a consistent style throughout our application:

JBoss AS 7.1

JBoss Community Documentation Page of 237 295

Resources.java

19. import java.util.logging.Logger;

20.

21. import javax.enterprise.context.RequestScoped;

22. import javax.enterprise.inject.Produces;

23. import javax.enterprise.inject.spi.InjectionPoint;

24. import javax.faces.context.FacesContext;

25. import javax.persistence.EntityManager;

26. import javax.persistence.PersistenceContext;

27.

28. /**

29. * This class uses CDI to alias Java EE resources, such as the persistence context, to CDI

beans

30. *

31. * <p>

32. * Example injection on a managed bean field:

33. * </p>

34. *

35. * <pre>

36. * &#064;Inject

37. * private EntityManager em;

38. * </pre>

39. */

40. public class Resources {

41. // use @SuppressWarnings to tell IDE to ignore warnings about field not being referenced

directly

42. @SuppressWarnings("unused")

43. @Produces

44. @PersistenceContext

45. private EntityManager em;

46.

47. @Produces

48. public Logger produceLog(InjectionPoint injectionPoint) {

49. return Logger.getLogger(injectionPoint.getMember().getDeclaringClass().getName());

50. }

51.

52. @Produces

53. @RequestScoped

54. public FacesContext produceFacesContext() {

55. return FacesContext.getCurrentInstance();

56. }

57.

58. }

Line

number

Note

21 - 24 We use the "resource producer" pattern, from CDI, to "alias" the old fashioned

injection of the entity manager to a CDI style injection. This allows us@PersistenceContext

to use.

If you want to define your own datasource, take a look at the or at .Getting Started Guide the JBoss AS wiki

JBoss AS 7.1

JBoss Community Documentation Page of 238 295

Before we wrap up our tour of the kitchensink example application, let's take a look at how the JAX-RS

endpoints are created. Firstly, {JaxRSActivator}}, which extends and is annotated with Application

, is the Java EE 6 "no XML" approach to activating JAX-RS.@ApplicationPath

The real work goes in , which produces the endpoint:MemberResourceRESTService

MembeResourceRESTService.java

020. import java.util.HashSet;

021. import java.util.List;

022. import java.util.Map;

023. import java.util.Set;

024. import java.util.logging.Logger;

025.

026. import javax.enterprise.context.RequestScoped;

027. import javax.inject.Inject;

028. import javax.persistence.NoResultException;

029. import javax.validation.ConstraintViolation;

030. import javax.validation.ConstraintViolationException;

031. import javax.validation.ValidationException;

032. import javax.validation.Validator;

033. import javax.ws.rs.Consumes;

034. import javax.ws.rs.GET;

035. import javax.ws.rs.POST;

036. import javax.ws.rs.Path;

037. import javax.ws.rs.PathParam;

038. import javax.ws.rs.Produces;

039. import javax.ws.rs.WebApplicationException;

040. import javax.ws.rs.core.MediaType;

041. import javax.ws.rs.core.Response;

042.

043. import org.jboss.as.quickstarts.kitchensink.data.MemberRepository;

044. import org.jboss.as.quickstarts.kitchensink.model.Member;

045. import org.jboss.as.quickstarts.kitchensink.service.MemberRegistration;

046.

047. /**

048. * JAX-RS Example

049. * <p/>

050. * This class produces a RESTful service to read/write the contents of the members table.

051. */

052. @Path("/members")

053. @RequestScoped

054. public class MemberResourceRESTService {

055. @Inject

056. private Logger log;

057.

058. @Inject

059. private Validator validator;

060.

061. @Inject

062. private MemberRepository repository;

063.

064. @Inject

065. MemberRegistration registration;

066.

067. @GET

JBoss AS 7.1

JBoss Community Documentation Page of 239 295

068. @Produces(MediaType.APPLICATION_JSON)

069. public List<Member> listAllMembers() {

070. return repository.findAllOrderedByName();

071. }

072.

073. @GET

074. @Path("/{id:[0-9][0-9]*}")

075. @Produces(MediaType.APPLICATION_JSON)

076. public Member lookupMemberById(@PathParam("id") long id) {

077. Member member = repository.findById(id);

078. if (member == null) {

079. throw new WebApplicationException(Response.Status.NOT_FOUND);

080. }

081. return member;

082. }

083.

084. /**

085. * Creates a new member from the values provided. Performs validation, and will return

a JAX-RS response with either

086. * 200 ok, or with a map of fields, and related errors.

087. */

088. @POST

089. @Consumes(MediaType.APPLICATION_JSON)

090. @Produces(MediaType.APPLICATION_JSON)

091. public Response createMember(Member member) {

092.

093. Response.ResponseBuilder builder = null;

094.

095. try {

096. //Validates member using bean validation

097. validateMember(member);

098.

099. registration.register(member);

100.

101. //Create an "ok" response

102. builder = Response.ok();

103. } catch (ConstraintViolationException ce) {

104. //Handle bean validation issues

105. builder = createViolationResponse(ce.getConstraintViolations());

106. } catch (ValidationException e) {

107. //Handle the unique constrain violation

108. Map<String, String> responseObj = new HashMap<String, String>();

109. responseObj.put("email", "Email taken");

110. builder = Response.status(Response.Status.CONFLICT).entity(responseObj);

111. } catch (Exception e) {

112. // Handle generic exceptions

113. Map<String, String> responseObj = new HashMap<String, String>();

114. responseObj.put("error", e.getMessage());

115. builder = Response.status(Response.Status.BAD_REQUEST).entity(responseObj);

116. }

117.

118. return builder.build();

119. }

120.

121.

122. /**

123. * <p>Validates the given Member variable and throws validation exceptions based on the

type of error.

JBoss AS 7.1

JBoss Community Documentation Page of 240 295

124. * If the error is standard bean validation errors then it will throw a

ConstraintValidationException

125. * with the set of the constraints violated.</p>

126. * <p>If the error is caused because an existing member with the same email is

registered it throws a regular

127. * validation exception so that it can be interpreted separately.</p>

128. *

129. * @param member Member to be validated

130. * @throws ConstraintViolationException If Bean Validation errors exist

131. * @throws ValidationException If member with the same email already exists

132. */

133. private void validateMember(Member member) throws ConstraintViolationException,

ValidationException {

134. //Create a bean validator and check for issues.

135. Set<ConstraintViolation<Member>> violations = validator.validate(member);

136.

137. if (!violations.isEmpty()) {

138. throw new ConstraintViolationException(new

HashSet<ConstraintViolation<?>>(violations));

139. }

140.

141. //Check the uniqueness of the email address

142. if (emailAlreadyExists(member.getEmail())) {

143. throw new ValidationException("Unique Email Violation");

144. }

145. }

146.

147. /**

148. * Creates a JAX-RS "Bad Request" response including a map of all violation fields, and

their message.

149. * This can then be used by clients to show violations.

150. *

151. * @param violations A set of violations that needs to be reported

152. * @return JAX-RS response containing all violations

153. */

154. private Response.ResponseBuilder createViolationResponse(Set<ConstraintViolation<?>>

violations) {

155. log.fine("Validation completed. violations found: " + violations.size());

156.

157. Map<String, String> responseObj = new HashMap<String, String>();

158.

159. for (ConstraintViolation<?> violation : violations) {

160. responseObj.put(violation.getPropertyPath().toString(),

violation.getMessage());

161. }

162.

163. return Response.status(Response.Status.BAD_REQUEST).entity(responseObj);

164. }

165.

166. /**

167. * Checks if a member with the same email address is already registered. This is the

only way to

168. * easily capture the "@UniqueConstraint(columnNames = "email")" constraint from the

Member class.

169. *

170. * @param email The email to check

171. * @return True if the email already exists, and false otherwise

172. */

JBoss AS 7.1

JBoss Community Documentation Page of 241 295

173. public boolean emailAlreadyExists(String email) {

174. Member member = null;

175. try {

176. member = repository.findByEmail(email);

177. } catch (NoResultException e) {

178. // ignore

179. }

180. return member != null;

181. }

182. }

Line

number

Note

20 The annotation tells JAX-RS that this class provides a REST endpoint mapped to @Path

(concatenating the path from the activator with the path for this endpoint).rest/members

23, 24 JAX-RS endpoints are CDI enabled, and can use CDI-style injection.

26 - 35 The method is called when the raw endpoint is accessed and offers up alistAllMembers()

list of endpoints. Notice that the object is automatically mapped to XML by JAXB.

37 - 42 The method is called when the endpoint is accessed with a member idlookupMemberById()

parameter appended (for example rest/members/1). Again, the object is automatically mapped

to XML by JAXB.

17.4.1 Arquillian

If you've been following along with the Test Driven Development craze of the past few years, you're probably

getting a bit nervous by now, wondering how on earth you are going to test your application. Lucky for you,

the Arquillian project is here to help!

Arquillian provides all the boiler plate for running your test inside JBoss AS, allowing you to concentrate on

testing your application. In order to do that, it utilizes Shrinkwrap, a fluent API for defining packaging, to

create an archive to deploy. We'll go through the testcase, and how you configure Arquillian in just a

moment, but first let's run the test.

Before we start, we need to let Arquillian know the path to our JBoss AS install. Open up

and set the property to the path to your JBoss ASsrc/test/resources/arquillian.xml jbossHome

install:

JBoss AS 7.1

JBoss Community Documentation Page of 242 295

Now, make sure JBoss AS is not running (so that the instance started for running the test does not interfere),

and then run the tests from the command line by typing:

mvn clean test -Parq-jbossas-managed

You should see JBoss AS start up, a deployed, test executed, and then the results displayed totest.war

you on the console:

$ > mvn clean test -Parq-jbossas-managed

[INFO] Scanning for projects...

[INFO]

[INFO] ------------------------------------------------------------------------

[INFO] Building JBoss AS Quickstarts: Kitchensink 7.0.0-SNAPSHOT

[INFO] ------------------------------------------------------------------------

[INFO]

[INFO] --- maven-clean-plugin:2.4.1:clean (default-clean) @ jboss-as-kitchensink ---

[INFO] Deleting /Users/pmuir/workspace/jboss-as-docs/quickstarts/kitchensink/target

[INFO]

[INFO] --- maven-resources-plugin:2.4.3:resources (default-resources) @ jboss-as-kitchensink ---

[INFO] Using 'UTF-8' encoding to copy filtered resources.

[INFO] Copying 2 resources

[INFO]

[INFO] --- maven-compiler-plugin:2.3.1:compile (default-compile) @ jboss-as-kitchensink ---

[INFO] Compiling 6 source files to

/Users/pmuir/workspace/jboss-as-docs/quickstarts/kitchensink/target/classes

[INFO]

[INFO] --- maven-resources-plugin:2.4.3:testResources (default-testResources) @

jboss-as-kitchensink ---

[INFO] Using 'UTF-8' encoding to copy filtered resources.

[INFO] Copying 1 resource

[INFO]

[INFO] --- maven-compiler-plugin:2.3.1:testCompile (default-testCompile) @ jboss-as-kitchensink

---

[INFO] Compiling 1 source file to

/Users/pmuir/workspace/jboss-as-docs/quickstarts/kitchensink/target/test-classes

[INFO]

[INFO] --- maven-surefire-plugin:2.7.2:test (default-test) @ jboss-as-kitchensink ---

[INFO] Surefire report directory:

/Users/pmuir/workspace/jboss-as-docs/quickstarts/kitchensink/target/surefire-reports

-------------------------------------------------------

T E S T S

-------------------------------------------------------

Running org.jboss.as.quickstarts.kitchensink.test.MemberRegistrationTest

Jun 25, 2011 7:17:49 PM

org.jboss.arquillian.container.impl.client.container.ContainerRegistryCreator

getActivatedConfiguration

INFO: Could not read active container configuration: null

log4j:WARN No appenders could be found for logger (org.jboss.remoting).

log4j:WARN Please initialize the log4j system properly.

Jun 25, 2011 7:17:54 PM org.jboss.as.arquillian.container.managed.ManagedDeployableContainer

startInternal

JBoss AS 7.1

JBoss Community Documentation Page of 243 295

INFO: Starting container with: [java, -Djboss.home.dir=/Users/pmuir/development/jboss,

-Dorg.jboss.boot.log.file=/Users/pmuir/development/jboss/standalone/log/boot.log,

-Dlogging.configuration=file:/Users/pmuir/development/jboss/standalone/configuration/logging.properties,

-jar, /Users/pmuir/development/jboss/jboss-modules.jar, -mp,

/Users/pmuir/development/jboss/modules, -logmodule, org.jboss.logmanager, -jaxpmodule,

javax.xml.jaxp-provider, org.jboss.as.standalone, -server-config, standalone.xml]

19:17:55,107 INFO [org.jboss.modules] JBoss Modules version 1.0.0.CR4

19:17:55,329 INFO [org.jboss.msc] JBoss MSC version 1.0.0.CR2

19:17:55,386 INFO [org.jboss.as] JBoss AS 7.0.0.Beta4-SNAPSHOT "(TBD)" starting

19:17:56,159 INFO [org.jboss.as] creating http management service using network interface

(management) port (9990) securePort (-1)

19:17:56,181 INFO [org.jboss.as.logging] Removing bootstrap log handlers

19:17:56,189 INFO [org.jboss.as.naming] (Controller Boot Thread) Activating Naming Subsystem

19:17:56,203 INFO [org.jboss.as.naming] (MSC service thread 1-4) Starting Naming Service

19:17:56,269 INFO [org.jboss.as.security] (Controller Boot Thread) Activating Security

Subsystem

19:17:56,305 INFO [org.jboss.remoting] (MSC service thread 1-1) JBoss Remoting version

3.2.0.Beta2

19:17:56,317 INFO [org.xnio] (MSC service thread 1-1) XNIO Version 3.0.0.Beta3

19:17:56,331 INFO [org.xnio.nio] (MSC service thread 1-1) XNIO NIO Implementation Version

3.0.0.Beta3

19:17:56,522 INFO [org.jboss.as.connector.subsystems.datasources] (Controller Boot Thread)

Deploying JDBC-compliant driver class org.h2.Driver (version 1.2)

19:17:56,572 INFO [org.apache.catalina.core.AprLifecycleListener] (MSC service thread 1-7) The

Apache Tomcat Native library which allows optimal performance in production environments was not

found on the java.library.path:

.:/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java

19:17:56,627 INFO [org.jboss.as.remoting] (MSC service thread 1-3) Listening on /127.0.0.1:9999

19:17:56,641 INFO [org.jboss.as.jmx.JMXConnectorService] (MSC service thread 1-2) Starting

remote JMX connector

19:17:56,705 INFO [org.jboss.as.ee] (Controller Boot Thread) Activating EE subsystem

19:17:56,761 INFO [org.apache.coyote.http11.Http11Protocol] (MSC service thread 1-7) Starting

Coyote HTTP/1.1 on http--127.0.0.1-8080

19:17:56,793 INFO [org.jboss.as.connector] (MSC service thread 1-3) Starting JCA Subsystem

(JBoss IronJacamar 1.0.0.CR2)

19:17:56,837 INFO [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-2)

Bound data source [java:jboss/datasources/ExampleDS]

19:17:57,335 INFO [org.jboss.as.server.deployment] (MSC service thread 1-1) Starting deployment

of "arquillian-service"

19:17:57,348 INFO [org.jboss.as.deployment] (MSC service thread 1-7) Started

FileSystemDeploymentService for directory /Users/pmuir/development/jboss/standalone/deployments

19:17:57,693 INFO [org.jboss.as] (Controller Boot Thread) JBoss AS 7.0.0.Beta4-SNAPSHOT "(TBD)"

started in 2806ms - Started 111 of 138 services (27 services are passive or on-demand)

19:18:00,596 INFO [org.jboss.as.server.deployment] (MSC service thread 1-6) Stopped deployment

arquillian-service in 8ms

19:18:01,394 INFO [org.jboss.as.server.deployment] (pool-2-thread-7) Content added at location

/Users/pmuir/development/jboss/standalone/data/content/0a/9e20b7bc978fd2778b89c7c06e4d3e1f308dfe/content19:18:01,403

INFO [org.jboss.as.server.deployment] (MSC service thread 1-7) Starting deployment of

"arquillian-service"

19:18:01,650 INFO [org.jboss.as.server.deployment] (pool-2-thread-6) Content added at location

/Users/pmuir/development/jboss/standalone/data/content/94/8324ab8f5a693c67fa57b59323304d3947bbf6/content19:18:01,659

INFO [org.jboss.as.server.deployment] (MSC service thread 1-5) Starting deployment of

"test.war"

19:18:01,741 INFO [org.jboss.jpa] (MSC service thread 1-7) read persistence.xml for primary

19:18:01,764 INFO [org.jboss.weld] (MSC service thread 1-3) Processing CDI deployment: test.war

19:18:01,774 INFO

[org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service

thread 1-3) JNDI bindings for session bean named MemberRegistration in deployment unit

JBoss AS 7.1

JBoss Community Documentation Page of 244 295

deployment "test.war" are as follows:

java:global/test/MemberRegistration!org.jboss.as.quickstarts.kitchensink.controller.MemberRegistration

java:app/test/MemberRegistration!org.jboss.as.quickstarts.kitchensink.controller.MemberRegistration

java:module/MemberRegistration!org.jboss.as.quickstarts.kitchensink.controller.MemberRegistration

java:global/test/MemberRegistration

java:app/test/MemberRegistration

java:module/MemberRegistration

19:18:01,908 INFO [org.jboss.weld] (MSC service thread 1-5) Starting Services for CDI

deployment: test.war

19:18:02,131 INFO [org.jboss.weld.Version] (MSC service thread 1-5) WELD-000900 1.1.1 (Final)

19:18:02,169 INFO [org.jboss.weld] (MSC service thread 1-2) Starting weld service

19:18:02,174 INFO [org.jboss.as.arquillian] (MSC service thread 1-3) Arquillian deployment

detected:

ArquillianConfig[service=jboss.arquillian.config."test.war",unit=test.war,tests=[org.jboss.as.quickstarts.kitchensink.test.MemberRegistrationTest]]19:18:02,179

INFO [org.jboss.jpa] (MSC service thread 1-6) starting Persistence Unit Service

'test.war#primary'

19:18:02,322 INFO [org.hibernate.annotations.common.Version] (MSC service thread 1-6) Hibernate

Commons Annotations 3.2.0.Final

19:18:02,328 INFO [org.hibernate.cfg.Environment] (MSC service thread 1-6) HHH00412:Hibernate

[WORKING]

19:18:02,330 INFO [org.hibernate.cfg.Environment] (MSC service thread 1-6)

HHH00206:hibernate.properties not found

19:18:02,332 INFO [org.hibernate.cfg.Environment] (MSC service thread 1-6) HHH00021:Bytecode

provider name : javassist

19:18:02,354 INFO [org.hibernate.ejb.Ejb3Configuration] (MSC service thread 1-6)

HHH00204:Processing PersistenceUnitInfo [

name: primary

...]

19:18:02,400 WARN [org.hibernate.cfg.AnnotationBinder] (MSC service thread 1-6)

HHH00194:Package not found or wo package-info.java: org.jboss.as.quickstarts.kitchensink.test

19:18:02,400 WARN [org.hibernate.cfg.AnnotationBinder] (MSC service thread 1-6)

HHH00194:Package not found or wo package-info.java:

org.jboss.as.quickstarts.kitchensink.controller

19:18:02,401 WARN [org.hibernate.cfg.AnnotationBinder] (MSC service thread 1-6)

HHH00194:Package not found or wo package-info.java: org.jboss.as.quickstarts.kitchensink.util

19:18:02,401 WARN [org.hibernate.cfg.AnnotationBinder] (MSC service thread 1-6)

HHH00194:Package not found or wo package-info.java: org.jboss.as.quickstarts.kitchensink.model

19:18:02,592 INFO [org.hibernate.service.jdbc.connections.internal.ConnectionProviderInitiator]

(MSC service thread 1-6) HHH00130:Instantiating explicit connection provider:

org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider

19:18:02,852 INFO [org.hibernate.dialect.Dialect] (MSC service thread 1-6) HHH00400:Using

dialect: org.hibernate.dialect.H2Dialect

19:18:02,858 WARN [org.hibernate.dialect.H2Dialect] (MSC service thread 1-6) HHH00431:Unable to

determine H2 database version, certain features may not work

19:18:02,862 INFO [org.hibernate.engine.jdbc.internal.LobCreatorBuilder] (MSC service thread

1-6) HHH00423:Disabling contextual LOB creation as JDBC driver reported JDBC version [3] less

than 4

19:18:02,870 INFO [org.hibernate.engine.transaction.internal.TransactionFactoryInitiator] (MSC

service thread 1-6) HHH00268:Transaction strategy:

org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory

19:18:02,874 INFO [org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory] (MSC service

thread 1-6) HHH00397:Using ASTQueryTranslatorFactory

19:18:02,911 INFO [org.hibernate.validator.util.Version] (MSC service thread 1-6) Hibernate

Validator 4.1.0.Final

19:18:02,917 INFO [org.hibernate.validator.engine.resolver.DefaultTraversableResolver] (MSC

service thread 1-6) Instantiated an instance of

JBoss AS 7.1

JBoss Community Documentation Page of 245 295

org.hibernate.validator.engine.resolver.JPATraversableResolver.

19:18:03,079 INFO [org.hibernate.tool.hbm2ddl.SchemaExport] (MSC service thread 1-6)

HHH00227:Running hbm2ddl schema export

19:18:03,093 INFO [org.hibernate.tool.hbm2ddl.SchemaExport] (MSC service thread 1-6)

HHH00230:Schema export complete

19:18:03,217 INFO [org.jboss.web] (MSC service thread 1-5) registering web context: /test

19:18:03,407 WARN [org.jboss.weld.Bean] (RMI TCP Connection(3)-127.0.0.1) WELD-000018 Executing

producer field or method [method] @Produces public

org.jboss.as.quickstarts.kitchensink.test.MemberRegistrationTest.produceLog(InjectionPoint) on

incomplete declaring bean Managed Bean [class

org.jboss.as.quickstarts.kitchensink.test.MemberRegistrationTest] with qualifiers [@Any

@Default] due to circular injection

19:18:03,427 WARN [org.jboss.weld.Bean] (RMI TCP Connection(3)-127.0.0.1) WELD-000018 Executing

producer field or method [method] @Produces public

org.jboss.as.quickstarts.kitchensink.test.MemberRegistrationTest.produceLog(InjectionPoint) on

incomplete declaring bean Managed Bean [class

org.jboss.as.quickstarts.kitchensink.test.MemberRegistrationTest] with qualifiers [@Any

@Default] due to circular injection

19:18:03,450 WARN [org.jboss.as.ejb3.component.EJBComponent] (RMI TCP Connection(3)-127.0.0.1)

EJBTHREE-2120: deprecated getTransactionAttributeType method called (dev problem)

19:18:03,459 INFO [org.jboss.as.quickstarts.kitchensink.controller.MemberRegistration] (RMI TCP

Connection(3)-127.0.0.1) Registering Jane Doe

19:18:03,616 INFO [org.jboss.as.quickstarts.kitchensink.test.MemberRegistrationTest] (RMI TCP

Connection(3)-127.0.0.1) Jane Doe was persisted with id 1

19:18:03,686 INFO [org.jboss.jpa] (MSC service thread 1-1) stopping Persistence Unit Service

'test.war#primary'

19:18:03,687 INFO [org.hibernate.tool.hbm2ddl.SchemaExport] (MSC service thread 1-1)

HHH00227:Running hbm2ddl schema export

19:18:03,690 INFO [org.jboss.weld] (MSC service thread 1-3) Stopping weld service

19:18:03,692 INFO [org.hibernate.tool.hbm2ddl.SchemaExport] (MSC service thread 1-1)

HHH00230:Schema export complete

19:18:03,704 INFO [org.jboss.as.server.deployment] (MSC service thread 1-8) Stopped deployment

test.war in 52ms

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 14.859 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------

[INFO] BUILD SUCCESS

[INFO] ------------------------------------------------------------------------

[INFO] Total time: 22.305s

[INFO] Finished at: Sat Jun 25 19:18:04 BST 2011

[INFO] Final Memory: 17M/125M

[INFO] ------------------------------------------------------------------------

$ >

As you can see, that didn't take too long (approximately 15s), and is great for running in your QA

environment, but if you running locally, you might prefer to connect to a running JBoss AS. To do that, start

up JBoss AS (as described in ). Now, run your test, but use the Getting started with JBoss AS

profile:arq-jbossas-remote

mvn clean test -Parq-jbossas-remote

JBoss AS 7.1

JBoss Community Documentation Page of 246 295

$> mvn clean test -Parq-jbossas-remote

[INFO] Scanning for projects...

[INFO]

[INFO] ------------------------------------------------------------------------

[INFO] Building JBoss AS Quickstarts: Kitchensink 7.0.0-SNAPSHOT

[INFO] ------------------------------------------------------------------------

[INFO]

[INFO] --- maven-clean-plugin:2.4.1:clean (default-clean) @ jboss-as-kitchensink ---

[INFO] Deleting /Users/pmuir/workspace/jboss-as-docs/quickstarts/kitchensink/target

[INFO]

[INFO] --- maven-resources-plugin:2.4.3:resources (default-resources) @ jboss-as-kitchensink ---

[INFO] Using 'UTF-8' encoding to copy filtered resources.

[INFO] Copying 2 resources

[INFO]

[INFO] --- maven-compiler-plugin:2.3.1:compile (default-compile) @ jboss-as-kitchensink ---

[INFO] Compiling 6 source files to

/Users/pmuir/workspace/jboss-as-docs/quickstarts/kitchensink/target/classes

[INFO]

[INFO] --- maven-resources-plugin:2.4.3:testResources (default-testResources) @

jboss-as-kitchensink ---

[INFO] Using 'UTF-8' encoding to copy filtered resources.

[INFO] Copying 1 resource

[INFO]

[INFO] --- maven-compiler-plugin:2.3.1:testCompile (default-testCompile) @ jboss-as-kitchensink

---

[INFO] Compiling 1 source file to

/Users/pmuir/workspace/jboss-as-docs/quickstarts/kitchensink/target/test-classes

[INFO]

[INFO] --- maven-surefire-plugin:2.7.2:test (default-test) @ jboss-as-kitchensink ---

[INFO] Surefire report directory:

/Users/pmuir/workspace/jboss-as-docs/quickstarts/kitchensink/target/surefire-reports

-------------------------------------------------------

T E S T S

-------------------------------------------------------

Running org.jboss.as.quickstarts.kitchensink.test.MemberRegistrationTest

Jun 25, 2011 7:22:28 PM

org.jboss.arquillian.container.impl.client.container.ContainerRegistryCreator

getActivatedConfiguration

INFO: Could not read active container configuration: null

log4j:WARN No appenders could be found for logger

(org.jboss.as.arquillian.container.MBeanServerConnectionProvider).

log4j:WARN Please initialize the log4j system properly.

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 4.13 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------

[INFO] BUILD SUCCESS

[INFO] ------------------------------------------------------------------------

[INFO] Total time: 10.474s

[INFO] Finished at: Sat Jun 25 19:22:33 BST 2011

[INFO] Final Memory: 17M/125M

JBoss AS 7.1

JBoss Community Documentation Page of 247 295

[INFO] ------------------------------------------------------------------------

$ >

Arquillian defines two modes, and . The mode will take care of startingmanaged remote managed

and stopping the server for you, whilst the mode connects to an already running server.remote

This time you can see the test didn't start JBoss AS (if you check the instance you started, you will see the

application was deployed there), and the test ran a lot faster (approximately 4s).

We can also run the test from Eclipse, in both managed and remote modes. First, we'll run in in managed

mode. In order to set up the correct dependencies on your classpath, right click on the project, and select

:Properties

JBoss AS 7.1

JBoss Community Documentation Page of 248 295

Now, locate the Maven panel:

JBoss AS 7.1

JBoss Community Documentation Page of 249 295

And activate the profile:arq-jbossas-managed

JBoss AS 7.1

JBoss Community Documentation Page of 250 295

Finally, hit , and then confirm you want to update the project configuration:Ok

Once the project has built, locate the in , right click on theMemberRegistrationTest src/test/java

test, and choose :Run As -> JUnit Test...

JBoss AS 7.1

JBoss Community Documentation Page of 251 295

You should see JBoss AS start in the Eclipse Console, the test be deployed, and finally the JUnit View pop

up with the result (a pass of course!).

We can also run the test in an already running instance of Eclipse. Simply change the active profile to

:arq-jbossas-remote

JBoss AS 7.1

JBoss Community Documentation Page of 252 295

Now, make sure JBoss AS is running, right click on the test case and choose :Run As -> JUnit Test

JBoss AS 7.1

JBoss Community Documentation Page of 253 295

Again, you'll see the test run in the server, and the JUnit View pop up, with the test passing.

So far so good, the test is running in both Eclipse and from the command line. But what does the test look

like?

JBoss AS 7.1

JBoss Community Documentation Page of 254 295

MemberRegistrationTest.java

23. import javax.inject.Inject;

24.

25. import org.jboss.arquillian.container.test.api.Deployment;

26. import org.jboss.arquillian.junit.Arquillian;

27. import org.jboss.as.quickstarts.kitchensink.model.Member;

28. import org.jboss.as.quickstarts.kitchensink.service.MemberRegistration;

29. import org.jboss.as.quickstarts.kitchensink.util.Resources;

30. import org.jboss.shrinkwrap.api.Archive;

31. import org.jboss.shrinkwrap.api.ShrinkWrap;

32. import org.jboss.shrinkwrap.api.asset.EmptyAsset;

33. import org.jboss.shrinkwrap.api.spec.WebArchive;

34. import org.junit.Test;

35. import org.junit.runner.RunWith;

36.

37. @RunWith(Arquillian.class)

38. public class MemberRegistrationTest {

39. @Deployment

40. public static Archive<?> createTestArchive() {

41. return ShrinkWrap.create(WebArchive.class, "test.war")

42. .addClasses(Member.class, MemberRegistration.class, Resources.class)

43. .addAsResource("META-INF/test-persistence.xml", "META-INF/persistence.xml")

44. .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")

45. // Deploy our test datasource

46. .addAsWebInfResource("test-ds.xml", "test-ds.xml");

47. }

48.

49. @Inject

50. MemberRegistration memberRegistration;

51.

52. @Inject

53. Logger log;

54.

55. @Test

56. public void testRegister() throws Exception {

57. Member newMember = new Member();

58. newMember.setName("Jane Doe");

59. newMember.setEmail("[email protected]");

60. newMember.setPhoneNumber("2125551234");

61. memberRegistration.register(newMember);

62. assertNotNull(newMember.getId());

63. log.info(newMember.getName() + " was persisted with id " + newMember.getId());

64. }

65.

66. }

Line

number

Note

23 tells JUnit to hand control over to Arquillian when executing@RunWith(Arquillian.class)

tests

JBoss AS 7.1

JBoss Community Documentation Page of 255 295

25 The annotation identifies the static method to Arquillian@Deployment createTestArchive

as the one to use to determine which resources and classes to deploy

28 We add just the classes needed for the test, no more

29 We also add as our test is going to use the databasepersistence.xml

30 Of course, we must add to enable CDIbeans.xml

24 - 28 Arquillian allows us to inject beans into the test case

41 - 49 The test method works as you would expect - creates a new member, registers them, and then

verifies that the member was created

As you can see, Arquillian has lived up to the promise - the test case is focused on to test (the what

method) and to test (the method). It's also worth noting that this isn't a simplistic@Deployment how @Test

unit test - this is a fully fledged integration test that uses the database.

Now, let's look at how we configure Arquillian. First of all, let's take a look at in arquillian.xml

.src/test/resources

JBoss AS 7.1

JBoss Community Documentation Page of 256 295

arquillian.xml

02. <!-- JBoss, Home of Professional Open Source Copyright 2012, Red Hat, Inc.

03. and/or its affiliates, and individual contributors by the @authors tag. See

04. the copyright.txt in the distribution for a full listing of individual contributors.

05. Licensed under the Apache License, Version 2.0 (the "License"); you may not

06. use this file except in compliance with the License. You may obtain a copy

07. of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required

08. by applicable law or agreed to in writing, software distributed under the

09. License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS

10. OF ANY KIND, either express or implied. See the License for the specific

11. language governing permissions and limitations under the License. -->

12. <arquillian xmlns="http://jboss.org/schema/arquillian"

13. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

14. xsi:schemaLocation="http://jboss.org/schema/arquillian

15. http://jboss.org/schema/arquillian/arquillian_1_0.xsd">

16.

17. <!-- Uncomment to have test archives exported to the file system for inspection -->

18. <!-- <engine> -->

19. <!-- <property name="deploymentExportPath">target/</property> -->

20. <!-- </engine> -->

21.

22. <!-- Force the use of the Servlet 3.0 protocol with all containers, as it is the most

mature -->

23. <defaultProtocol type="Servlet 3.0" />

24.

25. <!-- Example configuration for a remote JBoss AS 7 instance -->

26. <container qualifier="jboss" default="true">

27. <!-- If you want to use the JBOSS_HOME environment variable, just delete the jbossHome

property -->

28. <configuration>

29. <property name="jbossHome">/path/to/jboss/as</property>

30. </configuration>

31. </container>

32.

33. </arquillian>

Line

number

Note

9 Arquillian deploys the test war to JBoss AS, and doesn't write it to disk. For debugging, it can be

very useful to see exactly what is in your war, so Arquillian allows you to export the war when

the tests runs

13 - 17 Arquillian currently needs configuring to use JMX to connect to JBoss AS

Now, we need to look at how we select between containers in the :pom.xml

JBoss AS 7.1

JBoss Community Documentation Page of 257 295

pom.xml

197. <source>1.6</source>

198. <target>1.6</target>

199. </configuration>

200. </plugin>

201. <plugin>

202. <artifactId>maven-war-plugin</artifactId>

203. <version>2.1.1</version>

204. <configuration>

205. <!-- Java EE 6 doesn't require web.xml, Maven needs to

206. catch up! -->

207. <failOnMissingWebXml>false</failOnMissingWebXml>

208. </configuration>

209. </plugin>

210. <!-- The JBoss AS plugin deploys your war to a local JBoss AS

211. container -->

212. <!-- To use, run: mvn package jboss-as:deploy -->

213. <plugin>

214. <groupId>org.jboss.as.plugins</groupId>

215. <artifactId>jboss-as-maven-plugin</artifactId>

216. <version>7.1.1.Final</version>

217. </plugin>

218. </plugins>

219. </build>

220.

221. <profiles>

222. <profile>

223. <!-- The default profile skips all tests, though you can tune

224. it to run just unit tests based on a custom pattern -->

225. <!-- Seperate profiles are provided for running all tests, including

226. Arquillian tests that execute in the specified container -->

227. <id>default</id>

Line

number

Note

204 The profile needs an id so we can activate from Eclipse or the command line

206 - 211 Arquillian decides which container to use depending on your classpath. Here we define the

managed JBoss AS container.

222 - 217 Arquillian decides which container to use depending on your classpath. Here we define the

remote JBoss AS container.

And that's it! As you can see Arquillian delivers simple and true testing. You can concentrate on writing your

test functionality, and run your tests in the same environment in which you will run your application.

Arquillian also offers other containers, allowing you to run your tests against Weld Embedded

(super fast, but your enterprise services are mocked), GlassFish, and more

JBoss AS 7.1

JBoss Community Documentation Page of 258 295

That concludes our tour of the kitchensink quickstart. If you would like to use this project as a basis for your

own application on JBoss AS, you can of course copy this application sources and modify it.

JBoss AS 7.1

JBoss Community Documentation Page of 259 295

18 Helloworld OSGi quickstartThis quickstart shows you how to create and deploy a simple OSGi Bundle.

What is OSGi?

OSGi is a new feature in JBoss AS 7. It provides standards-based modularity and micro-services

as defined in the OSGi 4.2 Core Specifications. You can deploy OSGi bundles directly into JBoss

AS.

For more information on OSGi and on how to develop OSGi bundles, see the OSGi 4.2 Core

and the .Specification OSGi 4.2 Core Javadoc

More information on the OSGi component in JBoss AS can be found on the JBoss OSGi project

.pages

Switch to the directory and instruct Maven to build and deploy thequickstarts/helloworld-osgi

application:

mvn package jboss-as:deploy

Now, you should see the OSGi subsystem start up, and the bundle deployed and started:

JBoss AS 7.1

JBoss Community Documentation Page of 260 295

If you wish to undeploy the quickstart, or redeploy after making some changes, it's pretty easy:

- deploy any changes to the application to the application servermvn jboss-as:deploy

- undeploy the example from JBoss ASmvn jboss-as:undeploy

18.1 The Helloworld OSGi example in depth

The OSGi Bundle has one Java Source file, the Bundle Activator:

JBoss AS 7.1

JBoss Community Documentation Page of 261 295

Activator.java

01. package org.jboss.as.quickstarts.helloworld.osgi;

02.

03. import org.osgi.framework.BundleActivator;

04. import org.osgi.framework.BundleContext;

05.

06. public class Activator implements BundleActivator {

07. public void start(BundleContext context) throws Exception {

08. System.out.println("Hello AS7 World!!");

09. }

10.

11. public void stop(BundleContext context) throws Exception {

12. System.out.println("Bye AS7 World!!");

13. }

14. }

The bundle activator is very simple, and just prints out a message when the bundle starts and stops -

allowing you to verify that OSGi is working properly.

Now, let's look at the , where we create the bundle:pom.xml

pom.xml

002. <project xmlns="http://maven.apache.org/POM/4.0.0"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

003. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0

004. http://maven.apache.org/maven-v4_0_0.xsd">

005. <modelVersion>4.0.0</modelVersion>

006.

007. <groupId>org.jboss.as.quickstarts</groupId>

008. <artifactId>jboss-as-helloworld-osgi</artifactId>

009. <version>7.0.0-SNAPSHOT</version>

010. <packaging>bundle</packaging>

011. <name>JBoss AS Quickstarts: Helloworld OSGi</name>

012.

013. <url>http://jboss.org/jbossas/osgi</url>

014. <licenses>

015. <license>

016. <name>GNU Lesser General Public License</name>

017. <url>http://www.gnu.org/copyleft/lesser.html</url>

018. <distribution>repo</distribution>

019. </license>

020. </licenses>

021.

022. <properties>

023. <!-- Explicitly declaring the source encoding eliminates the following message: -->

024. <!-- [WARNING] Using platform encoding (UTF-8 actually) to copy filtered

025. resources, i.e. build is platform dependent! -->

026. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

027. </properties>

028.

029. <!-- Include the JBoss Maven repository so we can access JBoss artifacts -->

030. <repositories>

JBoss AS 7.1

JBoss Community Documentation Page of 262 295

031. <repository>

032. <id>jboss-public-repository</id>

033. <name>JBoss Repository</name>

034. <url>https://repository.jboss.org/nexus/content/groups/public

035. </url>

036. <releases>

037. <enabled>true</enabled>

038. </releases>

039. <snapshots>

040. <enabled>false</enabled>

041. </snapshots>

042. </repository>

043. </repositories>

044.

045. <pluginRepositories>

046. <pluginRepository>

047. <id>jboss-public-repository</id>

048. <name>JBoss Repository</name>

049. <url>https://repository.jboss.org/nexus/content/groups/public

050. </url>

051. <releases>

052. <enabled>true</enabled>

053. </releases>

054. <snapshots>

055. <enabled>false</enabled>

056. </snapshots>

057. </pluginRepository>

058. </pluginRepositories>

059.

060. <dependencies>

061. <dependency>

062. <groupId>org.osgi</groupId>

063. <artifactId>org.osgi.core</artifactId>

064. <version>4.2.0</version>

065. <scope>provided</scope>

066. </dependency>

067. </dependencies>

068.

069. <build>

070. <plugins>

071. <plugin>

072. <!-- This plugin takes care of packaging the artifact as an OSGi Bundle -->

073. <groupId>org.apache.felix</groupId>

074. <artifactId>maven-bundle-plugin</artifactId>

075. <version>2.3.4</version>

076. <extensions>true</extensions>

077. <configuration>

078. <instructions>

079. <!-- OSGi Manifest Metadata is specified here -->

080. <!-- The Bundle SymbolicName is the same as the artifact ID -->

081. <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>

082.

083. <!-- Specify the Bundle activator, which is invoked when

084. the Bundle is started -->

085.

<Bundle-Activator>org.jboss.as.quickstarts.helloworld.osgi.Activator</Bundle-Activator>

086.

087. <!-- Automatically compute all the necessary Import-Package statements

JBoss AS 7.1

JBoss Community Documentation Page of 263 295

-->

088. <Import-Package>*</Import-Package>

089.

090. <!-- This bundle does not export any packages -->

091. <Export-Package/>

092.

093. <!-- Packages that are not exported but need to be included

094. need to be listed as Private-Package -->

095.

<Private-Package>org.jboss.as.quickstarts.helloworld.osgi</Private-Package>

096. </instructions>

097. </configuration>

098. </plugin>

099.

100. <!-- JBoss AS plugin to deploy war -->

101. <plugin>

102. <groupId>org.jboss.as.plugins</groupId>

103. <artifactId>jboss-as-maven-plugin</artifactId>

104. <version>7.0.0.Beta5-SNAPSHOT</version>

105. <configuration>

106. <filename>${project.build.finalName}.jar</filename>

107. </configuration>

108. </plugin>

109. </plugins>

110. </build>

111. </project>

Line

numbers

Note

10 The packaging of the maven module is set to . This instructs maven and thebundle

maven-bundle-plugin to create an OSGi bundle.

62 - 67 Since the activator uses an OSGi interface, these are provided through the OSGi interfaces

artifact.

66 Use the scope for dependencies that are either provided by the OSGi frameworkprovided

(i.e. JBoss AS) itself or for dependencies that are provided through separate bundles.

71 - 98 The is used to create a bundle. You can configure it create importmaven-bundle-plugin

and export statements, and to specify the activator in use. You can read more about the OSGi

on the Apache Felix site.Bundle Maven Plugin

100 -

108

We can use the Maven plugin to deploy the bundle to JBoss AS as usual.jboss-as

As you can see, using OSGi with JBoss AS is pretty easy!

18.2 Creating a new OSGi bundle using Eclipse

Eclipse has built-in support for creating OSGi bundles. Eclipse is built on OSGi, therefore support for

developing OSGi bundles inside Eclipse is quite extensive.

JBoss AS 7.1

JBoss Community Documentation Page of 264 295

To quickly create an OSGi Bundle using Eclipse, follow these steps. In Eclipse do File -> New ->

:Project -> Plug-in Project

Select as the Target Platform a 'Standard' OSGi Framework and click .Next >

On the following page, you can specify the Bundle Symbolic Name, version, Bundle Activator and some

other details. You may use the defaults, or, for example, you could put the Activator in a different package,

e.g. .org.jboss.as.quickstarts.helloworld.osgi.Activator

Click again.Next >

On the Templates page select the 'Hello OSGi Bundle' template and click Finish:

JBoss AS 7.1

JBoss Community Documentation Page of 265 295

After clicking , the Plug-In Development perspective will open with the Manifest Editor. The ManifestFinish

Editor facilitates editing of the OSGi Metadata, such as the Imported Packages in the tab andDependencies

Exported Packages on the tab:Runtime

JBoss AS 7.1

JBoss Community Documentation Page of 266 295

Click on the link in the Manifest editor to open the Bundle Activator in the Java editor.Activator

JBoss AS 7.1

JBoss Community Documentation Page of 267 295

When finished making changes you can export your OSGi bundle so that it can be deployed directly into

JBoss AS. Click on :File -> Export -> Deployable plug-ins and fragments

JBoss AS 7.1

JBoss Community Documentation Page of 268 295

You have now created an OSGi Bundle, and the JAR can be found in the directory of the locationplugins

specified in the screen above. You can deploy it to JBoss AS using any of the standard deployment

mechanisms described in the .Getting Started Guide

18.3 The helloworld-osgi example in depth

The OSGi Bundle has one Java Source file, the Bundle Activator:

JBoss AS 7.1

JBoss Community Documentation Page of 269 295

Activator.java

01. package org.jboss.as.quickstarts.helloworld.osgi;

02.

03. import org.osgi.framework.BundleActivator;

04. import org.osgi.framework.BundleContext;

05.

06. public class Activator implements BundleActivator {

07. public void start(BundleContext context) throws Exception {

08. System.out.println("Hello AS7 World!!");

09. }

10.

11. public void stop(BundleContext context) throws Exception {

12. System.out.println("Bye AS7 World!!");

13. }

14. }

The bundle activator is very simple, and just prints out a message when the bundle starts and stops -

allowing you to verify that OSGi is working properly.

Now, let's look at the , where we create the bundle:pom.xml

pom.xml

002. <project xmlns="http://maven.apache.org/POM/4.0.0"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

003. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0

004. http://maven.apache.org/maven-v4_0_0.xsd">

005. <modelVersion>4.0.0</modelVersion>

006.

007. <groupId>org.jboss.as.quickstarts</groupId>

008. <artifactId>jboss-as-helloworld-osgi</artifactId>

009. <version>7.0.0-SNAPSHOT</version>

010. <packaging>bundle</packaging>

011. <name>JBoss AS Quickstarts: Helloworld OSGi</name>

012.

013. <url>http://jboss.org/jbossas/osgi</url>

014. <licenses>

015. <license>

016. <name>GNU Lesser General Public License</name>

017. <url>http://www.gnu.org/copyleft/lesser.html</url>

018. <distribution>repo</distribution>

019. </license>

020. </licenses>

021.

022. <properties>

023. <!-- Explicitly declaring the source encoding eliminates the following message: -->

024. <!-- [WARNING] Using platform encoding (UTF-8 actually) to copy filtered

025. resources, i.e. build is platform dependent! -->

026. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

027. </properties>

028.

029. <!-- Include the JBoss Maven repository so we can access JBoss artifacts -->

030. <repositories>

JBoss AS 7.1

JBoss Community Documentation Page of 270 295

031. <repository>

032. <id>jboss-public-repository</id>

033. <name>JBoss Repository</name>

034. <url>https://repository.jboss.org/nexus/content/groups/public

035. </url>

036. <releases>

037. <enabled>true</enabled>

038. </releases>

039. <snapshots>

040. <enabled>false</enabled>

041. </snapshots>

042. </repository>

043. </repositories>

044.

045. <pluginRepositories>

046. <pluginRepository>

047. <id>jboss-public-repository</id>

048. <name>JBoss Repository</name>

049. <url>https://repository.jboss.org/nexus/content/groups/public

050. </url>

051. <releases>

052. <enabled>true</enabled>

053. </releases>

054. <snapshots>

055. <enabled>false</enabled>

056. </snapshots>

057. </pluginRepository>

058. </pluginRepositories>

059.

060. <dependencies>

061. <dependency>

062. <groupId>org.osgi</groupId>

063. <artifactId>org.osgi.core</artifactId>

064. <version>4.2.0</version>

065. <scope>provided</scope>

066. </dependency>

067. </dependencies>

068.

069. <build>

070. <plugins>

071. <plugin>

072. <!-- This plugin takes care of packaging the artifact as an OSGi Bundle -->

073. <groupId>org.apache.felix</groupId>

074. <artifactId>maven-bundle-plugin</artifactId>

075. <version>2.3.4</version>

076. <extensions>true</extensions>

077. <configuration>

078. <instructions>

079. <!-- OSGi Manifest Metadata is specified here -->

080. <!-- The Bundle SymbolicName is the same as the artifact ID -->

081. <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>

082.

083. <!-- Specify the Bundle activator, which is invoked when

084. the Bundle is started -->

085.

<Bundle-Activator>org.jboss.as.quickstarts.helloworld.osgi.Activator</Bundle-Activator>

086.

087. <!-- Automatically compute all the necessary Import-Package statements

JBoss AS 7.1

JBoss Community Documentation Page of 271 295

-->

088. <Import-Package>*</Import-Package>

089.

090. <!-- This bundle does not export any packages -->

091. <Export-Package/>

092.

093. <!-- Packages that are not exported but need to be included

094. need to be listed as Private-Package -->

095.

<Private-Package>org.jboss.as.quickstarts.helloworld.osgi</Private-Package>

096. </instructions>

097. </configuration>

098. </plugin>

099.

100. <!-- JBoss AS plugin to deploy war -->

101. <plugin>

102. <groupId>org.jboss.as.plugins</groupId>

103. <artifactId>jboss-as-maven-plugin</artifactId>

104. <version>7.0.0.Beta5-SNAPSHOT</version>

105. <configuration>

106. <filename>${project.build.finalName}.jar</filename>

107. </configuration>

108. </plugin>

109. </plugins>

110. </build>

111. </project>

Line

numbers

Note

10 The packaging of the maven module is set to . This instructs maven and thebundle

maven-bundle-plugin to create an OSGi bundle.

62 - 67 Since the activator uses an OSGi interface, these are provided through the OSGi interfaces

artifact.

66 Use the scope for dependencies that are either provided by the OSGi frameworkprovided

(i.e. JBoss AS) itself or for dependencies that are provided through separate bundles.

71 - 98 The is used to create a bundle. You can configure it create importmaven-bundle-plugin

and export statements, and to specify the activator in use. You can read more about the OSGi

on the Apache Felix site.Bundle Maven Plugin

100 -

108

We can use the Maven plugin to deploy the bundle to JBoss AS as usual.jboss-as

As you can see, using OSGi with JBoss AS is pretty easy!

18.4 Creating a new OSGi Bundle using Eclipse

Eclipse has built-in support for creating OSGi bundles. Eclipse is built on OSGi, therefore support for

developing OSGi bundles inside Eclipse is quite extensive.

JBoss AS 7.1

JBoss Community Documentation Page of 272 295

To quickly create an OSGi Bundle using Eclipse, follow these steps. In Eclipse do File -> New ->

:Project -> Plug-in Project

Select as the Target Platform a 'Standard' OSGi Framework and click .Next >

On the following page, you can specify the Bundle Symbolic Name, version, Bundle Activator and some

other details. You may use the defaults, or, for example, you could put the Activator in a different package,

e.g. .org.jboss.as.quickstarts.helloworld.osgi.Activator

Click again.Next >

On the Templates page select the 'Hello OSGi Bundle' template and click Finish:

JBoss AS 7.1

JBoss Community Documentation Page of 273 295

After clicking , the Plug-In Development perspective will open with the Manifest Editor. The ManifestFinish

Editor facilitates editing of the OSGi Metadata, such as the Imported Packages in the tab andDependencies

Exported Packages on the tab:Runtime

JBoss AS 7.1

JBoss Community Documentation Page of 274 295

Click on the link in the Manifest editor to open the Bundle Activator in the Java editor.Activator

JBoss AS 7.1

JBoss Community Documentation Page of 275 295

When finished making changes you can export your OSGi bundle so that it can be deployed directly into

JBoss AS. Click on :File -> Export -> Deployable plug-ins and fragments

JBoss AS 7.1

JBoss Community Documentation Page of 276 295

You have now created an OSGi Bundle, and the JAR can be found in the directory of the locationplugins

specified in the screen above. You can deploy it to JBoss AS using any of the standard deployment

mechanisms described in the .Getting Started Guide

JBoss AS 7.1

JBoss Community Documentation Page of 277 295

19 Creating your own applicationWhat we didn't tell you about the is that it is generated from a Maven archetype. UsingKitchensink quickstart

this archetype offers you the perfect opportunity to generate your own project.

Watch and learn

To use the archetype to generate a new project, you should run:

mvn archetype:generate \

-DarchetypeArtifactId=jboss-javaee6-webapp-archetype \

-DarchetypeGroupId=org.jboss.spec.archetypes \

-DarchetypeVersion=7.0.2.CR2 \

Maven will download the archetype and it's dependencies, and ask you some questions:

JBoss AS 7.1

JBoss Community Documentation Page of 278 295

$> mvn archetype:generate \

-DarchetypeArtifactId=jboss-javaee6-webapp-archetype \

-DarchetypeGroupId=org.jboss.spec.archetypes \

-DarchetypeVersion=7.0.2.CR2 \

[INFO] Scanning for projects...

[INFO]

[INFO] ------------------------------------------------------------------------

[INFO] Building Maven Stub Project (No POM) 1

[INFO] ------------------------------------------------------------------------

[INFO]

.........

Define value for property 'groupId': : com.acme.corp

Define value for property 'artifactId': : acme-sales

Define value for property 'version': 1.0-SNAPSHOT: :

Define value for property 'package': com.acme.corp: :

[INFO] Using property: name = Java EE 6 webapp project

Confirm properties configuration:

groupId: com.acme.corp

artifactId: acme-sales

version: 1.0-SNAPSHOT

package: com.acme.corp

name: Java EE 6 webapp project

Y: :

[WARNING] CP Don't override file

/Users/pmuir/tmp/acme-sales/.settings/org.eclipse.jdt.apt.core.prefs

[INFO] ------------------------------------------------------------------------

[INFO] BUILD SUCCESS

[INFO] ------------------------------------------------------------------------

[INFO] Total time: 14.774s

[INFO] Finished at: Mon Jun 06 18:53:38 BST 2011

[INFO] Final Memory: 7M/125M

[INFO] ------------------------------------------------------------------------

$>

  Instruction

1 Enter the you wish to usegroupId

2 Enter the you wish to useartifactId

3 Enter the version you wish to use, or just hit if you wish to accept the default Enter 1.0-SNAPSHOT

4 Enter the java package you wish to use, or just hit if you wish to accept the default (which isEnter

copied from ).groupId

5 Finally, if you are happy with your choices, hit and Maven will generate the project for you.Enter

And that's it, you now have a brand new project with the same functionality as , butkitchensink

customized with your details.

JBoss AS 7.1

JBoss Community Documentation Page of 279 295

A blank canvas?

The archetype contains some sample code to get you started. If you would prefer a blank canvas,

with only a project skeleton, then use as yourjboss-javaee6-webapp-archetype-blank

archetype id.

Prefer Enterprise Applications (EARs)?

The archetype generates a WAR project. With Java EE 6, you can include EJBs in your WAR,

meaning you won't need an EAR until you need to divide your code into modules. If you would like

to create an EAR based project then use as yourjboss-javaee6-webapp-ear-archetype

archetype id (or if you want a blank EAR, then

).jboss-javaee6-webapp-ear-archetype-blank

Of course, you can create a project from the archetype using Eclipse, saving you the step of importing it.

First, choose :File -> New -> Other

Select the wizard:Maven Project

JBoss AS 7.1

JBoss Community Documentation Page of 280 295

If you wish, customize the project creation, otherwise, just hit :Next >

JBoss AS 7.1

JBoss Community Documentation Page of 281 295

Locate the archetype:jboss-javaee6-webapp-archetype

The image below is out of date, and the archetype id has changed to

jboss-javaee6-webapp-archetype

JBoss AS 7.1

JBoss Community Documentation Page of 282 295

Now hit .Ok

Next, fill in the and , and hit :groupId artifactId Finish

JBoss AS 7.1

JBoss Community Documentation Page of 283 295

You should now have a brand new project:

JBoss AS 7.1

JBoss Community Documentation Page of 284 295

Enjoy!

19.1 Creating your own application using Eclipse

JBoss AS 7.1

JBoss Community Documentation Page of 285 295

20 More Resources

Getting

Started

Guide

The Getting Started Guide covers topics such as server layout (what you can configure

where), data source definition, and using the web management interface.

Torquebox Torque Box allows you to use all the familiar services from JBoss AS 7, but with Ruby.

JBoss AS 7

FAQ

Frequently Asked Questions for JBoss AS 7

20.1 Getting Started Developing Applications

Presentation & Demo

Introduction

Prerequisites for using the script

Import examples into Eclipse and set up JBoss AS

The Helloworld Quickstart

Introduction

Using Maven

Using the Command Line Interface (CLI)

Using the web management interface

Using the filesystem

Using Eclipse

Digging into the app

The numberguess quickstart

Introduction

Run the app

Deployment descriptors src/main/webapp/WEB-INF

Views

Beans

The login quickstart

Introduction

Run the app

Deployment Descriptors

Views

Beans

The kitchensink quickstart

Introduction

Run the app

Bean Validation

JAX-RS

Arquillian

JBoss AS 7.1

JBoss Community Documentation Page of 286 295

1.

20.1.1 Introduction

This document is a “script” for use with the quickstarts associated with the Getting Started Developing

. It can be used as the basis for demoing/explaining the Java EE 6 programming modelApplications Guide

with JBoss AS 7.

There is an associated presentation – JBoss AS - Getting Started Developing Applications – which can be

used to introduce the Java EE 6 ecosystem.

The emphasis here is on the programming model, not on OAM/dev-ops, performance etc.

20.1.2 Prerequisites for using the script

JBoss AS 7 downloaded and installed

Eclipse Indigo with m2eclipse and JBoss Tools installed

The quickstarts downloaded and imported into Eclipse

Make sure is set.$JBOSS_HOME

Make sure has the correct path to your JBoss AS installsrc/test/resources/arquillian.xml

for kitchensink

Make sure your font size is set in Eclipse so everyone can read the text!

20.1.3 Import examples into Eclipse and set up JBoss AS

TODO

20.1.4 The Helloworld Quickstart

IntroductionThis quickstart is extremely basic, and is really useful for nothing more than showing than the app server is

working properly, and our deployment mechanism is working. We recommend you use this quickstart to

demonstrate the various ways you can deploy apps to JBoss AS 7.

Using Maven

Start JBoss AS 7 from the console

$JBOSS_HOME/bin/standalone.sh

JBoss AS 7.1

JBoss Community Documentation Page of 287 295

2.

3.

4.

5.

1.

2.

3.

4.

Deploy the app using Maven

mvn clean package jboss-as:deploy

The quickstarts use the jboss-as maven plugin to deploy and undeploy applications. This

plugin uses the JBoss AS Native Java Detyped Management API to communicate with the

server. The Detyped API is used by management tools to control an entire domain of

servers, and exposes only a small number of types, allowing for backwards and forwards

compatibility.

Show the app has deployed in the terminal

Visit http://localhost:8080/jboss-as-helloworld

Undeploy the app using Maven

mvn jboss-as:undeploy

Using the Command Line Interface (CLI)

Start JBoss AS 7 from the console (if not already running)

$JBOSS_HOME/bin/standalone.sh

Build the war

mvn clean package

Start the CLI

$JBOSS_HOME/bin/jboss-admin.sh --connect

The command line also uses the Deptyped Management API to communicate with the

server. It's designed to be as "unixy" as possible, allowing you to "cd" into nodes, with full

tab completion etc. The CLI allows you to deploy and undeploy applications, create JMS

queues, topics etc., create datasources (normal and XA). It also fully supports the domain

node.

Deploy the app

deploy target/jboss-as-helloworld.war

JBoss AS 7.1

JBoss Community Documentation Page of 288 295

5.

1.

2.

3.

4.

5.

6.

7.

8.

1.

Show the app has deployed

undeploy jboss-as-helloworld.war

Using the web management interface

Start JBoss AS 7 from the console (if not already running)

$JBOSS_HOME/bin/standalone.sh

Build the war

mvn clean package

Open up the web management interface http://localhost:9990/console

The web maangement interface offers the same functionality as the CLI (and again uses the

Detyped Management API), but does so using a pretty GWT interface! You can set up

virtual servers, interrogate sub systems and more.

Navigate . Click on choose file and locate Manage Deployments -> Add content

.helloworld/target/jboss-as-helloworld.war

Click and to upload the war to the server.Next Finish

Now click and to start the applicationEnable Ok

Switch to the console to show it deployed

Now click Remove

Using the filesystem

Start JBoss AS 7 from the console (if not already running)

$JBOSS_HOME/bin/standalone.sh

JBoss AS 7.1

JBoss Community Documentation Page of 289 295

2.

3.

4.

5.

6.

7.

1.

1.

2.

3.

4.

5.

2.

1.

2.

Build the war

mvn clean package

Of course, you can still use the good ol' file system to deploy. Just copy the file to

.$JBOSS_HOME/standalone/deployments

Copy the war

cp target/jboss-as-helloworld.war $JBOSS_HOME/standalone/deployments

Show the war deployed

The filesystem deployment uses marker files to indicate the status of a deployment. As this

deployment succeeded we get a

$JBOSS_HOME/standalone/deployments/jboss-as-helloworld.war.deployed

file. If the deployment failed, you would get a file etc..failed

Undeploy the war

rm $JBOSS_HOME/standalone/deployments/jboss-as-helloworld.war.deployed

Show the deployment stopping!

Start and stop the appserver, show that the deployment really is gone!

This gives you much more precise control over deployments than before

Using Eclipse

Add a JBoss AS server

Bring up the Server view

Right click in it, and choose New -> Server

Choose JBoss AS 7.0 and hit Next

Locate the server on your disc

Hit Finish

Start JBoss AS in Eclipse

Select the server

Click the Run button

JBoss AS 7.1

JBoss Community Documentation Page of 290 295

3.

1.

2.

3.

4.

1.

2.

3.

4.

5.

1.

2.

3.

4.

5.

6.

1.

2.

3.

4.

5.

1.

2.

3.

Deploy the app

right click on the app, choose Run As -> Run On Server

Select the AS 7 instance you want to use

Hit finish

Load the app at http://localhost:8080/jboss-as-helloworld

Digging into the app

Open up the helloworld quickstart in Eclipse, and open up .src/main/webapp

Point out that we don't require a anymore!web.xml

Show and explain it's a marker file used to JBoss AS to enable CDI (open it, show that itbeans.xml

is empty)

Show , and explain it is just used to kick the user into the app (open it, show theindex.html

meta-refresh)

Open up the - and emphasise that it's pretty simple.pom.xm

There is no parent pom, everything for the build is here

Show that we are enabling the JBoss Maven repo - explain you can do this in your POM or in

system wide ( )settings.xml

Show the section. Here we import the JBoss AS 7 Web Profile API.dependencyManagement

Explain that this gives you all the versions for all of the JBoss AS 7 APIs that are in the web

profile. Explain we could also depend on this directly, which would give us the whole set of

APIs, but that here we've decided to go for slightly tighter control and specify each dependency

ourselves

Show the import for CDI, JSR-250 and Servlet API. Show that these are all provided - we are

depending on build in server implementations, not packaging this stuff!

Show the plugin sections - nothing that exciting here, the war plugin is out of date and requires

you to provide , configure the JBoss AS Maven Plugin, set the Java version to 6.web.xml

Open up and open up the .src/main/java HelloWorldServlet

Point out the - explain this one annotation removes about 8 lines of XML - no@WebServlet

need to separately map a path either. This is much more refactor safe

Show that we can inject services into a Servlet

Show that we use the service (line 41)

#Cmd-click on HelloService

This is a CDI bean - very simple, no annotations required!

Explain injection

Probably used to string based bean resolution

This is typesafe (refactor safe, take advantage of the compiler and the IDE - we just saw

that!)

When CDI needs to inject something, the first thing it looks at is the type - and if the type

of the injection point is assignable from a bean, CDI will inject that bean

20.1.5 The numberguess quickstart

JBoss AS 7.1

JBoss Community Documentation Page of 291 295

1.

2.

3.

4.

5.

6.

1.

2.

3.

4.

1.

2.

1.

3.

4.

5.

6.

IntroductionThis quickstart adds in a "complete" view layer into the mix. Java EE ships with a JSF. JSF is a server side

rendering, component orientated framework, where you write markup using an HTML like language, adding

in dynamic behavior by binding components to beans in the back end. The quickstart also makes more use

of CDI to wire the application together.

Run the app

Start JBoss AS in Eclipse

Deploy it using Eclipse - just right click on the app, choose Run As -> Run On Server

Select the AS 7 instance you want to use

Hit finish

Load the app at http://localhost:8080/jboss-as-numberguess

Make a few guesses

Deployment descriptors src/main/webapp/WEB-INFEmphasize the lack of them!

No need to open any of them, just point them out

- don't need it!web.xml

- as before, marker filebeans.xml

- nice feature from AS7 - we can just put into thefaces-config.xml faces-config.xml

WEB-INF and it enables JSF (inspiration from CDI)

we saw this before, this time it's the same but adds in JSF APIpom.xml

Views

- same as before, just kicks us into the appindex.html

home.xhtml

Lines 19 - 25 – these are messages output depending on state of beans (minimise coupling

between controller and view layer by interrogating state, not pushing)

Line 20 – output any messages pushed out by the controller

Line 39 - 42 – the input field is bound to the guess field on the game bean. We validate the input by

calling a method on the game bean.

Line 43 - 45 – the command button is used to submit the form, and calls a method on the game bean

Line 48, 49, The reset button again calls a method on the game bean

Beans

JBoss AS 7.1

JBoss Community Documentation Page of 292 295

1.

1.

2.

3.

4.

1.

2.

5.

2.

3.

1.

2.

1.

2.

3.

4.

5.

6.

7.

– this is the main controller for the game. App has no persistence etc.Game.java

– As we discussed CDI is typesafe, (beans are injected by type) but sometimes need@Named

to access in a non-typesafe fashion. @Named exposes the Bean in EL - and allows us to

access it from JSF

– really simple app, we keep the game data in the session - to play two@SessionScoped

concurrent games, need two sessions. This is not a limitation of CDI, but simply keeps this

demo very simple. CDI will create a bean instance the first time the game bean is accessed,

and then always load that for you

– here we inject the maximum number we can guess. This allows us to@Inject maxNumber

externalize the config of the game

– here we inject the random number we need to guess. Two things@Inject rnadomNumber

to discuss here

Instance - normally we can inject the object itself, but sometimes it's useful to inject a

"provider" of the object (in this case so that we can get a new random number when the

game is reset!). Instance allows us to a new instance when neededget()

Qualifiers - now we have two types of Integer (CDI auto-boxes types when doing

injection) so we need to disambiguate. Explain qualifiers and development time

approach to disambiguation. You will want to open up and here.@MaxNumber @Random

– here is our reset method - we also call it on startup to set up initial values.@PostConstruct

Show use of .Instance.get()

This bean acts as our random number generator.Generator.java

explain about other scopes available in CDI + extensibility.@ApplicationScoped

Explain about producers being useful for determining bean instance at runtimenext()

Explain about producers allowing for loose couplinggetMaxNumber()

20.1.6 The login quickstart

IntroductionThe login quickstart builds on the knowledge of CDI and JSF we have got from numberguess. New stuff we

will learn about is how to use JPA to store data in a database, how to use JTA to control transactions, and

how to use EJB for declarative TX control.

Run the app

Start JBoss AS in Eclipse

Deploy it using Eclipse - just right click on the app, choose Run As -> Run On Server

Select the AS 7 instance you want to use

Hit finish

Load the app at http://localhost:8080/jboss-as-login

Login as admin/admin

Create a new user

JBoss AS 7.1

JBoss Community Documentation Page of 293 295

1.

2.

1.

2.

3.

1.

1.

2.

3.

4.

5.

6.

2.

1.

2.

3.

4.

5.

1.

2.

1.

2.

3.

4.

5.

3.

4.

Deployment Descriptors

Show that we have the same ones we are used in – , src/main/webapp beans.xml

faces-config.xml

We have a couple of new ones in src/main/resources

. Not too exciting. We are using a datasource that AS7 ships with. It'spersistence.xml

backed by the H2 database and is purely a sample datasource to use in sample applications.

We also tell Hibernate to auto-create tables - as you always have.

Again, the same old thing you are used to in Hibernate - auto-import data whenimport.sql

the app starts.

is the same again, but just adds in dependencies for JPA, JTA and EJBpom.xml

Views

One of the updates added to JSF 2.0 was templating ability. We take advantagetemplate.xhtml

of that in this app, as we have multiple views

Actually nothing too major here, we define the app "title" and we could easily define a common

footer etc. (we can see this done in the kitchensink app)

The command inserts the actual content from the templated page.ui:insert

#home.xhtml

Uses the template

Has some input fields for the login form, button to login and logout, link to add users.

Binds fields to credentials bean}}

Buttons link to login bean which is the controller

users.xhtml

Uses the template

Displays all users using a table

Has a form with input fields to add users.

Binds fields to the newUser bean

Methods call on userManager bean

Beans

Backing bean for the login form field, pretty trivial. It's request scoped (naturalCredentials.java

for a login field) and named so we can get it from JSF.

Login.java

Is session scoped (a user is logged in for the length of their session or until they log out}}

Is accessible from EL

Injects the current credentials

Uses the userManager service to load the user, and sends any messages to JSF as needed

Uses a producer method to expose the @LoggedIn user (producer methods used as we don't

know which user at development time)

Is a pretty straightforward JPA entity. Mapped with , has an natural id.User.java @Entity

This is an interface, and by default we use the ManagedBean version, whichUserManager.java

requires manual TX control

JBoss AS 7.1

JBoss Community Documentation Page of 294 295

5.

1.

2.

3.

4.

5.

6.

1.

2.

6.

1.

2.

3.

7.

1.

1.

2.

3.

4.

5.

6.

7.

1.

- accessible from EL, request scoped.ManagedBeanUserManager.java

Injects a logger (we'll see how that is produced in a minute)

Injects the entity manager (again, just a min)

Inject the UserTransaction (this is provided by CDI)

standard JPA-QL that we know and love - but lots of ugly TX handling code.getUsers()

Same for and methods - very simple JPA but...addUser() findUser()

Got a couple of producer methods.

is obvious - loads all the users in the database. No ambiguity - CDI takesgetUsers()

into account generic types when injecting. Also note that CDI names respect JavaBean

naming conventions

is used to bind the new user form to from the view layer - very nice as itgetNewUser()

decreases coupling - we could completely change the wiring on the server side (different

approach to creating the newUser bean) and no need to change the view layer.

EJBUserManager.java

It's an alternative – explain alternatives, and that they allow selection of beans at deployment

time

Much simple now we have declarative TX control.

Start to see how we can introduce EJB to get useful enterprise services such as declarative TX

control

Resources.java

{EntityManager}} - explain resource producer pattern

20.1.7 The kitchensink quickstart

IntroductionThe kitchensink quickstart is generated from an archetype available for JBoss AS (tell people to check the

Guide for details). It demonstrates CDI, JSF, EJB, JPA (which[Getting Started Developing Applications]

we've seen before) and JAX-RS and Bean Validation as well. We add in Arquillian for testing.

Run the app

Start JBoss AS in Eclipse

Deploy it using Eclipse - just right click on the app, choose Run As -> Run On Server

Select the AS 7 instance you want to use

Hit finish

Load the app at http://localhost:8080/jboss-as-kitchensink

Register a member - make sure to enter an invalid email and phone - show bean validation at work

Click on the member URL and show the output from JAX-RS

Bean Validation

Explain the benefits of bean validation - need your data always valid (protect your data) AND good

errors for your user. BV allows you to express once, apply often.

JBoss AS 7.1

JBoss Community Documentation Page of 295 295

2.

1.

2.

3.

1.

4.

1.

2.

3.

4.

1.

2.

3.

5.

1.

2.

1.

3.

4.

5.

6.

7.

1.

8.

1.

2.

3.

index.xhtml

Show the input fields – no validators attached

Show the message output

Member.java

Hightlight the various validation annotations

Java EE automatically applies the validators in both the persistence layer and in your views

RS

- Show that URL generation is just manualindex.xhtml

- simply activates JAX-RSJaxRsActivator.java

- add JAXB annotation to make JAXB process the class properlyMember.java

MemberResourceRESTService.java

sets the JAX-RS resource@Path

JAX-RS services can use injection

methods are auto transformed to XML using JAXB@GET

And that is it!

Arquillian

Make sure JBoss AS is running

mvn clean test -Parq-jbossas-remote

Explain the difference between managed and remote

Make sure JBoss AS is stopped

mvn clean test -Parq-jbossas-managed

Start JBoss AS in Eclipse

Update the project to use the profilearq-jbossas-remote

Run the test from Eclipse

Right click on test, Run As -> JUnit Test

MemberRegistrationTest.java

Discuss micro deployments

Explain Arquilian allows you to use injection

Explain that Arquillian allows you to concentrate just on your test logic