Technical Article
Introducing the Java EE 6 Platform: Part 1
By Ed Ort, December 2009
Published July 2000
Java Platform, Enterprise Edition (Java EE) is the industry-standard platform for building enterprise-class applications coded in the Java programming language. Based on the solid foundation of Java Platform, Standard Edition (Java SE), Java EE adds libraries and system services that support the scalability, accessibility, security, integrity, and other requirements of enterprise-class applications.
Since its initial release in 1999, Java EE has matured into a functionally rich, high performance platform. Recent releases of the platform have also stressed simplicity and ease of use. In fact, with the current release of the platform, Java EE 5, development of Java enterprise applications has never been easier or faster.
Java EE 6 adds significant new technologies and extends the usability improvements made in previous Java EE releases.
Progress continues. The next release of the platform, Java EE 6, adds significant new technologies, some of which have been inspired by the vibrant Java EE community. It also further simplifies the platform, extending the usability improvements made in previous Java EE releases.
This article highlights some of the significant enhancements in Java EE 6.
Java EE 6 Goals
Here are the main goals for the Java EE 6 platform:
More Flexible Technology Stack. Over time, the Java EE platform has gotten big, in some cases too big for certain types of applications. To remedy this, Java EE 6 introduces the concept of profiles, configurations of the Java EE platform that are designed for specific classes of applications. A profile may include a subset of Java EE platform technologies, additional technologies that have gone through the Java Community Process, but are not part of the Java EE platform, or both. Java EE 6 introduces the first of these profiles, the Web Profile, a subset of the Java EE platform designed for web application development. The Web Profile includes only those technologies needed by most web application developers, and does not include the enterprise technologies that these developers typically don't need.
In addition, the Java EE 6 platform has identified a number of technologies as candidates for pruning. These candidates include technologies that have been superseded by newer technologies or technologies that are not widely deployed. Pruning a technology means that it can become an optional component in the next release of the platform rather than a required component.
Java EE 6 introduces the Web Profile, a subset of the Java EE platform designed for web application development. |
Enhanced Extensibility. Over time, new technologies become available that are of interest to web or enterprise application developers. Rather than adding these technologies to the platform — and growing the platform without bounds — Java EE 6 includes more extensibility points and more service provider interfaces than ever before. This allows you to plug in technologies — even frameworks — in your Java EE 6 implementations in a standard way. Once plugged in, these technologies are just as easy to use as the facilities that are built into the Java EE 6 platform.
More extensibility points and service provider interfaces as well as web tier features such as support for self-registration makes the platform highly extensible. |
Particular emphasis on extensibility has been placed on the web tier. Web application developers often use third-party frameworks in their applications. However, registering these frameworks so that they can be used in Java EE web applications can be complicated, often requiring developers to add to or edit large and complex XML deployment descriptor files. Java EE 6 enables these frameworks to self-register, making it easy to incorporate and configure them in an application.
Further Ease of Development. Java EE 5 made it significantly easier to develop web and enterprise applications. For instance, Java EE 5 introduced a simpler enterprise application programming model based on Plain Old Java Objects (POJOs) and annotations, and eliminated the need for XML deployment descriptors. In addition, Enterprise JavaBeans (EJB) technology was streamlined, requiring fewer classes and interfaces and offering a simpler approach to object-relational mapping by taking advantage of the Java Persistence API (informally referred to as JPA).
Usability improvements in many areas of the platform makes it even easier to develop web and enterprise applications. |
Java EE 6 makes it even easier to develop enterprise or web applications. Usability improvements have been made in many areas of the platform. For example, you can use annotations to define web components such as servlets and servlet filters. Furthermore, a set of annotations for dependency injection has been standardized, making injectable classes much more portable across frameworks. In addition, Java EE application packaging requirements have been simplified. For example, you can add an enterprise bean directly to a web archive (WAR) file. You no longer need to package an enterprise bean in a Java archive (JAR) file and then put the JAR file in an enterprise archive (EAR) file.
Powerful New Technologies
Java EE 6 adds significant new technologies that make the platform even more powerful. Three of these are described below:
- Java API for RESTful Web Services (JAX-RS)
- Contexts and Dependency Injection for the Java EE Platform (CDI)
- Bean Validation
Java API for RESTful Web Services (JAX-RS)
Java API for RESTful Web Services (JAX-RS), JSR 311 enables you to rapidly build lightweight web services that conform to the Representational State Transfer (REST) style of software architecture. An important concept in REST is the existence of resources, each of which can be referred to with a global identifier, that is, a URI. In particular, data and functionality are considered resources that can be identified and accessed through URIs. To manipulate these resources, components of the network, clients and servers, communicate through a standardized interface such as HTTP and a small, fixed set of verbs — GET
, PUT
, POST
, and DELETE
— and exchange representations of these resources.
RESTful web services are web services built according to the REST architectural style. Building web services with the RESTful approach has emerged as a popular alternative to using SOAP-based technologies thanks to REST's lightweight nature and the ability to transmit data directly over HTTP.
JAX-RS makes it simple to create RESTful web services in Java. |
JAX-RS furnishes a standardized API for building RESTful web services in Java. The API contributes a set of annotations and associated classes and interfaces. Applying the annotations to POJOs enables you to expose web resources. This approach makes it simple to create RESTful web services in Java.
The specification for the initial release of the technology, JAX-RS 1.0, was finalized in October 2008 and a reference implementation named Jersey is also available. Java EE 6 includes the latest release of the technology, JAX-RS 1.1, which is a maintenance release that aligns JAX-RS with new features in Java EE 6.
Let's take a look at a RESTful web service that uses JAX-RS.
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.Get;
import javax.ws.rs.Post;
import javax.ws.rs.Consumes;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core UriInfo;
import javax.ws.rs.core.UriBuilder;
import java.net.URI;
@Path ("items")
@Produces (MediaType.APPLICATION_XML)
Public class ItemsResource {
@Context UriInfo uriInfo;
@GET
Items listItems() {
Return Allitems();
}
@POST
@Consumes (MediaType.APPLICATION_XML)
Public Response create(Item item) throws ItemCreationException {
Item newItem = createItem(item);
URI newItemURI = uriInfo.getRequestUriBuilder().path(newItem.getId()).build();
return Response.created(newItemURI).build();
}
...
}
In this example, the ItemsResource
class is a web service that manages a set of items. The imports in the class are for JAX-RS 1.1 annotations, classes, and interfaces.
Annotations add much of the information needed to identify resources and serve HTTP requests. |
The @Path
annotation specifies a relative path for the resource, in this case "items"
. The URI for the class resource is based on the application context. So if the application context for this example is http://example.com
, the URI for the class resource is http://example.com/items
. This means that if a client directs a request to the URI http://example.com/items
, the ItemsResource
class will serve it.
The @GET
annotation specifies that the annotated method, here the listItems()
method, handles HTTP GET
requests. When a client directs an HTTP GET
request to the URI for the ItemsResource
resource, the JAX-RS runtime invokes the listItems()
method to handle the GET
request.
Notice the @Produces
annotation. It specifies the MIME media types that the methods in the resource can produce and return to the client. In the ItemsResource
example, the @Produces
annotation specifies MediaType.APPLICATION_XML
. The MediaType
class is an abstraction of a MIME media type. Constants supplied to the class identify the particular media type to be abstracted. The MediaType.APPLICATION_XML
specification is an abstraction of the MIME media type for XML content, "application/xml".
JAX-RS automatically translates between Java types and MIME media types. |
Annotations such as @Produces
suggest some of the content type translation that JAX-RS handles automatically. For example, the listItems()
method returns a Java object of type Items
. JAX-RS automatically translates that Java type to the "application/xml" MIME type to be used in the HTTP response to the client. Note that the translation is automatic only if the returned type is supported by default. For instance, if Items
is a JAXB-annotated bean, then the translation would be automatic. However, if Items
is a POJO, you would need to implement a MessageBodyReader
to handle the serialization.
You can also specify a @Produces
annotation on a method. In that case, the MIME type you specify on the method overrides the MIME types in any @Produces
annotation that you specify on the class. For example, you could specify a @Produces
annotation for the listItems()
method as follows:
@GET
@Produces (MediaType.TEXT_PLAIN)
Items listItems() {
Return Allitems();
}
JAX-RS would then translate the Items
Java type to the "text/plain" MIME type, which represents plain text, and return content of that type in the HTTP response to the client.
The @POST
annotation specifies that the annotated method, in this case, the create()
method, responds to HTTP POST requests. In this example, the method creates a new item, perhaps in a database, and then returns a response indicating that it created the new item. When a client directs an HTTP POST
request to the URI for the ItemsResource
resource, the JAX-RS runtime invokes the create()
method to handle the POST
request.
Notice that the @Consumes
annotation is specified on the create()
method. The annotation specifies the MIME media types that the methods in the resource can accept from the client. As is the case for the @Produces
annotation, if you specify @Consumes
on a class, it applies to all the methods in the class. If you specify @Consumes
on a method, it overrides the MIME type in any @Consumes
annotation that you specify for the class. In the example, the @Consumes
annotation specifies that the create()
method can accept XML content, that is, the MIME type "application/xml". Here the type translation is from MIME type to Java type. When a client submits XML content in a POST
request to the URI for the ItemsResource
class, JAX-RS invokes the create()
method and automatically translates the incoming XML to the Item
Java type required for the method's argument.
Utility classes and interfaces further simplify actions related to building and using RESTful web services. |
JAX-RS also includes a number of utility classes and interfaces that further simplify actions related to building and using RESTful web services in Java. You've already seen one of them: MediaType
, a class for abstracting MIME media types. Some others are:
UriInfo
, an interface for accessing URI information. In this example, the@Context
annotation injects theUriInfo
interface into theuriInfo
field of theItemsResource
class.UriBuilder
, a class for building URIs from their componentsResponse
, a class represents an HTTP responseResponse.ResponseBuilder
, a class that buildsResponse
objects, in accordance with the well-known Builder Pattern
These classes and interfaces are used in the following statements in the example:
URI newItemURI = uriInfo.getRequestUriBuilder().path(newItem.getId()).build();
return Response.created(newItemURI).build();
The first statement builds a URI for the new item. The getRequestUriBuilder()
method is a UriInfo
method that creates a UriBuilder
object. The path()
and build()
methods are UriBuilder
methods that together construct the URI for the new item.
The second statement creates a Response
object for the new item to be returned to the client. The created
method is a Response
method that creates a Response.ResponseBuilder
object. The build()
method is a Response.ResponseBuilder
method that creates the Response
object for the new item. This object delivers metadata to the JAX-RS runtime to construct the HTTP response.
JAX-RS eliminates a lot of the low-level programming required in HTTP-aware web applications. |
These utility classes and interfaces hide a lot of the complexity of HTTP programming — another reason why using JAX-RS is a simple way to build RESTful web services. However, this simplicity also extends beyond web services. JAX-RS can simplify the development of many types of HTTP-aware web applications. For example, if you need to build a web application that examines HTTP headers, you can probably code it in a much simpler way by using JAX-RS rather than other approaches.
JAX-RS has other convenient features. For example, JAX-RS includes a number of parameter-based annotations to extract information from a request. One of these is @QueryParam
, with which you can extract query parameters from the Query
component of a request URL. Some other parameter-based annotations are @MatrixParam
, which extracts information from URL path segments, @HeaderParam
, which extracts information from HTTP headers, and @CookieParam
which extracts information from the cookies declared in cookie-related HTTP headers.
For information about all the features in JAX-RS 1.1, see Java API for RESTful Web Services (JAX-RS), JSR 311.
Contexts and Dependency Injection for the Java EE Platform
Contexts and Dependency Injection for the Java EE Platform (CDI), JSR 299 is a technology that supplies a powerful set of services to Java EE components. These services allow Java EE components, including EJB session beans and JavaServer Faces (JSF) managed beans, to be bound to lifecycle contexts, to be injected, and to interact in a loosely coupled way by firing and observing events. Perhaps most significantly, CDI unifies and simplifies the EJB and JSF programming models. It allows enterprise beans to replace JSF managed beans in a JSF application.
CDI unifies and simplifies the EJB and JSF programming models. It allows enterprise beans to act as JSF managed beans in a JSF application, and brings transactional support to the web tier. |
In essence, CDI helps bridge what was a major gap between the web tier of the Java EE platform and the enterprise tier. The enterprise tier, through technologies such as EJB and JPA, has strong support for transactional resources. For example, using EJB and JPA you can easily build an application that interacts with a database, commits or rolls back transactions on the data, and persists the data. The web tier, by comparison, is focused on presentation. Web tier technologies such as JSF and JavaServer Pages (JSP pages) render the user interface and display its content, but have no integrated facilities for handling transactional resources.
Through its services, CDI brings transactional support to the web tier. This can make it a lot easier to access transactional resources in web applications. For example, CDI makes it a lot easier to build a Java EE web application that accesses a database with persistence provided by JPA.
Let's look at some key parts of a web application that uses CDI services. The application, which processes user login and user logout requests, includes both JSF and EJB components. Here is the code for an input form on a JSF page that displays a login prompt for the web application:
<f:view>
<h:form>
<h:panelGrid columns="2" rendered="#{!login.loggedIn}">
<h:outputLabel for="username">Username:</h:outputLabel>
<h:inputText id="username" value="#{credentials.username}"/>
<h:outputLabel for="password">Password:</h:outputLabel>
<h:inputText id="password" value="#{credentials.password}"/>
</h:panelGrid>
<h:commandButton value="Login" action="#{login.login}" rendered="#{!login.loggedIn}"/>
<h:commandButton value="Logout" action="#{login.logout}" rendered="#{login.loggedIn}"/>
</h:form>
</f:view>
As you can see from the code, the login prompt displays fields for a user to enter a user name and password. It also displays a Login button and a Logout button. Notice the unified expression language (EL) expressions such as #{credentials.username}
and #{login.login}
. These expressions refer to beans, named credentials
and login
.
CDI builds on managed beans, which are designed to unify all of the various types of beans in Java EE 6. |
Note that CDI builds on a new concept introduced in Java EE 6 called managed beans, which is designed to unify all of the various types of beans in Java EE 6. A managed bean is a Java class that is treated as a managed component by the Java EE container. Optionally, you can give it a name in the same namespace as that used by EJB components. A managed bean can also rely on a small number of container-provided services, mostly related to lifecycle management and resource injection. Other Java EE technologies such as JSF, EJB, and CDI build on this basic definition of a managed bean by adding services. So for example, a JSF managed bean adds lifecycle scopes, an EJB session bean adds services such as support for transactions, and CDI adds services such as dependency injection. In CDI a managed bean or simply a bean is a Java EE component that can be injected into other components, associated with a context, or reached through EL expressions.
You declare a managed bean by annotating its class with the javax.annotation.ManagedBean
annotation or by using one of several CDI annotations such as a scope annotation or a qualifier annotation. Scope annotations and qualifier annotations are discussed later in this section. The annotation-based programming model makes it possible for a bean to begin as a POJO and later become another type of Java EE component such as an EJB component — perhaps to take advantage of more advanced functionality, such as transactional and security annotations or the instance pooling facility offered by EJB containers. For example, you can turn a POJO into a stateful session bean by adding a @Stateful
annotation to the object. Clients that use CDI to access a bean are unaffected by the bean's transition from POJO to EJB.
Any bean can be bound to a lifecycle context, can be injected, and can interact with other beans in a loosely coupled way by firing and observing events. In addition, a bean may be called directly from Java code, or as in this example, it may be invoked in a unified EL expression. This enables a JSF page to directly access a bean, even a bean that is implemented as an EJB component such as a session bean.
In this application, a bean named Credentials
has a lifecycle that is bound to the JSF request. The Credentials
bean is implemented as a JavaBean as follows:
@Model
public class Credentials {
private String username;
private String password;
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
}
To request CDI services, you annotate a Java EE component with CDI annotations. The @Model
annotation is a CDI annotation that identifies the Credentials
bean as a model object in an Model-View-Controller (MVC) architecture. The annotation, which is built into CDI, is a stereotype annotation. A stereotype annotation marks a class as fulfilling a specific role within the application.
CDI services allow Java EE components, including EJB components, to be bound to lifecycle events. |
The application also includes a Login
bean whose lifecycle is bound to the HTTP session. The Login
bean is implemented as an EJB stateful session bean, as follows:
@Stateful
@SessionScoped
@Model
public class Login {
@Inject Credentials credentials;
@Inject EntityManager userDatabase;
private User user;
@TransactionAttribute(REQUIRES_NEW)
@RolesAllowed("guest")
public void login() {
...
}
public void logout() {
user = null;
}
public boolean isLoggedIn() {
return user!=null;
}
@RolesAllowed("user")
@Produces @LoggedIn User getCurrentUser() {
...
}
}
The @Stateful
annotation is an EJB annotation that specifies that this bean is an EJB stateful session bean. The @TransactionAttribute
and @RolesAllowed
annotations are also EJB annotations. They declare the EJB transaction demarcation and security attributes of the annotated methods.
All beans have a scope. Among other things, this gives EJB components access to the request, session, and application contexts of web tier components. |
The @SessionScoped
annotation is a CDI annotation that specifies a scope for the bean. All beans have a scope that determines the lifecycle of its instances and the instances of the bean that are made visible to instances of other beans. This is an important feature because components such as EJB components do not have a well-defined scope. In particular, EJB components are not aware of the request, session, and application contexts of web tier components such as JSF managed beans, and do not have access to the state associated with those contexts. In addition, the lifecycle of a stateful EJB component cannot be scoped to a web-tier context.
By contrast, scoped objects in CDI exist in a well-defined lifecycle context that is managed by the Java EE container. Scoped objects may be automatically created when needed and then automatically destroyed when the context in which they were created ends. Significantly, the state of a scoped object is automatically shared by clients that execute in the same context. This means that clients such as other beans that execute in the same context as a scoped object see the same instance of the object. But clients in a different context see a different instance. The @SessionScoped
annotation specifies that the scope type for the Login
bean is session scope. Objects that are not associated with any of the usual scopes, but instead exist for the exclusive benefit of an object that triggered their creation, are said to be dependents of their owner. The lifecycle of these dependent objects is tied to that of the owner. In particular, a dependent object is destroyed whenever the owner is destroyed.
CDI services allow Java EE components, including EJB and JPA components, to be injected. |
Beans typically acquire references to other beans through dependency injection. The dependency injection mechanism is completely type safe. CDI uses the annotations specified in JSR 330: Dependency Injection for Java for dependency injection. One of those annotations, @Inject
, identifies a point at which a dependency on a Java class or interface can be injected. The container then provides the needed resource. In this example, the Login
bean specifies two injection points. The first use of the @Inject
annotation in the example injects a dependency on the Credentials
bean. In response, the container will inject the Credentials
bean into any instance of Login
created within this context. The second @Inject
annotation injects a dependency on the JPA EntityManager
. The container will inject the EntityManager
to manage the persistence context. Refer to Standardized Annotations for Dependency Injection to learn more about the @Inject
annotation and other annotations in JSR 330.
The @Produces
annotation identifies the getCurrentUser()
method as a producer method. A producer method is called whenever another bean in the system needs an injected object of the specified type. In this case, the injected object is the currently logged-in user, which is injected by the qualifier annotation @LoggedIn
. A qualifier identifies a specific implementation of a Java class or interface to be injected. In order to use a qualifier annotation, you first need to define its type as a qualifier. You use the @Qualifier
annotation, another JSR 330 annotation, to do that. For example:
@Target( { TYPE, METHOD, PARAMETER, FIELD })
@Retention(RUNTIME)
@Documented
@Qualifier
public @interface LoggedIn {...}
Let's return to the login prompt discussed earlier. When a user responds to the prompt and clicks the Submit button, CDI technology goes into action. The Java EE container automatically instantiates a contextual instance of the Credentials
bean and the Login
bean. An instance of a bean that is bound to a context is called a contextual instance. JSF assigns the user name and password the user entered to the Credentials
bean contextual instance. Next, JSF calls the login()
method in the Login
bean contextual instance. This instance continues to exist for and is available to other requests in the same HTTP session, and provides the User
object that represents the current user to any other bean that requires it.
This example demonstrates only some of the features in this powerful technology. Another feature enables beans to produce or consume events. Yet another lets you define interceptors that bind additional function across all bean types, or define decorators that apply the additional function to a specific bean type. To learn about these and the other features in CDI technology, see Contexts and Dependency Injection for the Java EE Platform, JSR 299.
Bean Validation
Validating data is a common task that occurs throughout an application. For example, in the presentation layer of an application, you might want to validate that the number of characters a user enters in a text field is at most 20 characters or that the number a user enters in a numeric field is positive. If you set those constraints, you probably want the same data to be validated before it's used in the business logic of the application and when the data is stored in a database.
Developers often code the same validation logic in multiple layers of an application, something that's time consuming and error-prone. Or they put the validation logic in their data model, cluttering it with what is essentially metadata.
Bean Validation affords a standard framework for validation, in which the same set of validations can be shared by all the layers of an application. |
Bean Validation, JSR 303 makes validation simpler and reduces the duplication, errors, and clutter that characterizes the way validation is often handled in enterprise applications. Bean Validation affords a standard framework for validation, in which the same set of validations can be shared by all the layers of an application.
Specifically, Bean Validation offers a framework for validating Java classes written according to JavaBeans conventions. You use annotations to specify constraints on a JavaBean — you can annotate a JavaBean class, field, or property. You can also extend or override these constraints through XML descriptors. A validator class then validates each constraint. You specify which validator class to use for a given type of constraint.
Here, for example, is part of a class that declares some constraints through Bean Validation annotations:
public class Address {
@NotNull @Size(max=30)
private String addressline1;
@Size(max=30)
private String addressline2;
...
public String getAddressline1() {
return addressline1;
}
public void setAddressline1(String addressline1) {
this.addressline1 = addressline1;
}
...
}
The @NotNull
annotation specifies that the annotated element, addressline1
, must not be null. The @Size
annotation specifies that the annotated elements, addressline1
and addressline2
, must not be longer than the specified maximum, 30 characters.
When an Address
object is validated, the addressline1
value is passed to a validator class that is defined for the @NotNull
constraint as well as to a validator class defined for the @Size
constraint. The addressline2
value is also passed to the validator class for the @Size
constraint. The pertinent validator classes perform the validations.
Bean Validation includes a number of built-in constraint definitions. You add your own constraints by declaring an annotation type that specifies a validator class. |
Both the @NotNull
and @Size
constraints are built into the Bean Validation framework so you do not need to define validator classes for them. However, you can add your own constraints to the built-in constraints, in which case, you need to define validator classes. For example, you can define a constraint named @ZipCode
as follows:
@Size(min=5, max=5)
@ConstraintValidator(ZipcodeValidator.class)
@Documented
@Target({ANNOTATION_TYPE, METHOD, FIELD})
@Retention(RUNTIME)
public @interface ZipCode {
String message() default "Wrong zipcode";
String[] groups() default {};
}
Then you can specify the @ZipCode
constraint on a class, field, or property just like any other constraint. Here is an example:
public class Address {
...
@ZipCode
private String zipCode;
public String getZipCode() {
return zipCode;
}
public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
...
}
When an Address
object is validated, the zipCode
value is passed to the ZipcodeValidator
class for validation. Notice that the constraint definition includes another constraint: @Size(min=5, max=5)
. This means that an element annotated by the @ZipCode
annotation must be exactly 5 characters in length. The element is validated against this constraint in addition to the primary constraint check that ZipcodeValidator
performs. Bean Validation allows you to create a constraint that is composed of other constraints. In fact, any composing constraint can itself be composed of constraints. Notice too that the constraint definition specifies an error message to be returned if the constraint fails the validation check. Here, the error message is "Wrong zipcode".
In addition to validating individual objects, you can use Bean Validation to validate an entire object graph. |
You can also use Bean Validation to validate an entire object graph in a straightforward way. An object graph is an object composed of other objects. If you specify the @Valid
annotation on the root object of an object graph, it directs the pertinent validator to recursively validate the associated objects in the object graph. Consider the following example:
public class Order {
@OrderNumber private String orderNumber;
@Valid @NotNull private Address delivery;
}
When an Order
object is validated, the Address
object and the associated objects in its object graph are validated too.
Bean Validation is integrated across the Java EE 6 platform. |
To meet the objective of sharing the same set of validations across all the layers of an application, Bean Validation is integrated across the Java EE 6 platform. For example, presentation-layer technologies such as JSF and enterprise-layer technologies such as JPA have access to the constraint definitions and validators available through the Bean Validation framework. You no longer need to specify constraints in multiple places and in multiple ways across the layers of an application.
To learn more about Bean Validation, see Bean Validation, JSR 303.