Skip navigation
1 2 3 Previous Next

bhaktimehta

38 posts
I had the pleasure to review JavaServer Faces: Introduction by Example by Josh Juneau which has been published by Apress in December 2014. http://ecx.images-amazon.com/images/I/51hPHr8HMAL._SX403_BO1,204,203,200_.jpgThe highlight of the book was the simplicity with which Josh has covered some of the most complicated topics related to JavaServer Faces (JSF).  I like how smoothly and seamlessly he can transition from the simple recipes to the more involved and detailed discussions in each chapter. I also  appreciated the way he covers every topic as a recipe and has an example source code and a detailed explanation for each recipe's code.

Here are the details of each chapter in the book

 

Chapter 1: Introduction to Servlets

Chapter 1 covers detailed introduction to Servlets with examples from setting up the Java Enterprise environment, installing GlassFish, developing the first servlet, to packaging and deploying the servlet. It also discusses about topics related to dispatching requests,  filtering web requests, adding listeners, downloading files etc. There is a section that covers Servlet 3.0 Non-Blocking I/O and Async APIs which will be very beneficial for readers interested in processing requests asynchronously and not having to block for a long running task to complete and send the response.

Chapter 2: JavaServer Pages

Chapter 2 covers JavaServer Pages(JSP) and starts with a simple JSP. It covers the lifecycle of the JSP, embedding Java in JSP page,  embedding expressions in EL, creating custom JSP tags, error handling, disabling scriptlets in JSP pages etc. I particularly liked the  database sample which shows how  to create an input form for a database record and loop through the records. The first two chapters covered the initial foundation extremely well to get started with JavaServer Faces in Chapter 3.

Chapter 3: The Basics of JavaServer Faces

This chapter begins with developing a simple JSF example. It covers details on breaking down a JSF application which consists of the  components for a JSF application. It covers the life cycle of a JSF application. Further sections discuss on writing a managed bean  and access it within a JSF view using EL. The Managed Bean Scopes section was very informative. The building sophisticated views  with components covered how to build well formed views with JSF and HTML. It also highlighted navigation techniques within JSF applications and how to validate inputs in the application before they can be persisted. 

Chapter 4: Facelets

Chapter 4 starts off with Facelets which is the default view definition language since JSF 2.0.  Josh shows how to use Netbeans IDE to create Facelet Template view and then how to apply the template to a view. This section also covered how to reuse a  component and its resources in any JSF view within the application by utilizing the facelets ui:component tag.  Also it covered handling variable length data with ui:repeat tag I particularly liked the section on debugging the view layout with ui.debug tag

Chapter 5: Java Server Faces Standard components

This chapter focusses on JSF component library and shows how to use external component libraries. It showed how to use Bean validation with JSF. Using a concrete example of subscribing to a news letter the chapter demonstrates various topics layering one on the other. This is one of the best chapters of the book.

Chapter 6: Advanced Java Server Faces and Ajax

This chapter delves into using JSF components with Ajax. It covers Ajax validation using f:ajax tag to add immediate validation  to JSF views thus avoiding the need for JavaScript for client side validation and allows asynchronous validation between the client and server logic in the JSF managed bean. Additionally it covers how to make partial page updates which was very interesting. This chapter demonstrates how to listen for system life cycle events such as PreDestroyApplicationEvent and PostConstructApplicationEvent. Another example is how to get periodic updates to pages without doing a manual refresh using the poll component. The section on  developing JSF components containing HTML5 was very good read which demonstrated how to create an HTML5 video component  from a JSF composite component. It also covers a flow instance which is a new feature in JSF 2.2 allowing sharing of information between the views of a flow instance.  Overall I found that this book was a great source of information for JavaEE developers wanting to develop component based user interfaces running on browsers for rapid development and deployment. I would highly recommend this book to anyone who wishes to know about JavaServer Faces from scratch as well as advanced users  who want to get more acquainted with the nuts and bolts of newer features.
RESTful Java Patterns and Best Practices is the second book which I have worked on and is recently published. 

Overview

The convergence of social networking, cloud computing, and era of mobile applications creates a generation of emerging technologies that allow different networked devices to communicate with each other over the Internet. As the technology landscape evolves, today  

JDK 8 introduced a lot of new features and improvements in the platform from Lamda expressions, Stream collection types, Functional interfaces, Type annotations, Nashorn etc. Guava library from Google provided some support for functional programming idioms prior to JDK 8. I have been using Guava for some of my projects. So here is a small write up on how new functionality added in JDK 8 makes it possible to achieve standardized way to functionality offered by Google's Guava. This article further highlights similarities and differences between the two APIs and was inspired by thisdiscussion on google groups. The following table shows some of the API which I will cover in detail wrt. Guava and JDK 8

FunctionalityGuavaJDK 8
Predicateapply(T input)test(T input)
Combining predicates Predicates.and/or/notPredicate.and/or/negate
SupplierSuplier.getSupplier.get
Joiner/StringJoinerJoiner.join()StringJoiner.add()
SettableFuture/CompletableFutureSettableFuture.set(T input)CompletableFuture.complete(T input)
OptionalOptional.of/ofNullable/emptyOptional.of/fromNullable/absent

Source Code

The following code snippets are part of a complete sample available at https://github.com/bhakti-mehta/samples/tree/master/jdk8-and-guavaFor the sake of simplicty, I have a simple sample which has a collection of people's data. We start with a simple POJO Person as shown below for both the JDK 8 and Guava cases

 public class Person { private String firstName; private String lastName; private int age; private Optional suffix; ... ... 

As shown in the above snippet the Person class has fields like firstName, lastName, age, an Optionalsuffix and getters and setters for these.

1.0 Predicates

A Predicate is a boolean valued function for an argument. Now we will define Predicate in Guava and JDK 8 and show how to get the list of people whose age is over 30. The following snippet shows how to use a Predicate which has an apply (Person input) method that takes a Personobject as input and validates if the age of the person is above 30

1.1 Predicate with Guava

Here is the code showing how to use com.google.common.base.Predicate

 final List persons = Person.createList(); final Predicate ageOver30 = new Predicate() { public boolean apply(Person input) { return input.getAge() > 30; } }; Collection filteredPersons = Collections2.filter(persons, ageOver30); 

The above snippet returns a Collection that satisfy that predicate ageOver30 by using Collections2.filter()method which takes a Predicate as an argument.

1.2 Predicate with JDK8

Here is a snippet of how to achieve the same behaviour using java.util.function.Predicate The Predicate has a test method what checks for the ageOver30Predicate

 final List persons = Person.createList(); final Predicate ageOver30 = new Predicate() { public boolean test(Person person) { return person.getAge() > 30; } }; Stream filteredPersons = persons.stream().filter( ageOver30); 

The above snippet transforms (List) into a Stream with the stream() method on the Collection interface. The filter() method takes the ageOver30Predicate and returns a stream that satisfies the criteria.

2.0 Combining Predicates

Predicates can be combined with other predicates. For example in our sample we need to find a list of people whose age is over 30 and whose name begins with "W", we can achieve this functionality with creating two Predicates

  • ageOver30
  • nameBeginsWith

Next we combine the 2 predicates by calling the andmethod with these two predicates.

2.1 Combining Predicates with Guava

Here is a code snippet with Guava predicate class which defines 2 predicates ageOver30 and nameBeginsWith

 final List persons = Person.createList(); final Predicate ageOver30 = new Predicate() { public boolean apply(Person input) { return input.getAge() > 30; } }; final Predicate nameBeginsWith = new Predicate() { public boolean apply(Person person) { return person.getLastName().startsWith("W"); } }; Collection filteredPersons = Collections2.filter(persons, Predicates.and(ageOver30, nameBeginsWith)); 

The above snippet returns a filtered list from the Collections2.filter() method by passing the combined predicates Predicates.and(ageOver30,nameBeginsWith)

2.2 Combining Predicates with JDK 8

Here is the same functionality using java.util.function.Predicate.and/or/negate

 public Stream getMultiplePredicates() { final List persons = Person.createList(); final Predicate ageOver30 = new Predicate() { public boolean test(Person person) { return person.getAge() > 30; } }; final Predicate nameBeginsWith = new Predicate() { public boolean test(Person person) { return person.getLastName().startsWith("W") ; } }; Stream filteredPersons = persons.stream().filter( ageOver30.and(nameBeginsWith)); return filteredPersons; } 

The above snippet returns a stream by filtering the combined ageOver30.and(nameBeginsWith))predicates.

3.0 Supplier

Supplier is a functional interface that encapsulates an operation and allows lazy evaluation of the operation. It supplies objects of a particular type.

3.1 Supplier in Guava

Here is a snippet of how to use com.google.common.base.Supplierin Guava

 public int getSupplier() { Supplier person = new Supplier() { public Person get() { return new Person("James", "Sculley", 53,Optional.of("Sr")); } }; return person.get().getAge(); } 

As seen in the above snippet we create a new Supplier and the get() method returns a new instance of Person.

3.2 Supplier in JDK 8

The following code shows how to create a java.util.function.Supplierwith Lamda expressions in JDK 8.

 public int getSupplier() { final List persons = Person.createList(); Supplier anotherone = () -> { Person psn = new Person("James", "Sculley", 53, Optional.of("Sr")); return psn; }; return anotherone.get().getAge(); } 

As shown in above snippet, similar to the Guava case, we create a new Supplier and the get() method returns a new instance of Person.

4.0 Joiner/StringJoiner

A Joiner in Guava/ StringJoiner in JDK8 joins text together separated by delimiters.

4.1 Joiner in Guava

Here is an example of a Joiner in Guava which joins the various string delimited by ';'

 public String getJoiner() { Joiner joiner = Joiner.on("; "); return joiner.join("Violet", "Indigo", "Blue", "Green", "Yellow", "Orange", "Red"); } 

4.2 StringJoiner in JDK 8

The following snippet shows how the equivalent functionality in JDK 8 is:

 public String getJoiner() { StringJoiner joiner = new StringJoiner("; "); return joiner.add("Violet").add( "Indigo").add( "Blue").add( "Green") .add("Yellow").add( "Orange").add( "Red").toString(); } 

5.0 java.util.Optional

java.util.Optionalis a way for programmers to indicate that there may have been a value initially, that is now set to null or no value was ever found.

5.1 Optional in Guava

Here is a sample of com.google.common.base.Optional

  • Optional.of(T) :Make an Optional containing the given non-null value, or fail fast on null.
  • Optional.absent(): Return an absent Optional of some type.
  • Optional.fromNullable(T): Turn the given possibly-null reference into an Optional, treating non-null as present and null as absent.

Here is the code which declares the suffix of a Person as Optional

 Optional suffix = Optional.of("Sr") 

5.2 Optional in JDK8

  • Optional.of(T); Returns an Optional with the specified present non-null value.
  • Optional.ofNullable(T);Returns an Optional describing the specified value, if non-null, otherwise returns an empty Optional
  • Optional.empty(); Returns an empty Optional instance. No value is present for this Optional.

Here is the code which declares the suffix of a Person as Optional

 Optional suffix = Optional.of("Sr") 

6.0 SettableFuture in Guava/ CompletableFuture in JDK 8

These extend the Future and provide asynchronous, event-driven programming model in contrast to the blocking nature of Futurein java. SettableFuture is similar to CompletableFuture in JDK 8 which can help to create a Future object for an event or a task which will occur. Code calling future.get() will block forever. When the asynchronous task finishes execution it calls future.set(). Now all the code blocking on Future.get() will get the details.

6.1 SettableFuture in Guava

Here is a simple case demonstrating this functionality in Guava and JDK8

 public SettableFuture getSettableFuture() { final SettableFuture future = SettableFuture.create(); return future; } public void handleFutureTask(SettableFuture sf) throws InterruptedException { Thread.sleep(5000); sf.set("Test"); } 

In the above snippet we create a new SettableFuture in default state using SettableFuture.create(). The set() method sets the value for this future object.

6.2 CompletableFuture in JDK8

The following code shows how the equivalent functionality is achieved with CompletableFuture in JDK 8.

 public CompletableFuture getCompletableFuture() { final CompletableFuture future = new CompletableFuture<>(); return future; } public void handleFutureTask(CompletableFuture cf) throws InterruptedException { Thread.sleep(5000); cf.complete("Test"); } 

As shown in the above snippet we create a CompletableFuture and invoke the complete method to set the value for this future object. The above samples showed how JDK 8 standardizes in the platform and augments to some of the functionality with Guava library aimed to provide with JDK7. JDK 8 has been a great leap in terms of the newer capabilities it provided. Guava will definitely provide additional improvements using the standardized API. Follow @bhakti_mehta

There is so much potential in extracting, processing and synthesizing the the multi faceted, realtime data that can be mined from social sites. Mining the Social Web by Mathew A. Rusell covers these topics scrupulously. Here is my detailed review of the book
 

Chapter 1: Mining Twitter, Exploring Trending topics, Discovering what users are talking about

This is an informative chapter which covers from the basics of how to create applications with Twitter, authorizing an application to access Twitter data, looking for trends, searching for tweets and how to extract the text, screen names and hashtags from the tweets. It also covers how to compute the lexical diversity of the tweets and visualizing the data with histograms. It covers matplotlib, prettytable and other Python packages. I have used Twitter APIs extensively and found this chapter very useful and well written. 

Chapter 2 : Mining Facebook: Analyzing Fan Pages, Examining Friendships, and More

This chapter covers the developer tools for Facebook, Graph API explorer, using the API over HTTP, Open Graph Protocol, examining friendships and analyzing social graph connections. It demonstrates how to use facebook-sdk package to make FQL queries. Other examples include computing overlapping likes in social network, analyzing mutual friendships and visualizing with D3.js. This chapter makes it apparent that there are many exciting possibilities for what can be done with social data, and that there  

One of the newer features introduced in JAX-RS 2.0 is the support for validating resource classes with Bean Validation Bean Validation support comes in Jersey 2.x by adding jersey-bean-validation module to the class-path. The following sample shows how to use Bean Validation with JA ]]> Type:Expresso,Blended,Chocolate,Brewed Size: Small, Medium, Large, X Large Preference: Regular, Non Fat, Soy Milk, Whipped CreamThe following code shows how the Coffee resource looks

 /** * * A simple JAX-RS resource which demonstrates Bean Validation * @author Bhakti Mehta * */ @Path("v1/coffees") public class CoffeesResource { @Context javax.ws.rs.core.UriInfo uriInfo; @GET @Path("{order}") @Produces(MediaType.APPLICATION_XML) @NotNull(message="Coffee does not exist for the order id requested") public Coffee getCoffee( @PathParam("order") int order) { return CoffeeService.getCoffee(order); } @POST @Consumes(MediaType.APPLICATION_XML) @Produces(MediaType.APPLICATION_XML) @ValidateOnExecution public Response addCoffee(@Valid Coffee coffee) { int order = CoffeeService.addCoffee(coffee); return Response.created(uriInfo.getAbsolutePath()) .entity("" + order + "").build(); } } 

As you can see in the preceeding snippet there is a GET and POST method. The @GET annotated method getCoffee() checks if a coffee exists for the PathParam order and returns it else returns null. There is an @NotNull annotation for the method to provide a message incase there is no coffee by the order specified The @POST annotated addCoffee() method adds a new order for the coffee. Notice the @Validannotation for the request parameter coffee. It indicates to validate the object coffee The next snippet shows how the Coffee object looks like.

 @XmlRootElement public class Coffee { @VerifyValue(Type.class) private String type; @VerifyValue(Size.class) private String size; @NotNull private String name; private double price; private int order; ....///getters and setters } 

I have two Enum Size and Type associated with the Coffee. Each of the enums are annotated with @VerifyEnum() annotation. The @VerifyValueis a custom constraint I introduced to validate any Enum object. It will be covered below. The following snippet shows how the Size and Type enums.

 public enum Size { Small("S"), Medium("M"), Large("L"), ExtraLarge("XL"); private String value; private Size(String v) { this.value = v; } public String getValue() { return value; } } 
 public enum Type { Expresso, Brewed, Blended, Chocolate ; } 

The following code shows how I have a custom bean validation constraint called VerifyValuewhich verifies if the value for the Enum is valid

 @Retention(RUNTIME) @Target({FIELD, METHOD}) @Documented @Constraint(validatedBy = VerifyValueValidator.class) public @interface VerifyValue { String message() default "Value specified is not valid"; Class[] groups() default {}; Class[] payload() default {}; Class> value(); } 

Here is the implementation for the VerifyValueValidator

 /** * Implementation for the user-defined constraint annotation @VerifyValue * This is a general purpose validator which verifies the value for any enum * If an Enum object has a getValue() method it will validate based on the value of the Enum * else will use the EnumConstant * * @author Bhakti Mehta */ public class VerifyValueValidator implements ConstraintValidator { Class> enumClass; public void initialize(final VerifyValue enumObject) { enumClass = enumObject.value(); } public boolean isValid(final Object myval, final ConstraintValidatorContext constraintValidatorContext) { if ((myval != null) && (enumClass != null)) { Enum[] enumValues = enumClass.getEnumConstants(); Object enumValue = null; for (Enum enumerable : enumValues) { if (myval.equals(enumerable.toString()) ) return true; enumValue = getEnumValue(enumerable); if ((enumValue != null) && (myval.toString().equals(enumValue.toString()))) { return true; } } } return false; } /** * Invokes the getValue() method for enum if present * @param enumerable The Enum object * @return returns the value of enum from getValue() or * enum constant */ private Object getEnumValue(Enum enumerable) { try { for (Method method: enumerable.getClass().getDeclaredMethods()) { if (method.getName().equals("getValue")) { return method.invoke(enumerable); } } } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } return null; } 

The isValid() method looks for all the Enum objects if its value matches that specified in the request and returns true else returns false. There is no straightforward method to get an enum from a value specified so I have implemented the getEnumValue() method. The EnumSet will return the EnumConstants but not an Enum based on its value.The getEnumValue() method uses reflection to invoke the getValue()method for the Enum. There can be further optimization to cache the enum based on the value in a HashMap so future references can be looked up from the map first. Here is the Application class which has the following properties set

 public Map getProperties() { Map properties = new HashMap() ; properties.put(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true); return properties; } 

The ServerProperties.BV_SEND_ERROR_IN_RESPONSE is a Bean Validation (JSR-349) support customization property that will allow the validation errors to be sent back in the response Complete sample can be downloaded from https://github.com/bhakti-mehta/samples/tree/master/jax-rs-bean-validation

Running and testing the sample

Install GlassfFish 4.0 Build the sample using mvn install Deploy the war to GlassFish

 Using curl to the URL http://localhost:8080/jax-rs-bean-validation/v1/coffees curl -X POST -d @test.xml http://localhost:8080/jax-rs-bean-validation/v1/coffees --header "Content-Type:application/xml" 

This will give you an order id for the coffee created. Here is the sample input for the POST request in the test.xml file <coffee> <type>Expresso</type> <size>XL</size> <name>Cafe Latte</name> <price>6.50</price> </coffee>

 Send a GET request to http://localhost:8080/jax-rs-bean-validation/v1/coffees/ You will get a validation error incase there is no coffee with the order specified 

You can send some invalid values in the Type or the Size and see the validation errors.

Jersey 1.1.x and Bean Validation

In Jersey 1.x (RI for JAX-RS 1.1) Bean Validation is not supported by default. With Jersey 1.x I have enabled bean validation for resource parameters by using Aspect oriented Programming by implementing a MethodInterceptorThis feature enables us to write code that is executed each time a matching method is invoked.

 /** * Intercepts resource methods before they are invoked to check for * parameters annotated with @Valid annotation * and validates the method arguments * * Incase the argument is not valid an appropriate exception with the error * message underlying the cause of constraint violation errors is thrown * @author Bhakti Mehta * */ public class ValidationInterceptor implements MethodInterceptor { private final Validator validator public static IsValidable isValidable() { return new IsValidable(); } public ValidationInterceptor() { validator = Validation.buildDefaultValidatorFactory().getValidator(); } @Override public Object invoke(MethodInvocation invocation) throws Throwable { Method method = invocation.getMethod(); Object argument = null; Annotation[][] parameterAnnotations = method.getParameterAnnotations(); if (parameterAnnotations != null) { for (int i = 0; i < parameterAnnotations.length; i++) { Annotation[] annotationsArray = parameterAnnotations[i]; for(Annotation annotation : annotationsArray){ if (annotation instanceof Valid) { argument = invocation.getArguments()[i]; } } } } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("\n"); if (argument != null ) { Set> violations = validator.validate(argument); if (!violations.isEmpty()) { for(ConstraintViolation violation : violations) { stringBuilder.append(violation.getMessage()).append("\n"); } throw new ConstraintViolationException( String.format("Error when validating method %s due to %s", method.getName(), stringBuilder.toString()) ,violations); } } return invocation.proceed(); } } class IsValidable extends AbstractMatcher { @Override public boolean matches(Method method) { Class[] interfaces = method.getDeclaringClass().getInterfaces(); if (interfaces.length > 0) { Class resource = interfaces[0]; try { Method resourceMethod = resource.getMethod(method.getName(), method.getParameterTypes()); return Modifier.isPublic(resourceMethod.getModifiers()); } catch (NoSuchMethodException nsme) { return false; } } else { return false; } } } 

The above snippet shows the implementation of a MethodInterceptor On the invoke() method we get an instance of the MethodInvocation object. As you can see in the above snippet we get the Method from the invocation.getMethod() call and iterate through the parameter annotations for the method and check if there is an @Valid annotation If a param has an annotation with @Valid we get the argument from the methodInvocation using invocation.getArguments()[i] Incase the argument is not Null we call the validator.validate(argument) For all the ConstraintViolations we throw a ConstraintViolationException with the list of violations Finally we call through the underlying method by calling invocation.proceed()The following code shows how to inject the ValidationInterceptor so it works with Jersey 1.1.x

 public class MyConfigurator extends JerseyServletModule { @Override protected void configureServlets() { MethodInterceptor validationInterceptor = new ValidationInterceptor(); requestInjection(validationInterceptor); bindInterceptor(Matchers.any(), ValidationInterceptor.isValidable(), validationInterceptor); 

The above code shows how we inject interceptors. Another solution provided which can be useful is using ResourceFilterFactory as mentioned here However in my case I needed to know the arguments of the method and validate them and I found the AOP method interceptorworked well.

Summary

This blog showed how to use Bean Validation with JAX-RS 2.0. A complete sample is available for download from https://github.com/bhakti-mehta/samples/tree/master/jax-rs-bean-validation Additionally for people who cannot upgrade to JAX-RS 2.0 we covered how to support Bean Validation using two approaches 1. AOP with method interceptors 2. Using RequestFilterFactory and RequestFilters Hope this was helpful.

Developing RESTful Services with JAX-RS 2.0, WebSockets, and JSON is the new book which Masoud Kalali and I have worked on and recently published. https://www.java.net//sites/default/files/book-image.JPG As the technology landscape moves focus towards smaller devices, the need for building scalable, flexible, lightweight, and real-time communications-based applications grows. HTML 5 and Java EE 7 provide a new synthesis of technologies that demonstrate tremendous scope and potential in areas of device independence, asynchronous communication, interoperability, and portability. Newer technologies in JavaEE 7 like WebSockets, JSON , asynchronous invocation capable components keep the platform innovative and improve developer productivity. Developing RESTful Services with JAX-RS 2.0, WebSockets, and JSON is a practical, hands-on guide that provides you with clear and pragmatic information to take advantage of the real power behind HTML5 and Java EE technologies. This book covers 
  • Developing RESTful Web Services using the JAX-RS 2.0 API
  • Building applications with the JavaScript and Java Client API for WebSockets and Server-Sent Events
  • Understanding security, fault tolerance with WebSockets and Server-Sent Events
  • Producing, parsing, and manipulating JSON data with the help of standard JSON API
  • Best practices in building applications with WebSockets, Server-Sent Events, and JAX-RS 2.0
  • Using the aspects of asynchronous programming to improve scalability
The last chapter of the book includes design and development of two complete applications: one event based application based on Twitter API and other library based application which will integrate the different JavaEE 7 technologies together. For more information you can check here.  
Silicon Valley Code Camp is one of the best known secrets and one of the best organized conferences in the Bay Area.  I have the pleasure to speak at this conference for the past two years and am amazed at its growing popularity. Here are some statistics for this year 4500 registrations and registration was closed230 sessions The Code Camp consists of these points:
  • By and for the developer community
  • No Charge To Attendees
  • Never occurs during working hours
  •   Sessions range from informal chalk talks to presentations. There was an awesome kids track with young speakers like Shadaj Laddad on Scala,  talks like Python programming for kids to Pacman in 50 minutes. My good friend Arun Gupta led a track on Minecraft modding which was a huge success.    Here are some images from the conference this year.https://www.java.net//sites/default/files/photo_1.JPGhttps://www.java.net//sites/default/files/photo-38.JPG What does it take to fuel 4500 attendees? 400 pizzas and 1000 subs https://www.java.net//sites/default/files/photo_4.JPG  https://www.java.net//sites/default/files/photo_3.JPG  6 dedicated parking lots and yet overflowing https://www.java.net//sites/default/files/photo_2.JPG These are the slides for my sessions this year
  • Fight the empire lightweightly with HTML5, WebSockets, Server-Sent Events and others
  • Think Async
  • I would like to thank Peter Kellner and his team for putting together such a wonderful show.   Also thanks to the sponsors as well as Foothill College for supporting this effort. Till next year ...
    I will be presenting the following sessions at Silicon Valley Code Camp 2013. For those in the Bay Area, Silicon Valley Code Camp is on Oct 5,6 2013 in Foothill College, Los Altos. It is a very well organized conference by the developers for the developers. This year has 232 sessions and 4500 registrations and am always amazed at the way Peter Kellner and his team pull this off! These are my talks which I am looking forward to present. 

    Fight the empire lightweightly with HTML5, WebSockets, ServerSentEvents & others

    Sat Oct 5 at 5pm Based on the Star Wars theme, this session focuses on how Java EE 7 provides an extensive set of new and enhanced features to support standards such as HTML5, WebSocket, and Server-sent events, among others. The session shows how these new features are designed and matched to work together for developing lightweight solutions matching end users  
    Glassfish 4.0 is released. This is the reference implementation for Java EE 7 and focusses on HTML 5 and improving developer productivity. You can download the bits from here https://glassfish.java.net/download.html Apart from the Java EE 7 support in GlassFish 4.0 there have been numerous other areas where Glassfish 4 has provided lots of improvements and innovation [url=https://twitter.com/MartinJMares/]Martin Mares[/url] ,[url=https://blogs.oracle.com/kasso/] Chris Kasso[/url] and I have been working on the Admin Command Framework. These are some new enhancements that were added to Glassfish 4.0. [b]o Support for Progress status using Server Sent Events[/b] [b]o Job Management support[/b] [h2]Support for Progress status in commands using Server Sent Events.[/h2] This section will cover the newly introduced [b]@Progress[/b] annotation. We will walk through the basic usages of Progress API. Next we will see how ServerSentEvents fits in with the Progress API. [h3] Progress API in Glassfish 4.0[/h3] Consider some long running commands say start-cluster. It would be useful to be notified about the progress of the command as it is executing. To facilitate support for Progress status in AdminCommands a new annotation [b]@Progress[/b] is added. Any command which wants to use the Progress status API can be annotated with [b]@Progress[/b] The ProgressStatus object can be obtained from the [b]AdminCommandContext[/b]. The Progress API can be used to specify the total steps for execution. Once the total steps are known the percentage can be computed. Additionally the ProgressStatus API takes a message that can be added as the command progresses like Installing, Parsing... etc. As the command is executing, the progress can be updated by specifying the steps and the message to be sent to the client. 
    @Progress
    public class SomeCommand implements AdminCommand {
     
      public void execute(AdminCommandContext context) {
    
           ProgressStatus ps = context.getProgressStatus();
           ps.setTotalStepCount(3);
           ...
           ..
           ps.progress(1, "Parsing files..");
    
    The above snippet shows the [b]@Progress[/b] annotation on the command. It also demonstrates how to get the [b]ProgressStatus[/b] object from the [b]AdminCommandContext[/b]. It shows how to use the[b] ProgressStatus.progress()[/b] method to specify the number of steps taken and a message to be emitted. Here is the Progress Status API which command developers can read for detailed information. http://grepcode.com/file/maven.java.net/content/groups/promoted/org.glassfish.main.common/glassfish-api/4.0-b78/org/glassfish/api/admin/ProgressStatus.java [h3] Using ServerSentEvents to emit progress[/h3] Server-Sent Events (SSE) is a technology for providing push notifications from servers to clients once an initial client connection has been established. For our case of long running commands which emits progress as it executes, the server can continuously sending the progress using Server Sent Events API. [h3]Definition of a ManagedJob[/h3] Any command which has progress information in it ie annotated with [b]@Progress[/b] or which is run with [b]--detach[/b] (See section below) option is known as a [b]ManagedJob[/b]. Each job has a job id associated with it. You can query the status of a [b]ManagedJob[/b] using [b]list-jobs[/b] command. [h2]How it fits together [/h2] 1. When a managed job is executed in GlassFish the REST client will open an SSE connection with header Accept: text/event-stream. 2. The command gets executed on a dedicated thread pool which is provided by the JobManager. 3. Once the channel of communication is established all the progress feedback is sent as Server Sent Events and the channel is kept open to keep sending progress as it occurs. 4. The Response is closed when the command finishes execution. [img=600x400]http://weblogs.java.net/sites/default/files/sse.png[/img] The above figure shows the interaction between the Server and the command which is annotated with @Progress executed by the client. The progress is sent via SSE and finally the ActionReport is sent once the command finishes execution. [h2]Job Management commands[/h2] These are newer commands which are introduced [list] [*]detach option to commands [*]attach command [*]list-jobs command [*] configure-managed-jobs [/list] [h3]detach option to commands [/h3] Any command can be run with [b]--detach[/b] option. This will give a job id associated with the command and the job is run in the background. You can then lookup the job using the [b]list-jobs[/b] command. (Similar to the jobs command in Unix) You can later attach to the job using the [b]attach[/b] command with the job id too and see the progress. [h3]attach command [/h3] The following image shows a sample command started by the client which emits progress status information. 1. Client 1 starts the sample command which has some progress information 2. The server executes the command and sends the progress to the client using ServerSentEvents. You can open another terminal for Client 2 and attach to the same job and see the same progress updates on both the clients. [img=500x300]http://weblogs.java.net/sites/default/files/image.png[/img] Fig 1. Multiple clients attaching to get progress via Server Sent Events. Bboth the terminals Client1 and Client2 are both getting the same set of progress related Server Sent Events at the same time. Even if one client kills using Ctrl C the other will still see the updates. [h3]list-jobs[/h3] The [b]list-jobs[/b] command can provide information regarding the jobs. It lists the job id, the name, the time the job was started, the state and the Exitcode. Here is a sample output of list-jobs command asadmin list-jobs NAME JOB ID TIME STATE EXIT CODE USER sample-command1 1 2013-02-05 14:11:24 COMPLETED SUCCESS admin You can even run list-jobs with a single job id 
    asadmin list-jobs 1
    NAME                         JOB ID   TIME                                STATE                EXIT CODE   USER  
    sample-command1   1            2013-02-05 14:11:24   COMPLETED   SUCCESS     admin 
    
    
    Using curl to get the data of the list-jobs 
    This will get the information of all jobs 
    curl  -vSs -H 'X-Requested-By foo' -X GET http://localhost:4848/management/jobs
    
    This will get the information of job whose id is 1
    curl  -vSs -H 'X-Requested-By foo' -X GET http://localhost:4848/management/jobs/id/1 
    
    [h3]configure-manage-jobs command[/h3] The [b]configure-managed-jobs[/b] command is used to clean up these [b]ManagedJobs[/b]. By default the job retention period is 24 hours. But using this command you can specify how long you want to keep the jobs. [h3]How you can contribute[/h3] Download GlassFish 4.0 from https://glassfish.java.net/download.html and try the newer features. Java EE 7 tutorial is here http://docs.oracle.com/javaee/7/tutorial/doc/home.htm You can file bugs using this link https://java.net/jira/browse/GLASSFISH Provide feedback at users@glassfish.dev.java.net.  
    GlassFish comes preconfigured with Apache Felix Gogo, which is an implementation of OSGi RFC 147, and is a proposed standard shell for OSGi environments. For Glassfish 4.0 there is no longer need to open a separate port to access the shell. The OSGi shell commands are integrated with asadmin, so you can now access the OSGi shell commands via asadmin tool. There is a remote command called osgi which accepts subcommands which are fed to the OSGi shell and their result returned via asadmin. This integration allows you to secure the OSGi commands using GlassFish admin credentials as well. If you have turned on  
    Masoud Kalali and I will be presenting a BOF at Javaone 2012 Server Sent Events, Async Servlet, Web Sockets and JSON; born to work together! This session focuses on how Java EE 7 provides extensive set of new and enhanced features to support standards like HTML5, WebSockets, and Server Sent Events among others. In this session we will show how these new features are designed and matched to work together for developing lightweight solutions matching end users high expectation from a web application  

    Jersey 2.0 has a lot of new features as mentioned by Marek here . One of the nice features which they have added is the Client and Server support for In an earlier entryServer Sent Eventsa> . Here is a sample which shows how we use the new Server Sent Event apis introduced in jersey 2.0. <a href="http://weblogs.java.net/blog/bhaktimehta/archive/2012/04/21/server-sent-events-sample-glassfish">In an earlier entry</a> we had shown Server Sent Events sample using the CDI, ServerSentEveEventChannel as an outgoing event message queue . @Path("twittersse") public class ServerSentEventsResource { static EventChannel eventChannel= new EventChannel(); @GET @Produces(EventChannel.SERVER_SENT_EVENTS) public EventChannel getMessage() { return eventChannel; } @POST @Consumes(MediaType.TEXT_PLAIN) public void sendMessage(String message) throws IOException { System.out.println("Sending " + message); eventChannel.write(new OutboundEvent.Builder().name("custom-message").data(String.class, message).build()); } } Here is the code for the Stateless Session bean which will get the data from Twitter and post to the ServerSentEventsResource class every 10 seconds. @Stateless @Named public class TwitterBean { private final static String SEARCH_URL = "http://search.twitter.com/search.json?q=glassfish&rpp=5&include_entities=true" + "&with_twitter_user_id=true&result_type=mixed"; private final static String TARGET_URI= "http://localhost:8080/jersey-sse-twitter-sample"; @Schedule(hour="*", minute="*", second="*/10") public void sendTweets() { Client client = ClientFactory.newClient(); try { WebTarget webTarget= client.target(new URI(TARGET_URI)) ; String message = getFeedData(); System.out.println("Posting message"); webTarget.path("twittersse").request().post(Entity.text(message)); } catch (URISyntaxException e) { e.printStackTrace(); } } Here is the code for the Servlet client which uses the EventSource apis to listen for the Server Sent Events and prints the information. When EventSource is created, it makes GET request to given URI and waits for incoming InboundEvents. Whenever any event is received, onEvent(InboundEvent) is called and listeners are notified I use the async support in Servlet 3.0. Also I am using json-lib apis to bind from JSON to Java. @WebServlet(name = "TestClient", urlPatterns = {"/TestClient"} ,asyncSupported=true) public class TestClient extends HttpServlet { private final static String TARGET_URI = "http://localhost:8080/jersey-sse-twitter-sample/twittersse"; private ExecutorService executorService; @Override public void init() throws ServletException { executorService = Executors.newFixedThreadPool(3); } @Override protected void service(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); try { final AsyncContext asyncContext = request.startAsync(); asyncContext.setTimeout(600000); asyncContext.addListener(new AsyncListener() { @Override public void onComplete(AsyncEvent event) throws IOException { } @Override public void onTimeout(AsyncEvent event) throws IOException { System.out.println("Timeout" + event.toString()); } @Override public void onError(AsyncEvent event) throws IOException { System.out.println("Error" + event.toString()); } @Override public void onStartAsync(AsyncEvent event) throws IOException { } }); Thread t = new Thread(new AsyncRequestProcessor(asyncContext)); t.start(); } catch (Exception e) { e.printStackTrace(); } } /** * This class will create the EventSource * and when the SSE are received will print the data * from the Inbound events */ class AsyncRequestProcessor implements Runnable { private final AsyncContext context; public AsyncRequestProcessor(AsyncContext context) { this.context = context; } @Override public void run() { Client client = ClientFactory.newClient(); client.configuration().register(OutboundEventWriter.class); context.getResponse().setContentType("text/html"); final javax.ws.rs.client.WebTarget webTarget; try { final PrintWriter out = context.getResponse().getWriter(); webTarget = client.target(new URI(TARGET_URI)); out.println("Glassfish tweets"); EventSource eventSource = new EventSource(webTarget, executorService) { @Override public void onEvent(InboundEvent inboundEvent) { try { //get the JSON data and parse it JSONObject jsonObject = JSONObject.fromObject( inboundEvent.getData(String.class, MediaType.APPLICATION_JSON_TYPE )); JSONArray jsonArray = (((JSONArray) (jsonObject.get("results")))); for (int i = 0; i Here is the Application class to register the JAX-RS resource ServerSentEventsResource public class MyApplication extends Application { Set> classes = new HashSet>() { { add(ServerSentEventsResource.class); add(OutboundEventWriter.class); }}; @Override public Set> getClasses() { return classes; } }  Here is the source code to try. You can build the maven project, download the latest glassfish bits from here and deploy the jersey-sse-twitter-sample.war You can see at http://localhost:8080/jersey-sse-twitter-sample/TestClient the Twitter updates start showing up. Note that this is a work in progress so apis may change.You can check for more Jersey related updates here and follow @gf_jersey on Twitter to get Jersey-related news. Last but not the least I would like to thank my very talented colleagues and friends Jakub Podlesak, Masoud Kalali, Rajiv Mordani and Jitendra Kotamraju for all their wonderful ideas and help. Thanks a lot!

    Loadbalancers can set thier cookies indicating which backend server can serve a user's requests and direct future requests to the same server. I was experimenting with session stickiness using apache, mod_proxy and Glassfish and here is a short summary of the steps I executed. Apache 2 is installed on Mac OSX in /etc/apache2 mod_proxy,mod_proxy_http, mod_proxy_ajp and mod_proxy_balancer comes as part of standard Apache 2.2+ distribution This link shows the layout of Apache HTTPD on different operating systems For the Mac OSX you can see the file layout as shown here

     ServerRoot :: /usr Primary Config Fle :: /etc/apache2/httpd.conf DocumentRoot :: /Library/WebServer/Documents ErrorLog :: /var/log/apache2/error_log AccessLog :: /var/log/apache2/access_log cgi-bin :: /Library/WebServer/CGI-Executables (empty by default) binary :: /usr/sbin/httpd start/stop :: /usr/sbin/apachectl (start|stop|restart|fullstatus|status|graceful|graceful-stop|configtest|help) 

    These are the following steps I followed to configure sticky sessions. edit the /etc/apache2/httpd.conf to add these following lines

      BalancerMember http://localhost:28080 route=i1 BalancerMember http://localhost:28081 route=i2 BalancerMember http://localhost:28083 route=i3  ProxyPreserveHost On ProxyPass /clusterjsp balancer://hacluster/clusterjsp stickysession=JSESSIONID  SetHandler balancer-manager Order Deny,Allow Allow from all  

    Here I have added 3 BalancerMembers which are 3 glassfish instances I have created. I have also enabled the balancer-manager support using the above lines with Location /balancer-manager I am working with the glassfish 4.0 installation from the trunk but this should work with any Glassfish 3.x release. This is a very simple setup with 3 instances.

     cd $GF_HOME/bin asadmin start-domain asadmin create-cluster c1 Create 3 instances asadmin create-local-instance --cluster c1 i1 asadmin create-local-instance --cluster c1 i2 asadmin create-local-instance --cluster c1 i3 asadmin start-cluster c1 asadmin deploy --target c1 clusterjsp.ear The javaee samples can be downloaded from http://glassfish-samples.java.net/, I have attached the ear in the zip file below asadmin create-system-properties --target i1 INSTANCE=i1 asadmin create-system-properties --target i2 INSTANCE=i2 asadmin create-system-properties --target i3 INSTANCE=i3 asadmin create-jvm-options --target c1 -DjvmRoute=\${INSTANCE} Note the values for the system properties INSTANCE i1 and i2 and i3 are the same as what is mentioned in the route element of the httpd.conf above 

    Now start apache2

     sudo su /etc/apache2/apachectl start 

    On the browser send a get request to http://localhost/clusterjsp/HaJsp.jsp You can see the http headers using Chrome->View->Developer Tools ->Network tab JSESSION_ID added to Response You will see the Set-Cookie header in the response has the JSESSION_ID appended which points to i2 You can Reload the page and see future requests are directed to the instance i2 Sticky sessions You can also experiment with failover by stopping one of the instances in which case the request gets directed to a new server and session affinity starts with that server. You can also access load balancer manager by using a Web browser to access the page http://localhost/balancer-manager

    Introduction

    Server-Sent Events (SSE) is a standard describing how servers can initiate data transmission towards clients once an initial client connection has been established. It is commonly used to send message updates or continuous data streams to a browser client and designed to enhance native, cross-browser streaming through a JavaScript API called EventSource, through which a client requests a particular URL in order to receive an event stream.

    Sample

    The sample demonstrates a simple example of SSE. Here we have a servlet which periodically polls for Twitter information and pushes the data to the clients using Server Sent Events. This samples showcases a JavaEE6 application that uses CDI,ServerSentEventHandler and ServerSentEventHandlerContext apis along with twitter search apis and javascript client code.

    Code Snippets

    Here is the code for the ServletContextInitializer. There is a Timer which gets the feeds periodically

     public class SSEServletContextListener implements ServletContextListener { @Inject TwitterFeedBean tfs; private final int time = 60; @Override public void contextInitialized(ServletContextEvent servletContextEvent) { ServletContext servletContext = servletContextEvent.getServletContext(); try{ // create the timer and timer task objects Timer timer = new Timer(); TwitterTimerTask task = new TwitterTimerTask(tfs); timer.schedule(task, 0, 1000 * time); // save our timer for later use servletContext.setAttribute ("timer", timer); } catch (Exception e) { servletContext.log ("Problem initializing timer task every "+ time +" seconds: " + e.getMessage ()); } } @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { ServletContext servletContext = servletContextEvent.getServletContext(); Timer timer = (Timer)servletContext.getAttribute ("timer"); if (timer != null) timer.cancel(); servletContext.removeAttribute ("timer"); } class TwitterTimerTask extends TimerTask { TwitterFeedBean bean; TwitterTimerTask(TwitterFeedBean t) { this.bean = t; } public void run() { try { bean.getFeeds(); } catch (IOException e) { e.printStackTrace(); } } } } 

     

    Here is the TwitterHandler which is a ServerSentEventHandler

     /** * TwitterHandler class which will send messages using Server Sent Events * * @author Bhakti Mehta */ @ServerSentEvent("/twittersse") public class TwitterHandler extends ServerSentEventHandler { @Override public void onConnected(ServerSentEventConnection client) { super.onConnected(client); } public void sendMessage(String data) { System.out.println("Handler="+this+" Sending data="+data); try { connection.sendMessage(data); } catch(IOException ioe) { // May be client is already disconnected. Just close it try { connection.close(); } catch(Exception e) { //ignore if the connection close threw an exception } } } 

    Here is the TwitterFeedBean which gets the data from the Twitter search url

     @Named @ApplicationScoped public class TwitterFeedBean { @Inject @ServerSentEventContext("/twittersse") ServerSentEventHandlerContext sc; final private String SEARCH_URL = "http://search.twitter.com/search.json?q=glassfish&rpp=5&include_entities=true" + "&with_twitter_user_id=true&result_type=mixed"; public TwitterFeedBean() { } public void getFeeds() throws IOException { for(TwitterHandler handler : sc.getHandlers()) { handler.sendMessage(composeMessage()); } } private String composeMessage() { return getFeedData(); } private String getFeedData() { StringBuilder sb = new StringBuilder(); try { URL twitter = new URL(SEARCH_URL); URLConnection yc = null; yc = twitter.openConnection(); BufferedReader in = new BufferedReader( new InputStreamReader( yc.getInputStream())); String inputLine; while ((inputLine = in.readLine()) != null) { System.out.println("Input line" + inputLine); sb.append(inputLine) ; } in.close(); return sb.toString(); } catch (IOException e) { e.printStackTrace(); } return new String("Error in getting data from the feeds ") ; } } 

    Finally here is the app.js which will create the EventSource. It also parses the JSON feeds

     var network = function (eventSource) { return { initialize: function() { var url = 'http://' + document.location.host + '/sse-twitter-sample/twittersse'; eventSource = new EventSource(url); eventSource.onmessage = function (event) { var feeds = event.data.toString(); console.log(feeds); var theNewParagraph = document.createElement('p'); var theBreak = document.createElement('br'); theNewParagraph.setAttribute('title','The feeds'); var data = JSON.parse(feeds); var theText; var divTag ; var tweetInfo ; // Before we continue we check that we got data if(data !== undefined) { for (var k = 0;k To run the sample deploy the sse-twitter-sample.war to the latest nightly of glassfish 4.0 and you can run http://localhost:8080/sse-twitter-sample/ You may have to wait for a minute before the feeds start appearing. Also since this is a sample to stop the timer you should undeploy the application otherwise it will keep getting the tweets.. Jitu has another sample here Note this is a work in progress so apis may change.

     We are pleased to announce the release of Glassfish 3.1.2 . 

    These are the highlights of some of the main features in Glassfish 3.1.2

    Main Features

    • Improved Administration Console with better startup time and option to load in background after server startup. [blog]
    • Improved clustering with new DCOM Support for Windows (as an alternative to SSH for remote management of GlassFish instances) and Non-Multicast clustering.
    • Improved EclipseLink integration with EclipseLink MOXy support and TopLink Grid support (Coherence as 2nd level data cache)
    • WebSocket (RFC 6455) Support
    • Transaction recovery using database (in addition to the existing file system support)
    • Improved Security (secure admin requires password, Oracle GlassFish Server secure by default with new password required be set during installation or on first use), and
      SSL Encrypted traffic between the Domain Administration Server and remote instances
    • NetBeans 7.1.1 ships with GlassFish Server 3.1.2

    As you can see the newly released Netbeans 7.1.1 ships with Glassfish 3.1.2.

    We have added 3 new samples which will work out of the box using Netbeans 7.1.1 and Glassfish 3.1.2.

    This blog talks about the new samples.

    To download Netbeans 7.1.1 go to http://netbeans.org/downloads/index.html Choose the Javaee supported technology

    Once Netbeans is installed you can try the samples by clicking File->New Project->Samples->JavaEE

     Netbeans projects

    You will see 3 new samples which are introduced in Netbeans 7.1.1

    1.Embedded Glassfish

    This is a simple maven sample which shows the Embedded API in Glassfish 3.1.2 and demonstrates

            1. Start/stop GlassFish Server
            2. Deploy & Undeploy an application
            3. Scattered Archive
            4. Running asadmin commands from CommandRunner

    You can right select the sample as shown above right click and Click Build. It will download the maven dependency  glassfish-embedded-all jar.

    Under the Source Packages you can see the embedded.telephonedirectory.client and embedded.telephonedirectory.server packages
    The embedded.telephonedirectory.server has few JPA entities defined   and a PersistenceManager CDI bean.
    The embedded.telephonedirectory.client has all the code which shows how to use the embedded apis in Glassfish. You can see we define an http-listener,
    ?then the JDBC pool and resource required for the application is created, the application is deployed using org.glassfish.embeddable.Deployer API.
    To access the application launch the URL in the bowser http://localhost:9590/td

     Once the user finishes accessing the application type quit in the Tasks panel, the application is undeployed and embedded glassfish is stopped.

    2.EjbContainer sample in Glassfish

    This sample demonstrates the use of Maven to test EJB's using the standard EjbContainer support in Glassfish 3.1.2.

    Open the project in Netbeans and right click and click Build.
    Under the Source Packages tab you will see the org.glassfish.embedded.tempconverter package and see a StatelessSession bean called TemperatureConverter
    which does basic conversion from Farenheit to Celcius and vice versa.
    Under the Test Packages tab you will see the TemperatureConverterTest.java which is a simple junit test which


    1. Creates the EjbContainer
    2. Gets the Context object and does a lookup for the TemperatureConverterBean
    3. Invokes the methods on the TemperatureConverterBean

     3.Application scoped resources sample in Glassfish

    This is a simple sample which shows Application scoped resources in Glassfish. You can right click and click on Run to run this project.

    When you open the project you will see ApplicationScopedResources-app-client and ApplicationScopedResources-ejb modules.

    The ApplicationScopedResources-ejb module defines a StatelessSessionBean HelloBean which takes in a DataSource
    and does a lookup and returns the name of the  datasource or the default if it does not find any matching datasource.

    The main file of interest is the glassfish-resources.xml which you can see under the Files tab which is next to the Projects tab.
    You can see it the jdbc-resource java:app/app-scoped-resource in  java:app : namespace which is shared by all components, modules in an application
    (eg: application-client, web component, ejb component in an application, .ear). The application client looks for the "java:app/app-scoped-resource and prints 
    it since the application client is part of the ear  it can access it.

    Please try these samples in Netbeans 7. 1.1.and give us your feedback. Also go ahead download and try Glassfish 3.1.2 and we look forward to hear from you!

    References