Java EE 8 Cookbook

4.5 (2 reviews total)
By Elder Moraes
    Advance your knowledge in tech with a Packt subscription

  • Instant online access to over 7,500+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. New Features and Improvements

About this book

Java EE is a collection of technologies and APIs to support Enterprise Application development. The choice of what to use and when can be dauntingly complex for any developer. This book will help you master this. Packed with easy to follow recipes, this is your guide to becoming productive with Java EE 8.

You will begin by seeing the latest features of Java EE 8, including major Java EE 8 APIs and specifications such as JSF 2.3, and CDI 2.0, and what they mean for you.

You will use the new features of Java EE 8 to implement web-based services for your client applications. You will then learn to process the Model and Streaming APIs using JSON-P and JSON-B and will learn to use the Java Lambdas support offered in JSON-P. There are more recipes to fine-tune your RESTful development, and you will learn about the Reactive enhancements offered by the JAX-RS 2.1 specification.

Later on, you will learn about the role of multithreading in your enterprise applications and how to integrate them for transaction handling. This is followed by implementing microservices with Java EE and the advancements made by Java EE for cloud computing.

The final set of recipes shows you how take advantage of the latest security features and authenticate your enterprise application.

At the end of the book, the Appendix shows you how knowledge sharing can change your career and your life.

Publication date:
April 2018
Publisher
Packt
Pages
382
ISBN
9781788293037

 

New Features and Improvements

Java EE 8 is a big release, desired and anticipated by the global community for about four years. More than ever before, the whole platform is now even more robust, mature, and stable.

This chapter will cover the main APIs that we can highlight for Java EE 8. Not that they are the only topics covered by this release—far from it—but they have a big role in the enterprise context and are worthy of a careful look inside.

In this chapter, we will cover the following recipes:

  • Running your first Bean Validation 2.0 code
  • Running your first CDI 2.0 code
  • Running your first JAX-RS 2.1 code
  • Running your first JSF 2.3 code
  • Running your first JSON-P 1.1 code
  • Running your first JSON-B 1.0
  • Running your first Servlet 4.0 code
  • Running your first Security API 1.0
  • Running your first MVC 1.0 code
 

Running your first Bean Validation 2.0 code

Bean Validation is a Java specification that basically helps you to protect your data. Through its API, you can validate fields and parameters, express constraints using annotations, and extend your customs' validation rules.

It can be used both with Java SE and Java EE.

In this recipe, you will have a glimpse of Bean Validation 2.0. It doesn't matter whether you are new to it or already using version 1.1; this content will help you get familiar with some of its new features.

Getting ready

First, you need to add the right Bean Validation dependency to your project, as follows:

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.8.Final</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
<version>3.0.1-b10</version>
</dependency>
</dependencies>

How to do it...

  1. First, we need to create an object with some fields to be validated:
public class User {

@NotBlank
private String name;

@Email
private String email;

@NotEmpty
private List<@PositiveOrZero Integer> profileId;

public User(String name, String email, List<Integer> profileId) {
this.name = name;
this.email = email;
this.profileId = profileId;
}
}
  1. Then we create a test class to validate those constraints:
public class UserTest {

private static Validator validator;

@BeforeClass
public static void setUpClass() {
validator = Validation.buildDefaultValidatorFactory()
.getValidator();
}

@Test
public void validUser() {
User user = new User(
"elder",
"[email protected]",
asList(1,2));

Set<ConstraintViolation<User>> cv = validator
.validate(user);
assertTrue(cv.isEmpty());
}

@Test
public void invalidName() {
User user = new User(
"",
"[email protected]",
asList(1,2));

Set<ConstraintViolation<User>> cv = validator
.validate(user);
assertEquals(1, cv.size());
}

@Test
public void invalidEmail() {
User user = new User(
"elder",
"elder-eldermoraes_com",
asList(1,2));

Set<ConstraintViolation<User>> cv = validator
.validate(user);
assertEquals(1, cv.size());
}

@Test
public void invalidId() {
User user = new User(
"elder",
"[email protected]",
asList(-1,-2,1,2));

Set<ConstraintViolation<User>> cv = validator
.validate(user);
assertEquals(2, cv.size());
}
}

How it works...

Our User class uses three of the new constraints introduced by Bean Validation 2.0:

  • @NotBlank: Assures that the value is not null, empty, or an empty string (it trims the value before evaluation, to make sure there aren't spaces).
  • @Email: Allows only a valid email format. Forget those crazy JavaScript functions!
  • @NotEmpty: Ensures that a list has at least one item.
  • @PositiveOrZero: Guarantees that a number is equal or greater than zero.

Then we create a test class (using JUnit) to test our validations. It first instantiates Validator:

@BeforeClass
public static void setUpClass() {
validator = Validation.buildDefaultValidatorFactory().getValidator();
}

Validator is an API that validates beans according to the constraints defined for them.

Our first test method tests a valid user, which is a User object that has:

  • Name not empty
  • Valid email
  • profileId list only with integers greater than zero:
User user = new User(
"elder",
"[email protected]",
asList(1,2));

And finally, the validation:

Set<ConstraintViolation<User>> cv = validator.validate(user);

The validate() method from Validator returns a set of constraint violations found, if any, or an empty set if there are no violations at all.

So, for a valid user it should return an empty set:

assertTrue(cv.isEmpty());

And the other methods work with variations around this model:

  • invalidName(): Uses an empty name
  • invalidEmail(): Uses a malformed email
  • invalidId(): Adds some negative numbers to the list

Note that the invalidId() method adds two negative numbers to the list:

asList(-1,-2,1,2));

So, we expect two constraint violations:

assertEquals(2, cv.size());

In other words, Validator checks not only the constraints violated, but how many times they are violated.

See also

 

Running your first CDI 2.0 code

Context and Dependency Injection (CDI) is certainly one of the most important APIs for the Java EE platform. In version 2.0, it also works with Java SE.

Nowadays, CDI has an impact on many other APIs in the Java EE platform. As said in an interview for Java EE 8 – The Next Frontier project:

"If there was CDI by the time we created JSF, it would be made completely different."
– Ed Burns, JSF Spec Lead

There is a lot of new features in CDI 2.0. This recipe will cover Observer Ordering to give you a quick start.

Getting ready

First, you need to add the right CDI 2.0 dependency to your project. To make things easier at this point, we are going to use CDI SE, the dependency that allows you to use CDI without a Java EE server:

<dependency>
<groupId>org.jboss.weld.se</groupId>
<artifactId>weld-se-shaded</artifactId>
<version>3.0.0.Final</version>
</dependency>

How to do it...

This recipe will show you one of the main features introduced by CDI 2.0: Ordered Observers. Now, you can turn the observers job into something predictable:

  1. First, let's make an event to be observed:
public class MyEvent {

private final String value;

public MyEvent(String value){
this.value = value;
}

public String getValue(){
return value;
}
}
  1. Now, we build our observers and the server that will fire them:
public class OrderedObserver {

public static void main(String[] args){
try(SeContainer container =
SeContainerInitializer.newInstance().initialize()){
container
.getBeanManager()
.fireEvent(new MyEvent("event: " +
System.currentTimeMillis()));
}
}

public void thisEventBefore(
@Observes @Priority(Interceptor.Priority
.APPLICATION - 200)
MyEvent event){

System.out.println("thisEventBefore: " + event.getValue());
}

public void thisEventAfter(
@Observes @Priority(Interceptor.Priority
.APPLICATION + 200)
MyEvent event){

System.out.println("thisEventAfter: " + event.getValue());
}
}

Also, don't forget to add the beans.xml file into the META-INF folder:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
bean-discovery-mode="all">
</beans>
  1. Once you run it, you should see a result like this:
INFO: WELD-ENV-002003: Weld SE container 
353db40d-e670-431d-b7be-4275b1813782 initialized

thisEventBefore: event -> 1501818268764
thisEventAfter: event -> 1501818268764

How it works...

First, we are building a server to manage our event and observers:

public static void main(String[] args){
try(SeContainer container =
SeContainerInitializer.newInstance().initialize()){
container
.getBeanManager()
.fireEvent(new ExampleEvent("event: "
+ System.currentTimeMillis()));
}
}

This will give us all the resources needed to run the recipe as if it was a Java EE server.

Then we build an observer:

public void thisEventBefore(
@Observes @Priority(Interceptor.Priority.APPLICATION - 200)
MyEvent event){

System.out.println("thisEventBefore: " + event.getValue());
}

So, we have three important topics:

  • @Observes: This annotation is used to tell the server that it needs to watch the events fired with MyEvent
  • @Priority: This annotation informs in which priority order this observer needs to run; it receives an int parameter, and the execution order is ascendant
  • MyEvent event: The event being observed

On the thisEventBefore method and thisEventAfter, we only changed the @Priority value and the server took care of running it in the right order.

There's more...

The behavior would be exactly the same in a Java EE 8 server. You just wouldn't need SeContainerInitializer and would need to change the dependencies to the following:

<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>

See also

 

Running your first JAX-RS 2.1 code

JAX-RS is an API designed to give a portable and standard way for building RESTful web services in Java. This is one of the most used technologies for data transporting between different applications that uses some network (internet included) for communication.

One of the coolest features introduced by the 2.1 release is Server-Sent Events (SSE), which will be covered in this recipe. SSE is a specification created by HTML5 where it has established a channel between server and client, one way only from server to client. It is a protocol that transports a message containing some data.

Getting ready

Let's start by adding the right dependency to our project:

    <dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-http</artifactId>
<version>2.26-b09</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>2.26-b09</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-sse</artifactId>
<version>2.26-b09</version>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>
</dependencies>

You surely noticed that we are using Jersey here. Why? Because Jersey is the reference implementation for JAX-RS, which means that all JAX-RS specifications are first implemented through Jersey.

Moreover, with Jersey we can use Grizzly to start a small local server, which will be useful for this recipe, as we need just a few server features to show the SSE behavior.

Further on in this book, we will use a full GlassFish to build more JAX-RS recipes.

How to do it...

  1. First, we create a class that will be our server:
public class ServerMock {

public static final URI CONTEXT =
URI.create("http://localhost:8080/");
public static final String BASE_PATH = "ssevents";

public static void main(String[] args) {
try {
final ResourceConfig resourceConfig = new
ResourceConfig(SseResource.class);

final HttpServer server =
GrizzlyHttpServerFactory.createHttpServer(CONTEXT,
resourceConfig, false);
server.start();

System.out.println(String.format("Mock Server started
at %s%s", CONTEXT, BASE_PATH));

Thread.currentThread().join();
} catch (IOException | InterruptedException ex) {
System.out.println(ex.getMessage());
}
}
}
  1. Then, we create a JAX-RS endpoint to send the events to the clients:
@Path(ServerMock.BASE_PATH)
public class SseResource {

private static volatile SseEventSink SINK = null;

@GET
@Produces(MediaType.SERVER_SENT_EVENTS)
public void getMessageQueue(@Context SseEventSink sink) {
SseResource.SINK = sink;
}

@POST
public void addMessage(final String message, @Context Sse sse)
throws IOException {
if (SINK != null) {
SINK.send(sse.newEventBuilder()
.name("sse-message")
.id(String.valueOf(System.currentTimeMillis()))
.data(String.class, message)
.comment("")
.build());
}
}
}
  1. Then, we create a client class to consume the events generated from the server:
public class ClientConsumer {

public static final Client CLIENT = ClientBuilder.newClient();
public static final WebTarget WEB_TARGET =
CLIENT.target(ServerMock.CONTEXT
+ BASE_PATH);

public static void main(String[] args) {
consume();
}

private static void consume() {

try (final SseEventSource sseSource =
SseEventSource
.target(WEB_TARGET)
.build()) {

sseSource.register(System.out::println);
sseSource.open();

for (int counter=0; counter < 5; counter++) {
System.out.println(" ");
for (int innerCounter=0; innerCounter < 5;
innerCounter++) {
WEB_TARGET.request().post(Entity.json("event "
+ innerCounter));
}
Thread.sleep(1000);
}

CLIENT.close();
System.out.println("\n All messages consumed");
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
}

To try it out, you have to first run the ServerMock class and then the ClientConsumer class. If everything worked well, you should see something like this:

InboundEvent{name='sse-message', id='1502228257736', comment='',    data=event 0}
InboundEvent{name='sse-message', id='1502228257753', comment='', data=event 1}
InboundEvent{name='sse-message', id='1502228257758', comment='', data=event 2}
InboundEvent{name='sse-message', id='1502228257763', comment='', data=event 3}
InboundEvent{name='sse-message', id='1502228257768', comment='', data=event 4}

These are the messages sent from the server to the client.

How it works...

This recipe is made up of three parts:

  • The server, represented by the ServerMock class
  • The SSE engine, represented by the SseResource class
  • The client, represented by the ClientConsumer class

So once ServerMock is instantiated, it registers the SseResource class:

final ResourceConfig resourceConfig = new ResourceConfig(SseResource.class);
final HttpServer server = GrizzlyHttpServerFactory.createHttpServer(CONTEXT, resourceConfig, false);
server.start();

Then two key methods from SseResource take place. The first one adds messages to the server queue:

addMessage(final String message, @Context Sse sse)

The second one consumes this queue and sends the messages to the clients:

@GET
@Produces(MediaType.SERVER_SENT_EVENTS)
public void getMessageQueue(@Context SseEventSink sink)

Note that this one has a media type SERVER_SENT_EVENTS, introduced in this version for this very purpose. And finally, we have our client. In this recipe, it is both posting and consuming messages.

It consumes here:

sseSource.register(System.out::println);
sseSource.open();

It posts here:

ServerMock.WEB_TARGET.request().post(Entity.json("event " + innerCounter));

See also

 

Running your first JSF 2.3 code

JavaServer Faces (JSF) is the Java technology made to simplify the process of building a UIs, despite how it's made for the frontend and the UI is built in the backend.

With JSF, you can build components and use (or reuse) them in the UI in an extensible way. You can also use other powerful APIs, such as CDI and Bean Validation, to improve your application and its architecture.

In this recipe, we will use the Validator and Converter interfaces with the new feature introduced by version 2.3, which is the possibility of using them with generic parameters.

Getting ready

First, we need to add the dependencies needed:

        <dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>

How to do it...

  1. Let's create a User class as the main object of our recipe:
public class User implements Serializable {

private String name;
private String email;

public User(String name, String email) {
this.name = name;
this.email = email;
}

//DON'T FORGET THE GETTERS AND SETTERS
//THIS RECIPE WON'T WORK WITHOUT THEM
}
  1. Now, we create a UserBean class to manage our UI:
@Named
@ViewScoped
public class UserBean implements Serializable {

private User user;

public UserBean(){
user = new User("Elder Moraes", "[email protected]");
}

public void userAction(){
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage("Name|Password welformed"));
}

//DON'T FORGET THE GETTERS AND SETTERS
//THIS RECIPE WON'T WORK WITHOUT THEM
}
  1. Now, we implement the Converter interface with a User parameter:
@FacesConverter("userConverter")
public class UserConverter implements Converter<User> {

@Override
public String getAsString(FacesContext fc, UIComponent uic,
User user) {
return user.getName() + "|" + user.getEmail();
}

@Override
public User getAsObject(FacesContext fc, UIComponent uic,
String string) {
return new User(string.substring(0, string.indexOf("|")),
string.substring(string.indexOf("|") + 1));
}

}
  1. Now, we implement the Validator interface with a User parameter:
@FacesValidator("userValidator")
public class UserValidator implements Validator<User> {

@Override
public void validate(FacesContext fc, UIComponent uic,
User user)
throws ValidatorException {
if(!user.getEmail().contains("@")){
throw new ValidatorException(new FacesMessage(null,
"Malformed e-mail"));
}
}
}
  1. And then we create our UI using all of them:
<h:body>
<h:form>
<h:panelGrid columns="3">
<h:outputLabel value="Name|E-mail:"
for="userNameEmail"/>
<h:inputText id="userNameEmail"
value="#{userBean.user}"
converter="userConverter" validator="userValidator"/>
<h:message for="userNameEmail"/>
</h:panelGrid>
<h:commandButton value="Validate"
action="#{userBean.userAction()}"/>
</h:form>
</h:body>

Don't forget to run it in a Java EE 8 server.

How it works...

The UserBean class manages the communication between the UI and the server. Once you instantiate the user object, it is available for both of them.

That's why when you run it, the Name | E-mail is already filled (the user object is instantiated when the UserBean class is created by the server).

We associated the userAction() method from the UserBean class to the Validate button of the UI:

<h:commandButton value="Validate" action="#{userBean.userAction()}"/>

You can create other methods in UserBean and do the same to empower your application.

The whole core of our recipe is represented by just a single line in the UI:

<h:inputText id="userNameEmail" value="#{userBean.user}" converter="userConverter" validator="userValidator"/>

So, our two implemented interfaces used here are userConverter and userValidator.

Basically, the UserConverter class (with getAsString and getAsObject methods) converts an object to/from a string and vice versa, according to the logic defined by you.

We have just mentioned it in the preceding code snippet:

value="#{userBean.user}"

The server uses the userConverter object, calls the getAsString method, and prints the result using the preceding expression language.

Finally, the UserValidator class is automatically called when you submit the form, by calling its validate method, and applying the rules defined by you.

There's more...

You could increase the validators by adding a Bean Validation on it and, for example, defining the email property from User with an @Email constraint.

See also

 

Running your first JSON-P 1.1 code

JSON-Pointer is the Java API for JSON processing. By processing, we mean generating, transforming, parsing, and querying JSON strings and/or objects.

In this recipe, you will learn how to use JSON Pointer to get a specific value from a JSON message in a very easy way.

Getting ready

Let's get our dependency:

<dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>
</dependency>

How to do it...

  1. First, we define a JSON message to represent a User object:
{
"user": {
"email": "[email protected]",
"name": "Elder",
"profile": [
{
"id": 1
},
{
"id": 2
},
{
"id": 3
}
]
}
}
  1. Now, we create a method to read it and print the values we want:
public class JPointer {

public static void main(String[] args) throws IOException{
try (InputStream is =
JPointer.class.getClassLoader().getResourceAsStream("user.json");
JsonReader jr = Json.createReader(is)) {

JsonStructure js = jr.read();
JsonPointer jp = Json.createPointer("/user/profile");
JsonValue jv = jp.getValue(js);
System.out.println("profile: " + jv);
}
}
}

The execution of this code prints the following:

profile: [{"id":1},{"id":2},{"id":3}]

How it works...

The JSON Pointer is a standard defined by the Internet Engineering Task Force (IETF) under Request for Comments (RFC) 6901. The standard basically says that a JSON Pointer is a string that identifies a specific value in a JSON document.

Without a JSON Pointer, you would need to parse the whole message and iterate through it until you find the desired value; probably lots of ifs, elses, and things like that.

So, JSON Pointer helps you to decrease the written code dramatically by doing this kind of operation in a very elegant way.

See also

 

Running your first JSON-B code

JSON-B is an API for converting Java objects to/from JSON messages in a standardized way. It defines a default mapping algorithm to convert Java classes to JSON and still lets you customize your own algorithms.

With JSON-B, Java EE now has a complete set of tools to work with JSON, such as JSON API, and JSON-P. No third-party frameworks are needed anymore (although you are still free to use them).

This quick recipe will show you how to use JSON-B to convert a Java object to and from a JSON message.

Getting ready

Let's add our dependencies to the project:

    <dependencies>
<dependency>
<groupId>org.eclipse</groupId>
<artifactId>yasson</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.1</version>
</dependency>
</dependencies>

How to do it...

  1. Let's create a User class as a model for our JSON message:
public class User {

private String name;
private String email;

public User(){
}

public User(String name, String email) {
this.name = name;
this.email = email;
}

@Override
public String toString() {
return "User{" + "name=" + name + ", email=" + email + '}';
}

//DON'T FORGET THE GETTERS AND SETTERS
//THIS RECIPE WON'T WORK WITHOUT THEM

}
  1. Then, let's create a class to use JSON-B to transform an object:
public class JsonBUser {

public static void main(String[] args) throws Exception {
User user = new User("Elder", "[email protected]");

Jsonb jb = JsonbBuilder.create();
String jsonUser = jb.toJson(user);
User u = jb.fromJson(jsonUser, User.class);

jb.close();
System.out.println("json: " + jsonUser);
System.out.println("user: " + u);

}
}

The result printed is:

json: {"email":"[email protected]","name":"Elder"}
user: User{name=Elder, [email protected]}

The first line is the object transformed into a JSON string. The second is the same string converted into an object.

How it works...

It uses the getters and setters defined in the User class to transform both ways and that's why they are so important.

See also

 

Running your first Servlet 4.0 code

Servlet 4.0 is one the of biggest APIs of Java EE 8. Since the very beginning of the Java EE platform (the old J2EE), the Servlet specification has always played a key role.

The coolest additions of this version are surely HTTP/2.0 and Server Push. Both of them bring performance improvements to your application.

This recipe will use Server Push to do one of the most basic tasks in a web page—loading an image.

Getting ready

Let's add the dependencies that we need:

<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>

How to do it...

  1. We will create a servlet:
@WebServlet(name = "ServerPush", urlPatterns = {"/ServerPush"})
public class ServerPush extends HttpServlet {

@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse
response) throws ServletException, IOException {

PushBuilder pb = request.newPushBuilder();
if (pb != null) {
pb.path("images/javaee-logo.png")
.addHeader("content-type", "image/png")
.push();
}

try (PrintWriter writer = response.getWriter();) {
StringBuilder html = new StringBuilder();
html.append("<html>");
html.append("<center>");
html.append("<img src='images/javaee-logo.png'><br>");
html.append("<h2>Image pushed by ServerPush</h2>");
html.append("</center>");
html.append("</html>");
writer.write(html.toString());
}
}
}
  1. To try it, run the project in a Java EE 8 server and open this URL:
https://localhost:8080/ch01-servlet/ServerPush

How it works...

We use the PushBuilder object to send an image to the client before it is requested by the img src tag. In other words, the browser doesn't need to do another request (what it usually does with img src) to have an image available for rendering.

It might seem as if it doesn't make too much difference for a single image, but it would with dozens, hundreds, or thousands of images. Less traffic for your client and from your server. Better performance for all!

There's more...

If you are using JSF, you can get the benefits from Server Push for free! You don't even need to rewrite a single line of your code, as JSF relies on the Server Push specification.

Just make sure that you run it under the HTTPS protocol, as HTTP/2.0 only works under it.

See also

 

Running your first Security API code

Security is one of the top concerns when you build an enterprise application. Luckily, the Java EE platform now has this API that handles many of the enterprise requirements in a standardized way.

In this recipe, you will learn how to define roles and give them the right authorization based on rules defined in the methods that manage sensitive data.

Getting ready

We start by adding our dependencies to the project:

        <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.tomee</groupId>
<artifactId>openejb-core</artifactId>
<version>7.0.4</version>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>

How to do it...

  1. We first create a User entity:
@Entity 
public class User implements Serializable{

@Id
private Long id;
private String name;
private String email;

public User(){
}

public User(Long id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
}

//DON'T FORGET THE GETTERS AND SETTERS
//THIS RECIPE WON'T WORK WITHOUT THEM
}
  1. Here, we create a class to store our security roles:
public class Roles {
public static final String ADMIN = "ADMIN";
public static final String OPERATOR = "OPERATOR";
}
  1. Then, we create a stateful bean to manage our user operations:
@Stateful
public class UserBean {

@PersistenceContext(unitName = "ch01-security-pu",
type = PersistenceContextType.EXTENDED)
private EntityManager em;

@RolesAllowed({Roles.ADMIN, Roles.OPERATOR})
public void add(User user){
em.persist(user);
}

@RolesAllowed({Roles.ADMIN})
public void remove(User user){
em.remove(user);
}

@RolesAllowed({Roles.ADMIN})
public void update(User user){
em.merge(user);
}

@PermitAll
public List<User> get(){
Query q = em.createQuery("SELECT u FROM User as u ");
return q.getResultList();
}
  1. Now, we need to create an executor for each role:
public class RoleExecutor {

public interface Executable {
void execute() throws Exception;
}

@Stateless
@RunAs(Roles.ADMIN)
public static class AdminExecutor {
public void run(Executable executable) throws Exception {
executable.execute();
}
}

@Stateless
@RunAs(Roles.OPERATOR)
public static class OperatorExecutor {
public void run(Executable executable) throws Exception {
executable.execute();
}
}
}
  1. And finally, we create a test class to try our security rules.

Our code uses three test methods: asAdmin(), asOperator(), and asAnonymous().

  1. First, it tests asAdmin():
    //Lot of setup code before this point

@Test
public void asAdmin() throws Exception {
adminExecutor.run(() -> {
userBean.add(new User(1L, "user1", "[email protected]"));
userBean.add(new User(2L, "user2", "[email protected]"));
userBean.add(new User(3L, "user3", "[email protected]"));
userBean.add(new User(4L, "user4", "[email protected]"));

List<User> list = userBean.get();

list.forEach((user) -> {
userBean.remove(user);
});

Assert.assertEquals("userBean.get()", 0,
userBean.get().size());
});
}
  1. Then it tests asOperator():
    @Test
public void asOperator() throws Exception {

operatorExecutor.run(() -> {
userBean.add(new User(1L, "user1", "[email protected]"));
userBean.add(new User(2L, "user2", "[email protected]"));
userBean.add(new User(3L, "user3", "[email protected]"));
userBean.add(new User(4L, "user4", "[email protected]"));

List<User> list = userBean.get();

list.forEach((user) -> {
try {
userBean.remove(user);
Assert.fail("Operator was able to remove user " +
user.getName());
} catch (EJBAccessException e) {
}
});
Assert.assertEquals("userBean.get()", 4,
userBean.get().size());
});
}
  1. And, finally it tests asAnonymous():
    @Test
public void asAnonymous() {

try {
userBean.add(new User(1L, "elder",
"[email protected]"));
Assert.fail("Anonymous user should not add users");
} catch (EJBAccessException e) {
}

try {
userBean.remove(new User(1L, "elder",
"[email protected]"));
Assert.fail("Anonymous user should not remove users");
} catch (EJBAccessException e) {
}

try {
userBean.get();
} catch (EJBAccessException e) {
Assert.fail("Everyone can list users");
}
}
This class is huge! For the full source code, check the link at the end of the recipe.

How it works...

The whole point in this recipe is to do with the @RolesAllowed, @RunsAs, and @PermitAll annotations. They define what operations each role can do and what happens when a user tries an operation using the wrong role.

There's more...

What we did here is called programmatic security; that is, we defined the security rules and roles through our code (the program). There's another approach called declarative security, where you declare the rules and roles through application and server configurations.

One good step up for this recipe is if you evolve the roles management to a source outside the application, such as a database or a service.

See also

 

Running your first MVC 1.0 code

If you are following the news about Java EE 8, you may now be wondering: why is MVC 1.0 here if it was dropped from the Java EE 8 umbrella?

Yes, it is true. MVC 1.0 doesn't belong (anymore) to the Java EE 8 release. But it didn't reduce the importance of this great API and I'm sure it will change the way some other APIs work in future releases (for example, JSF).

So why not cover it here? You will use it anyway.

This recipe will show you how to use a Controller (the C) to inject a Model (the M) into the View (the V). It also brings some CDI and JAX-RS to the party.

Getting ready

Add the proper dependencies to your project:

        <dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.mvc</groupId>
<artifactId>javax.mvc-api</artifactId>
<version>1.0-pr</version>
</dependency>

How to do it...

  1. Start by creating a root for your JAX-RS endpoints:
@ApplicationPath("webresources")
public class AppConfig extends Application{
}
  1. Create a User class (this will be your MODEL):
public class User {

private String name;
private String email;

public User(String name, String email) {
this.name = name;
this.email = email;
}

//DON'T FORGET THE GETTERS AND SETTERS
//THIS RECIPE WON'T WORK WITHOUT THEM
}
  1. Now, create a Session Bean, which will be injected later in your Controller:
@Stateless
public class UserBean {

public User getUser(){
return new User("Elder", "[email protected]");
}
}
  1. Then, create the Controller:
@Controller
@Path("userController")
public class UserController {

@Inject
Models models;

@Inject
UserBean userBean;

@GET
public String user(){
models.put("user", userBean.getUser());
return "/user.jsp";
}
}
  1. And finally, the web page (the View):
<head>
<meta http-equiv="Content-Type" content="text/html;
charset=UTF-8">
<title>User MVC</title>
</head>
<body>
<h1>${user.name}/${user.email}</h1>
</body>

Run it on a Java EE 8 server and access this URL:

http://localhost:8080/ch01-mvc/webresources/userController

How it works...

The main actor in this whole scenario is the Models class injected into the Controller:

@Inject
Models models;

It's a class from MVC 1.0 API that owns the responsibility, in this recipe, of letting the User object be available for the View layer. It's injected (using CDI) and uses another injected bean, userBean, to do it:

models.put("user", userBean.getUser());

So, the View can easily access the values from the User object using expression language:

<h1>${user.name}/${user.email}</h1>

See also

About the Author

  • Elder Moraes

    Elder Moraes helps Jakarta EE developers build and deliver secure, fast, and available applications so that they are able to work on great projects. He is passionate about content sharing; he does it by speaking at international events, blogging, and writing articles.

    He has been working with Java since 2002 and has developed applications for different industries. As a board member at SouJava, he led the Java EE 8 - The Next Frontier initiative, interviewing some world-class Java EE experts

    Browse publications by this author

Latest Reviews

(2 reviews total)
Καλό βιβλίο, σε καλή τιμή.
Good overview on Java EE 8 fatures and APIs.
Java EE 8 Cookbook
Unlock this book and the full library for FREE
Start free trial