Tuesday May 15, 2012

JSON-P: Java API for JSON Processing (TOTD #178)


JSR 353 is Java API for JSON Processing (JSON-P) and will define an API to process (e.g. parse, generate, transform, and query) JSON. This JSR will be delivered as part of Java EE 7. The API will allow to produce and consume JSON in a streaming fashion (StAX equivalent in XML world) and build a Java object model for JSON (DOM equivalent in XML world). Note, binding JSON to Java objects and vice versa is not part of the scope of this JSR.

json-processing-spec.java.net is where all the specification work is happening and jsonp.java.net is the project for the  Reference Implementation. Its still early days but this Tip Of The Day (TOTD) will explain how to get started. The workspace can be checked out as

git clone git://java.net/jsonp~git
Cloning into jsonp~git...
remote: Counting objects: 313, done.
remote: Compressing objects: 100% (218/218), done.
remote: Total 313 (delta 110), reused 0 (delta 0)
Receiving objects: 100% (313/313), 64.13 KiB, done.
Resolving deltas: 100% (110/110), done.

Building the workspace require JAVA_HOME to be set (/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home or /System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home). Once set, the workspace can be built as
mvn install
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] RI for JSON-P JSR
[INFO] Java API for Processing JSON (JSON-P)
[INFO] jsonp-tests
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building RI for JSON-P JSR 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------

. . .

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

[INFO]
[INFO] --- maven-jar-plugin:2.3.1:jar (default-jar) @ jsonp-tests ---
[WARNING] JAR will be empty - no content was marked for inclusion!
[INFO] Building jar: /Users/arungup/code/workspaces/jsonp~git/tests/target/jsonp-tests-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- maven-install-plugin:2.3.1:install (default-install) @ jsonp-tests ---
[INFO] Installing /Users/arungup/code/workspaces/jsonp~git/tests/target/jsonp-tests-1.0-SNAPSHOT.jar to /Users/arungup/.m2/repository/org/glassfish/jsonp-tests/1.0-SNAPSHOT/jsonp-tests-1.0-SNAPSHOT.jar
[INFO] Installing /Users/arungup/code/workspaces/jsonp~git/tests/pom.xml to /Users/arungup/.m2/repository/org/glassfish/jsonp-tests/1.0-SNAPSHOT/jsonp-tests-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] RI for JSON-P JSR ................................. SUCCESS [0.528s]
[INFO] Java API for Processing JSON (JSON-P) ............. SUCCESS [12.214s]
[INFO] jsonp-tests ....................................... SUCCESS [1.695s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

The API .jar file is in api/target/jsonp-ri-1.0-SNAPSHOT.jar and javadocs are in api/target/jsonp-ri-1.0-SNAPSHOT-javadoc.jar. There are several tests in the tests directory that shows the API usage. The RI JARs are not pushed to a public maven repo yet but are installed in the local repo with the above command. These can be included in your "pom.xml" with the following coordinates:

<dependency>
<groupId>javax.json</groupId>
<artifactId>jsonp-ri</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

The key APIs are
  • DOM-based APIs (javax.json package)
    • JsonBuilder - Builds a JSON object or JSON array
    • JsonReader - Reads a JSON object or array from the stream
    • JsonWriter - Writes a JSON object or array to the stream
  • Streaming APIs (javax.json.stream package)
    • JsonGenerator - Streaming JSON generator
    • JsonParser - Allows forward, read-only access to JSON

Here is an sample usage of JsonBuilder:
JsonObject value = new JsonBuilder()
   .beginObject()
     .add("firstName", "John")
     .add("lastName", "Smith")
     .add("age", 25)
        .beginObject("address")
           .add("streetAddress", "21 2nd Street")
           .add("city", "New York")
           .add("state", "NY")
           .add("postalCode", "10021")
        .endObject()
        .beginArray("phoneNumber")
           .beginObject()
              .add("type", "home")
              .add("number", "212 555-1234")
           .endObject()
           .beginObject()
              .add("type", "home")
              .add("number", "646 555-4567")
           .endObject()
        .endArray()
   .endObject()
.build();

Here is a sample usage of JsonReader:

String json = "...";
JsonReader reader = new JsonReader(new StringReader(json));
JsonValue value = reader.readObject();
reader.close();

A sample usage of JsonWriter:

JsonWriter jsonWriter = new JsonWriter(new FileWriter(...));
JsonObject jsonObject = new JsonBuilder()
.beginObject()
. . .
.endObject()
.build()
; jsonWriter.writeObject(jsonObject); jsonWriter.close();
Here is a sample usage of JsonGenerator:

JsonGenerator generator = new JsonGenerator(new FileWriter(...));
generator
.beginObject()
. . .
.beginArray()
. . .
.endArray()
.endObject()
.build();
generator.close();

And finally a sample usage of JsonParser:
String json = "...";
JsonParser parser = new JsonParser(new StringReader(json));
Iterator<Event> it = reader.iterator();
Event event = it.next();
The event  can be of the following types:
  • START_OBJECT
  • END_OBJECT
  • START_ARRAY
  • END_ARRAY
  • KEY_NAME
  • VALUE_STRING
  • VALUE_NUMBER
  • VALUE_FALSE
  • VALUE_TRUE
  • VALUE_NULL
Here are some references to track the progress and provide feedback:
This JSR will be delivered as part of Java EE 7. Here are some other early work that has been explained:

Have fun!

Saturday Apr 21, 2012

JMS 2.0 Early Draft - Simplified API Sample Code


Java Message Service (JSR 343) is undergoing a major revision as part of Java EE 7. The Early Draft of the specification has been available for a few weeks now and online javadocs are now available. Several other specifications such as JPA 2.1, JAX-RS 2.0, EJB 3.2, JavaServer Faces 2, and CDI 1.1 in the Java EE 7 umbrella have released early drafts. Some of the specs have been explained in detailed:
This blog will provide an update on JMS 2.0 Early Draft.

JMS 1.1 was released in Dec 2003. A lot has chnged in the Java landscape since then - think about annotations, generics, auto-closeable, dependency injection, and a lot more. The Java EE platform itself has evolved extensively since then, especially Java EE 6 is a "game changer". There are multiple JMS implementations still running solid and so there is lot of development/deployment experience on that as well. Keeping all of that, and much more, in mind, the main goals of JMS 2.0 are:
  • Changes to improve ease of development
  • Clarification of relationship between the JMS and other Java EE specifications
  • Definition of a new mandatory API to allow any JMS provider to be integrated with any Java EE application server
  • Extensions to support Java EE 7
  • Other enhancements as requested by the community
This blog will take a code sample from the section 11.4 of the Early Draft to highlight how ease-of-development changes are now coming to JMS 2.0.

This is how a message is sent using the existing JMS API:

@Resource(lookup = "jms/connectionFactory ")
ConnectionFactory connectionFactory;

@Resource(lookup="jms/inboundQueue")
Queue inboundQueue;

public void sendMessageOld (String payload) {
Connection connection = null; try {
connection = connectionFactory.createConnection(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer messageProducer = session.createProducer(inboundQueue); TextMessage textMessage = session.createTextMessage(payload); messageProducer.send(textMessage); } catch (JMSException e) {
// do something
} finally {
try {
if (connection != null)
connection.close();
} catch (JMSException e2) {
// do something else
}
} }
This works very well but several issues with it:
  1. Multiple intermediate objects such as Connection, Session, and MessageProducer need to be created in order to send a message. All these objects serve a purpose but makes the JMS application more complicated. It also leads to lots of boilerplate code as well.
  2. The arguments to createSession are confusing. The first argument specifies whether the session is transacted or not. The second argument specifies, how, if you used the session to receive messages, how those messages would be acknowledged. These two arguments are not independent. If the first argument is set to true then the second argument is irrelevant. So we only need one argument here.

    The other part is when this method is in a EJB then the transactions are controlled by the container. Or if a bean-managed transactions are used then the transaction would be started and committed using the UserTransaction API, not by methods in the JMS API. In fact, the EJB spec says that if this code is running in a transaction then the arguments to createSession are completely ignored. And even then we are required to supply some arguments here to satisfy the contract.
  3. The Connection need to explicitly closed in the finally block in order to release the resources appropriately on the server side. The code does not even show closing of MessageProducer and Session and And the finally block gets ugly with nested exceptions.

Now lets take a look at how the new API will simplify the programming model:

@Resource(lookup = "jms/connectionFactory")
ConnectionFactory connectionFactory;
@Resource(lookup="jms/inboundQueue") Queue inboundQueue;
public void sendMessageNew (String payload) { try (JMSContext context = connectionFactory.createContext();){ context.send(inboundQueue,payload); } }
Simple, isn't it ?

Here are the main changes:
  1. All the boilerplate is gone. Instead just create a ConnectionFactory, create a context from it, and invoke send on it.
  2. The destinatation (inboundQueue) is now specified on send insead of MessageProducer.
  3. Connection is now auto-closeable so try block will close it autoamatically.
  4. New methods throw runtime exception so the code looks much cleaner.

And if you are using Dependency Injection, then the code can be further simplified to:

@Inject
@JMSConnectionFactory("jms/connectionFactory")
private JMSContext context;
@Resource(mappedName = "jms/inboundQueue")
private Queue inboundQueue;
public void sendMessageNew(String payload) {
context.send(inboundQueue, payload);
}
Some clean ups to note here are ...
  • No need for application to instantiate JMSContext
  • The same injected JMSContext is available in other places, if within the same CDI scope
How cool is that ?

Here is yet another example on how the simplified API receives a message synchronously:

@Inject
@JMSConnectionFactory("jms/connectionFactory")
private JMSContext context;
@Resource(lookup="jms/inboundQueue") Queue inboundQueue;
public String receiveMessageNew() { JMSConsumer consumer = context.createConsumer(inboundQueue); return consumer.receivePayload(String.class); }

The section 11.4 of the JMS 2.0 Early Draft provide more lot more samples with the standard (or existing) API and the simplified (or new) API.

Do you like the direction that the JMS 2.0 Expert Group is taking ? Would you like to provide feedback and contribute ?

The latest progress on JMS 2.0 can be tracked at:

Help us make JMS 2.0 better, simpler, easier to use. Join users@jms-spec and contribute!

Tuesday Feb 07, 2012

JAX-RS 2.0 Early Draft Explained - Java EE 7 Making Progress


JAX-RS 2.0 Early Draft has been available for about 3 months now. JAX-RS 2.0, just like JPA 2.1, was one one of the first JSRs to be filed as part of Java EE 7. Several other specifications in Java EE 7 have released early drafts as well (JavaServer Faces 2.2CDI 1.1, EJB 3.2, and more coming as well) and I'll cover them in later blogs.

Here are the topics covered so far:
JAX-RS 2.0 is a brand new specification and here are the main highlights so far:
  • Client API: The HTTPUrlConnection is too low level and is not RESTful-oriented. Invoking a RESTful resource using this class would look like:

    URL url = new URL("http://.../atm/balance");
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestMethod("GET");
    conn.setDoInput(true);
    conn.setDoOutput(false);
               
    BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
    String line;
    while ((line = br.readLine()) != null) {
        out.println(line);
    }


    Notice, how much code has to be written and its brittle. Some JAX-RS 1.0/1.1 implementations already provide a higher-level client-side API to access the Web resources. For example, read TOTD #57 for more details about Jersey Client API. A slightly more advanced sample to access Twitter timeline using Jersey Client API is described in TOTD #143.

    JAX-RS 2.0 introduces a standard Client API to in javax.ws.rs.client package to access the Web resource. It also share features with JAX-RS server API (readers/writers).

    A simple usage looks like:

    Client client = ClientFactory.newClient();
    String balance = client.target("http://.../atm/balance")
                           .request("text/plain")
                           .get(String.class);


    Instead of Client client = ClientFactory.newClient(), would you like @Inject Client client then vote for JAX_RS_SPEC-170.

    Path and query parameters can be easily specified using the builder pattern as shown below:

    Client client = ClientFactory.newClient();
    String balance = client.target("http://.../atm/{card}/balance")
                           .pathParam("card", "1111222233334444")
                           .queryParam("pin", "1234")
                           .request("text/plain")
                           .get(String.class);


    See how the template in the target path is automatically substituted with the correct value. The request type is specified to be "text/plain" and GET method of this web resource is invoked. This will be translated to:

    http://.../atm/1111222233334444/balance?pin=1234

    A POST request will look like:

    Money balance = client.target("http://.../atm/{card}/withdraw")
                          .pathParam("card", "1111222233334444")
                          .queryParam("pin", "1234")
                          .request("application/json")
                          .post(text("50.0"), Money.class);

    There is also generic command pattern that enables separation of concern between the creator and submitteruseful for batch processing using Invocation. And the code would look like:

    Invocation inv1 = client.target("http://.../atm/{card}/balance")
                            .pathParam("card", "1111222233334444")
                            .queryParam("pin", "1234")
                            .request("text/plain")
                            .buildGet();


    Invocation inv2 = client.target("http://.../atm/{card}/withdraw")
                            .pathParam("card", "1111222233334444")
                            .queryParam("pin", "1234")
                            .request("application/json")
                            .buildPost(text("50.0"));

    And once the Invocations are ready then they can be invoked.

  • Filters and Handlers: The filters and handlers allow app developers to perform message request pre-processing and response post-processing via well-defined extension points on the client- and server-side. This is yet another feature that was supported by several JAX-RS 1.0/1.1 implementations with each using slightly different semantics and now getting standardized in JAX-RS 2.0.

    Filters are non-wrapping extension points, allow pre-processing without modifying the request itself. A filter implements interface RequestFilter or ResponseFilter or both and is annotated with @Provider. A logging filter that simply logs the message may look like:

    @Provider
    class LoggingFilter implements RequestFilter, ResponseFilter {

        @Override
        public FilterAction preFilter(FilterContext ctx) throws IOException {
            logRequest(ctx.getRequest());
            return FilterAction.NEXT;
        }

        @Override
        public FilterAction postFilter(FilterContext ctx) throws IOException {
            logResponse(ctx.getResponse());
            return FilterAction.NEXT;
        }
    }

    Multiple filters are grouped in filter chains. The response from preFilter and postFilter indicate whether the next filter in the chain need to be executed (FilterAction.NEXT) or stopped (FilterAction.STOP).

    Handlers provide wrapping extension points. A handler implements interface ReadFromHandler or WriteToHandler or both and is annotated with @Provider. A GZIP filter that provides deflate and inflate capabilities may look like:

    @Provider
    class GzipHandler implements ReadFromHandler, WriteToHandler {
        @Override
        public Object readFrom(ReadFromHandlerContext ctx) throws IOException {
            InputStream old = ctx.getInputStream();
            ctx.setInputStream(new GZIPInputStream(old));
            try {
                return ctx.proceed();
            } finally {
                ctx.setInputStream(old);
            }
        }

        @Override
        public Object writeTo(WriteToHandlerContext ctx) throws IOException {
            OutputStream old = ctx.getOutputStream();
            GZIPOutputStream gzipOutputStream =
    new GZIPOutputStream(old);
            ctx.setInputStream(gzipOutputStream);
            try {
                return ctx.proceed();
            } finally {
                gzipOutputStream.finish();
                ctx.setOutputStream(old);
            }
        }
    }

    Multiple handlers are grouped in handler chains. The proceed method must be explicitly called in order for the next handler in the chain to be invoked.

    In the direction of flow the filters always executed before handlers. The following diagram shows the exact execution order on client and server-side:



    The handlers and filters can be associated to each method of a resource specifically using @NameBinding. The specification defines @GlobalBinding to associate handlers and filters to all methods of a resource but the recent version of the specification removes it and makes it a default. Also look at JAX_RS_SPEC-146 that asks for a mechanism to override the global filters/handlers.

    The dynamic binding, enabled by implementing DynamicBinding, provide more control on the association with resources and methods.
  • Hypermedia: Linking resources together is one of the main RESTful principles. There are structural links that are used to avoid sending a complete representation of a resource and enable lazy loading. The clients can follow these type of links to retrieve the "pieces" they need. A transitional link is used to update the state of a resource and is typically identified by a "rel" attribute. Structural links are normally in the entity; transitional links could be in link headers or the entity.

    JAX-RS 2.0 will only support transitional links in headers using newly added Link and LinkBuilder classes. The proposed Client API can also create a target from a link. The code may look like:

    Response r = client.target("/product").request("application/json").get();
    ResponseHeaders rh = r.getHeaders();
    if (rh.hasLink("ship")) {
        client.invocation(rh.getLink("ship")).invoke();
    }


    On the server side, ResponseBuilder has support for adding one or more link headers. The code may look like:

    @Path("/products")
    public class MyResponse {

        @GET
        @Path("{id}")
        @Produces({"application/json", "application/xml"})
        public Response getProduct(@PathParam("id")int id) {
            Product product = new Product(id);
            return Response
                    .ok(product)
                    .link("http://.../orders/" + id + "/ship", "ship")
                    .build();
        }
    }


  • Validation: Web resources must validate data received in query or header parameters or entity bodies. Currently this validation has to be performed in the application code. The Bean Validation specification already defines a extensible mechanism to specify validation constraints on a bean. So the JAX-RS specification leverages that and introduces support for declarative validation. The constraint annotations can be specified in public constructor parameters, method parameters, fields and bean properties. In addition, they can also decorate resource classes, entity parameters and resource methods. Here is a sample class augmented with constraint annotations:

    @Path("/")
    class ProductResource {

        @POST
        @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
        public void addProduct(@NotNull @FormParam("productName") String name,
                               @NotNull @Category @FormParam("category") String category) {
            . . .
        }
    }


    The @NotNull is a pre-defined constraint in the Bean Validation API and ensures that the target parameters are not null. The @Category is a user-defined constraint using the extensible mechanism provided by the Bean Validation API. If the constraints are violated then the resource method is not invoked and instead a response with status code 400 (Bad Request) and an entity that describe the violations is returned to the client.

    Here is a sample code of how to validate request entity bodies when they are mapped to resource method parameters:

    @CheckProduct
    class Product { . . . }

    @Path("/")
    class ProductResource {

        @POST
        @Consumes(MediaType.APPLICATION_JSON)
        public void addProduct(@Valid Product product) {
            . . .
        }
    }


    The presence of @Valid (a pre-defined annotation in Bean Validation API) next to the method parameter ensures that the @CheckProduct constraint is called to verify the mapped entity.

    The JAX-RS specification also defines the sequence to validate root resource class instances. The recommendation is to return as many violations as possible instead of aborting after the first violation is encountered.
  • Asynchronous Processing: JAX-RS 2.0 introduces asynchronous processing on server- and client-side APIs for the usual reasons. The server-side code will look like:

    @Path("/async")
    class ProductResource {
        @Context ExecutionContext ctx;

        @GET
        @Suspend
        public Product longOp() {
            Executors.newSingleThreadExecutor().submit(
                new Runnable() {
                    public void run() {
                        Proruct product = longQueryFromDatabase();
                        ctx.resume(product);
                    }
                }
            );
        }
    }

    The longOp method is invoked when this resource is accessed using GET, forks a new thread, and returns immediately without producing the result. Once longQueryFromDatabase returns the product then the connection is resumed and the response is returned by calling ctx.resume and setting the value.

    ExecutionContext also provide suspend() that allows to override the values, such as timeout, specified in the annotation based upon the runtime state.

    On the client-side, the code will look like:

    Client client = ClientFactory.newClient();
    Future<String> future = client.target("http://.../atm/{card}/balance")
                                  .pathParam("card", "1111222233334444")
                                  .queryParam("pin", "1234")
           
                           .request("text/plain")
                  
                    .async()
                         
             .get();

    The async() is called during building the client request. The return Future<String> can be used to query/cancel the status of execution on the server-side using isDone and cancel. Once the response is ready then Future<T>.get() is invoked to receive an instance of T if the response was successful or null if the invocation failed.

    Optionally an InvocationCallback<T> may be registered during the request invocation. The completed method is called when the invocation completes successfully and a response is available and failed method is called when the invocation fails. The code looks like:

    Future<String> future = client.target("http://.../atm/{card}/balance")
                                  .pathParam("card", "1111222233334444")
                                  .queryParam("pin", "1234")
           
                           .request("text/plain")
                  
                    .async()
                         
             .get(
                                      new InvocationCallback<String>() {
                                          @Override
                                          public void completed(String result) {
                                              // got the correct result
                                              System.out.println(result);
                                          }

                                          @Override
                                          public void failed(InvocationException error) {
                                              // ouch, got an error!
                                              System.err.println(error.getCause());
                                          }
                                      }
                                   );


    Notice, the type of the result is specified as type parameter to InvocationCallback.

    Client and server developers optimize their resources (threads) depending upon their needs and are independent of each other. A client really can't tell if a resource is implemented asynchronously or not and shouldn't even need to know.

  • Improved connection negotiation: This would allow a server to specify a preferred MIME type if the client does not care about it. This can be easily specified using the "qs" qualifier as shown below:

    @Path("/")
    class ProductResource {

        @GET
        @Produces({ "text/xml
    ;qs=0.75", "application/json"})
        public Product[] getProducts() {
            . . .
        }
    }


    The default server-side qs-value and the final order of server-side served types preferences follow the same rules as those specified for HTTP Accept Header. Per those rules an unspecified value takes the default value of 1. So the above @Produces rule says "application/json" will be served as the preferred type if there is no Accept header from the client. The section 3.5 talks more about qs parameter and the section 3.8 in the specification provide complete details about how media type of the response is chosen by a JAX-RS runtime.

The Appendix D in the specification provide a comprehensive list of changes from the previous version of the specification.

Here are some final set of references for you:

And of course, it'll all be delivered as part of GlassFish 4.0!

Learn the latest and greatest about JAX-RS 2.0 from Marek Potociar's talk on JAX-RS at Devoxx 2011:

Monday Jan 23, 2012

JPA 2.1 Early Draft Explained - Java EE 7 making progress

Java Persistence API 2.1 Early Draft has been available for about a month now. JPA2 was one of the first JSRs to be filed as part of Java EE 7. Several other specifications in Java EE 7 have released early drafts as well (JavaServer Faces 2.0, JAX-RS 2.0, CDI 1.1, more coming as well) and I'll cover them in later blogs.

Here are the main highlights of JPA 2.1:
  • Support for Stored Procedures: Added support for the invocation of predefined database functions and user-defined database functions to the Java Persistence query language.

    There are different variants of EntityManager.createXXXStoredProcedureQuery methods that return a StoredProcedureQuery for executing a stored procedure.  Just liked @NamedQuery, there is @NamedStoredProcedureQuery that specifies and names a stored procedure, its parameters, and its result type. This annotation can be specified on an entity or mapped superclass. The name specified in the annotation is then used in EntityManager.createNamedStoredProcedureQuery. The IN, OUT, and INOUT parameters can be set and used to retrieve values passed back from the procedure. For example:

    @Entity
    @NamedStoredProcedureQuery(name="topGiftsStoredProcedure", procedureName="Top10Gifts")
    public class Product {
     . . .
    }


    // In your client

    StoredProcedreQuery query = EntityManager.createNamedStoredProcedureQuery("topGiftsStoredProcedure");
    query.registerStoredProcedureParameter(1, String.class, ParameterMode.INOUT);
    query.setParameter(1, "top10");
    query.registerStoredProcedureParameter(2, Integer.class, ParameterMode.IN);
    query.setParameter(2, 100);
    // there are other setParameter methods for defining the temporal type of a parameter
    . . .
    query.execute();
    String response = query.getOutputParameterValue(1);


    The section 3.8.6 provide more details.
  • Bul update/delete using Criteria: Added CriteriaUpdate, CriteriaDelete, CommonAbstractQuery interfaces, refactored AbstractQuery interface.

    Here is a sample for CriteriaUpdate from section 6.5.15:

    CriteriaUpdate<Customer> q = cb.createCriteriaUpdate(Customer.class);
    Root<Customer> c = q.from(Customer.class);
    q.set(c.get(Customer_.status), "outstanding")
     .where(cb.lt(c.get(Customer_.balance), 10000));

    with the equivalent JPQL of:

    UPDATE Customer c
    SET c.status = 'outstanding'
    WHERE c.balance < 10000

    This query can then be executed as:

    @PersistenceContext EntityManager em;
    Query query = em.createQuery(q);
    query.executeUpdate();

    Here is a sample for CriteriaDelete from section 6.5.15:

    CriteriaDelete<Customer> q = cb.createCriteriaDelete(Customer.class);
    Root<Customer> c = q.from(Customer.class);
    q.where(cb.equal(c.get(Customer_.status), "inactive"),
            cb.isEmpty(c.get(Customer_.orders)));

    with the equivalent JPQL of:

    DELETE FROM Customer c
    WHERE c.status = 'inactive'
    AND c.orders IS EMPTY


    This query can then be executed in similar way as earlier:

    @PersistenceContext EntityManager em;
    Query query = em.createQuery(q);
    query.executeUpdate();

  • New reserved keywords: Added the following to Java Persistence query language reserved identifiers: FUNCTION, ON, TREAT.
    • Pre-defined and user-defined functions using FUNCTION: JPQL provide several in-built functions which may be used in the SELECT, WHERE or HAVING clause of a query such as CONCAT, SUBSTRING, TRIM, LENGTH, ABS, SQRT, and CURRENT_DATE. The section 4.6.17.3 define invocation of predefined and user-defined database functions using the FUNCTION operator. The FUNCTION is used to invoke predefined database functions or user-defined database functions. An example from the section is:

      SELECT c
      FROM Customer c
      WHERE FUNCTION(‘hasGoodCredit’, c.balance, c.creditLimit)

    • Downcasting using TREAT: TREAT is supported for downcasting within path expressions in the FROM and WHERE clauses. Use of the TREAT operator allows access to subclass-specific state. An example from section 4.4.9 is:

      SELECT b.name, b.ISBN
      FROM Order o JOIN TREAT(o.product AS Book) b


      In this example, the join is performed between Order and Product but name and ISBN are attributes of the Book class which is a subclass of the Product class. Another example is:

      SELECT e FROM Employee e
      WHERE TREAT(e AS Exempt).vacationDays > 10
      OR TREAT(e AS Contractor).hours > 100


      Here again vacationDays are attributes for Exempt employees only and hours only for Contractor.

    • Join condition using ON: The ON clause in SQL is used to specify the relationship between the tables. It is different from the WHERE clause which specifies the criteria for the rows to be picked. An example from the section 4.4.5.2 shows the JPQL as:

      SELECT s.name, COUNT(p)
      FROM Suppliers s LEFT JOIN s.products p
      ON p.status = 'inStock'
      GROUP BY s.name


      The mapped SQL for this will be:

      SELECT s.name, COUNT(p.id)
      FROM Suppliers s LEFT JOIN Products p
      ON s.id = p.supplierId AND p.status = 'inStock'
      GROUP BY s.name


      The s.id = p.supplierId condition is generated becase of the LEFT JOIN. The additional JOIN condition of p.status = 'inStock' is also added to the generated SQL because of the ON clause in the JPQL. The result of this query will include all suppliers (with possibly NULL values). This is different from the query below:

      SELECT s.name, COUNT(p)
      FROM Suppliers s LEFT JOIN s.products p
      WHERE p.status = 'inStock'
      GROUP BY s.name


      The result of this query will not include suppliers that have no products in stock.

      Additional methods are also added to Fetch, Join, CollectionJoin, SetJoin, ListJoin, and MapJoin interfaces to support the ON clause.
  • Entity listeners using CDI: Entity Listeners allow to handle cross-cutting lifecycle events in a non-persistent listener class. In JPA 2.1, entity listeners will support dependency injection through CDI. The usual lifecycle callback methods of @PrePersist, @PostPersist, @PreUpdate, and @PreRemove can be used for entities. The entity listeners can also be annotated with @PostConstruct and @PreDestroy for their own lifecycle. The section 3.5.1 provides more details on this.

    Read more details on jsr338-experts alias archive and users@jpa-spec.
  • Synchronization of persistence contexts: In JPA 2, the persistence context is synchronized with the underlying resource manager. Any updates made to the persistence context are propagated to the resource manager. JPA 2.1 introduces the concept of unsynchronized persistence contenxt. Here is how you can create a container-managed unsynchronized persistence context:

    @PersistenceContext(synchronization=SynchronizationType.UNSYNCHRONIZED) EntityManager em;

    The section 7.6.1 provide more details.
  • Several clarifications in text and javadocs

The Appendix in the specification provide a comprehensive list of changes in this version of the specification. And there are change bars through out as well allowing you to see what has changed since JPA 2.

Here are some final set of references for you:

And of course, it'll all be delivered as part of GlassFish 4.0!


About

profile image
Arun Gupta is a technology enthusiast, a passionate runner, author, and a community guy who works for Oracle Corp.


Java EE 7 Samples

Stay Connected

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today