24 September 2012

ServerSent-Events on WebLogic Server

In addition to the WebSocket support we've added into the next major release of WebLogic Server (version 12.1.2  with all usual caveats with respect to release timeframes, no guarantee, etc.) we've also added support for the HTML5 ServerSent-Event model through collaborating with the GlassFish team and integrating the GlassFish ServerSent-Event feature.

The HTML5 ServerSent-Event model provides a mechanism to allow browser clients to establish a uni-directional communication path to a server, where the server is then able to push messages to the browser at any point in time. 

A common JavaScript API (EventSource) is provided in modern browsers that allows the client to establish connections to the server and register callback functions to handle events as they come in over the connection, which can then be used to make any necessary page updates.

Some good sources of information on ServerSent-Events/EventSources are:
This new feature in WebLogic Server and GlassFish provides a small Java API and a couple of annotations that developers use to create and publish ServerSent-Event handlers, from which applications on the server can use to send messages to connected browser clients at any time, essentially enabling applications to push messages to clients over standard HTTP(S).

The runtime component of the feature uses CDI to instantiate and manage the handlers and support the injection of them into other application components as well as setting up and managing the asynchronous connection for each client.

Jitu from the GlassFish team provided some information on the feature earlier in the year:
Bhakti also from the GlassFish team has a posting with an example of a SSE application that fetches data from a twitter feed and republishes to clients:
Here it is running on a development build of WebLogic Server 12.1.2.


Besides being an interesting new feature with lots of possibilities, this also serves to demonstrate how the WebLogic and GlassFish teams are cooperating and producing innovative outcomes.



18 September 2012

WebSockets on WebLogic Server

We've been busy working on putting in support for the WebSocket Protocol into WebLogic Server with the intent to include it in the next major release (usual caveats apply with respect to dates, times, features, etc.).  Running the Autobahn WS Testsuite, which seems to be the industry defacto WebSocket compatibility verifier, we are seeing reports with very high levels of compatibility.

As there's no standard WebSocket Java API at this point, we've chosen to model the API on the Grizzly WebSocket API with some minor changes where necessary.  Once the results of JSR-356 (Java API for WebSocket) becomes public, we'll look to implement and support that.

In the background we have also done some integration work with the earlier WebSocket-SDK that was being used as a vehicle for WebSocket API investigations in order to try it out and look at the SPI requirements -- but we won't expose it in WLS 12.1.2 and will wait for the formal Java API for WebSocket to be finalized.

Back to WLS 12.1.2 and it's WebSocket API, as an exercise, I just ported the Apache Tomcat WebSocket demo called snake to run on WLS.

The original Tomcat demo source is here:

http://svn.apache.org/viewvc/tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/snake/
 
Here it is running on a development build of WebLogic Server 12.1.2.


There are some differences in terms of handling of connections and the registration approach but it was a pretty straight forward exercise and took about 30 minutes.  The demo didn't require too many major changes as the APIs are semantically similar in terms of accepting connections, handling messages and sending/broadcasting messages to clients.  Thankfully I didn't have to do anything on the client JavaScript side ... :-)

We also have the Grizzy/GlassFish Chat demo running on WLS as well.



 More info to come as we progress the documentation, etc.  Should be some demos of this running at OOW this year too I'd guess.


02 July 2012

JSF Managed Beans, @PostConstruct and CDI

In a similar vein to my last post, with this blog I'd like to try and raise the visibility of another bug that is being seen in a few different places, and for which there is already a patch available for it.

The basic issue here is that when an application is using JSF Managed Beans that in turn make use of the @PostContruct lifecycle annotation to execute some post-construction tasks, if the WEB-INF/beans.xml file is included and thus enables the CDI circuitry, the @PostConstruct method on the JSF ManagedBean is no longer invoked.

The good news is that if this scenario is part of your application design, then you can pick up and apply a patch for WLS 12c that will resolve the issue.

The relevant base bug # is 13703600 and the Smart Update patch ID is UXPH.  

From what I've read in the bug logs, we're also looking to include this fix in one of the patch-set-updates (PSUs) we are providing, so anyone that applies the relevant PSU should automatically get this fix.


25 June 2012

Multipart File Upload with WLS 12c

Multipart File Upload with WLS 12c

Just a word for anyone out there looking to use the Servlet 3.0 file upload feature with WLS 12c.

If you use the annotation approach on the Servlet class, it works perfectly well

However if you use the web.xml file to specify or override specific values using the multipart-config settings, then we have a small issue when we parse and apply those settings to the underling configuration bean.  This results in the maxFileSize value always being set to a value of 0.

Ultimately this manifests itself as a problem when uploading any file since the file size will always exceed the maximum allowed size of 0. 

The good news is there's a fix already available for it -- if you run into it, look for the patch for bug#14915431 or SmartUpdate patch 8EC8.

04 April 2012

WebLogic and EJB 3.1 @Singleton @Startup with @PostConstruct


That's quite the mouthful of annotations ..

A question was posed recently on the WLS EJB OTN forum asking about why WLS doesn't correctly support this combination of annotations, where the method with the @PostConstruct annotation was not  being called as expected. 

I thought I'd check it out with a simple test, which I'm sharing here. 

1. Using NetBeans, I created a new "Web Application" project and assigned it to use my local WebLogic Server 12c installation. 



2.Within the project, I created an EJB 3.1 Singleton using the NetBeans wizard.  Not that creating EJBs in Java EE 6 requires this sort of assistance any more, having done away with most of the gunk from earlier versions of the specification.  With EJB 3.1, an EJB can now be just a class with annotations and the logic.  That's it. Simple.



3. On the EJB 3.1 Singleton, I then added the @Startup annotation to indicate that the bean must be instantiated when the container starts.  I also added a method which I annotated with @PostContruct to indicate it should be called after the class has been instantiated via its constructor.  The method prints a message to standard out when it is called.

I also added an instance variable with a default value, that is subsequently changed in the init method.  Accessing this from a servlet will also show whether the init method was invoked.
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sab.demo;

import java.util.Date;
import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
import javax.ejb.LocalBean;
import javax.ejb.Startup;

/**
 *
 * @author sbutton
 */
@Singleton
@Startup
public class TestSingletonBean {
    
    private String TESTVAL = "IF YOU SEE THIS @POSTCONSTRUCT HAS NOT BEEN CALLED";
    
    @PostConstruct
    void init() {
        TESTVAL = "@PostConstruct method was called on " + new Date();
        System.out.printf("\n\nIn init: %s\n", TESTVAL);
    }
    
    public String getTestVal() {
        return TESTVAL; 
    }    
}

5. Since this test app is making use of the new Java EE 6 ease-of-use features that support the deployment of EJBs in Web applications, I could simply deploy this web application to see if the EJB Singleton was started on deployment and whether the @PostConstruct method was called.


Looking on the console where WebLogic Server was started in NetBeans, the message from the init method is seen right after the application deployment completes.


This demonstrates that WebLogic Server is correctly handling EJB 3.1 with @Singleton, @Startup and @PostConstruct.
 
6. Taking it one minor step further.

To independently observe the value of TESTVAL to ensure it has been modified via the init method, in the same project (it's very handy this web and ejb cohabitation ...) I added a servlet using the @WebServlet annotation.

In the servlet, I used the @EJB annotation to obtain a reference to the @Singleton and displayed the result of calling its getTestVal method on the page.

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sab.demo;

import java.io.IOException;
import java.io.PrintWriter;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *
 * @author sbutton
 */
@WebServlet(name = "TestServlet", urlPatterns = {"/TestServlet", "/test"})
public class TestServlet extends HttpServlet {

    @EJB
    TestSingletonBean singleton;

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {
            out.println("");
            out.println("");
            out.println("<title>Servlet TestServlet</title>");
            out.println("");
            out.println("");
            out.println("<h1>Servlet TestServlet at " + request.getContextPath() + "</h1>");
            out.printf("<p>Singleton TESTVAL: %s</p>", singleton.getTestVal());
            out.println("");
            out.println("");
        } finally {
            out.close();
        }
    }
}

7. Calling this from a browser shows the value of TESTVAL to be that set in the init method.


So in summary, this simple example shows WebLogic Server 12c supporting the EJB @Singleton and @Startup semantics correctly.




05 March 2012

WebLogic Server Singleton Services

WebLogic Server has supported the notion of a Singleton Service for a number of releases, in which WebLogic Server will maintain a single instance of a configured singleton service on one managed server within a cluster.  The singleton can be migrated to another server in the cluster, either automatically if it's current hosting server becomes available, or manually at an operators request.  The singleton can be optionally be configured with a preferred server to run on, as well as a set of named servers to which it can be migrated.  A singleton can be deployed as a standalone service or as part of an application deployment. 

The documentation for the singleton server is here:

http://docs.oracle.com/cd/E24329_01/web.1211/e24425/service_migration.htm#i1051668

With this capability, a question arises from time-to-time whether the Singleton Service feature in WebLogic Server can be used to provide a cluster wide singleton service for applications to use

The answer to this is yes, but it requires you to do a few things to expose the singleton instance to applications running in the cluster so that it can be looked up and used.

Since a singleton service is basically a POJO that implements the weblogic.cluster.singleton.SingletonService interface, which gets instantiated and managed by WebLogic Server, it doesn't have a surface area that allows it to be seen by applications running in the cluster. 

To allow the singleton service to be used by applications, in addition to implementing the basic logic that is required, it also needs to perform the following tasks:
  • Provide an RMI Remote interface that the singleton service additionally implements, which then allows it to be accessed and invoked from any server in the cluster
  • When the singleton service is activated, it binds itself into the cluster-wide JNDI tree
  •  When the singleton service is deactivated, unbinds itself from the cluster-wide JNDI tree
DemoSingletonImpl

package sab.demo.wlssingletoninstance;

import java.rmi.Remote;
import java.rmi.RemoteException;

/**
 *
 * @author sbutton
 */
public interface DemoSingleton extends Remote {
    
    public final String JNDI_NAME="DemoSingleton";
    
    public String singletonLocation();
    
    public String getWebLogicServerName();
    public String getHostName();
    
    public int increment();
    public int value();
    
}
DemoSingletonImpl
package sab.demo.wlssingletoninstance;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.rmi.RemoteException;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;
import weblogic.cluster.singleton.SingletonService;
import weblogic.jndi.Environment;

/**
 * Example of a WebLogic Server Singleton Service that can be accessed from
 * other deployed components.
 *
 * @author sbutton
 */
public class DemoSingletonImpl implements DemoSingleton, SingletonService {

    private Integer counter = 0;
    final private Logger logger = new Logger().getLogger("DemoSingletonImpl");

    public DemoSingletonImpl() {
        super();
        logger.info("Constructor");
    }

    // ================================================================ //
    // ===================== Singleton Service Methods ================ //
    // ================================================================ //
    
    @Override
    public void activate() {
        logger.info("Activate on " + singletonLocation());
        counter = 0;
        try {
            Environment env = new Environment();
            Context ctx = env.getInitialContext();
            ctx.rebind(JNDI_NAME, this);
            logger.info("Executed bind for: " + JNDI_NAME);
            logger.info(String.format("Looking up JNDI_NAME returns: %s", ctx.lookup(JNDI_NAME).getClass().getName()));
            //quickTest();

        } catch (NamingException e) {
            logger.warning("Unable to bind: " + this.getClass().getName() + " into JNDI as:" + this.getClass().getName() + ", Error: " + e.getMessage());
        }
    }

    @Override
    public void deactivate() {
        logger.info("Deactivate on " + singletonLocation());
        try {
            Environment env = new Environment();
            Context ctx = env.getInitialContext();
            ctx.unbind(JNDI_NAME);
            logger.info("Executed unbind for: " + JNDI_NAME);
        } catch (NamingException e) {
            System.out.println("\tUnable to unbind from JNDI as: " + JNDI_NAME + ", Error: " + e.getMessage());
        }
    }

    // ================================================================ //
    // ========================= Remotable Methods ==================== //
    // ================================================================ //
    
    @Override
    public String singletonLocation()  {
        return String.format("%s %s",
                getHostName(),
                getWebLogicServerName());
    }

    @Override
    public String getWebLogicServerName() {
        return Utilities.getWebLogicServerName();
    }

    @Override
    public String getHostName() {
        return Utilities.getHostName();
    }

    @Override
    public synchronized int increment() {
        counter++;
        return counter.intValue();
    }

    @Override
    public int value() {
        return counter.intValue();
    }

    // ================================================================ //
    // ========================== Private Methods ===================== //
    // ================================================================ //    
    
    /**
     * Called on activate to verify binding is available
     */
    private void quickTest() {
        try {
            Environment env = new Environment();
            Context ctx = env.getContext();
            DemoSingleton singleton =
                    (DemoSingleton) PortableRemoteObject.narrow(ctx.lookup(DemoSingleton.JNDI_NAME), DemoSingleton.class);
            logger.info("quickTest: " + singleton.singletonLocation());
        } catch (Exception ne) {
            logger.log(Logger.SEVERE, ne);
            logger.severe("Error: %s" + ne.getMessage());
        }
    }
}

Deploying and Configuring the Singleton
To deploy the singleton in standalone mode, compile and package the classes into a JAR file and put the JAR file into the WebLogic Server classpath. Note this needs to be done on each physical machine where the managed servers in the cluster run.

You configure a singleton service instance for cluster using the WebLogic Server console.


This ultimately writes an entry in the domain's config.xml as such:

<singleton-service>
  <name>DemoSingleton</name>
  <user-preferred-server>Mike</user-preferred-server>
  <class-name>sab.demo.wlssingletoninstance.DemoSingletonImpl</class-name>
  <cluster>Tingles</cluster>
</singleton-service>
When the preferred managed server starts, the singleton service will be instantiated.
<Mar 2, 2012 3:25:32 PM CST> <Notice> <Cluster> <BEA-000102> <Joining cluster Tingles on 239.192.0.0:7001> 
<Mar 2, 2012 3:25:33 PM CST> <Notice> <WebLogicServer> <BEA-000365> <Server state changed to RUNNING.> 
<Mar 2, 2012 3:25:33 PM CST> <Notice> <WebLogicServer> <BEA-000360> <The server started in RUNNING mode.> 
[] INFO Activate on Steve-Button-MacBook-Pro.local Mike
[] INFO Executed bind for: DemoSingleton
[] INFO Looking up JNDI_NAME returns: sab.demo.wlssingletoninstance.DemoSingletonImpl
[] INFO quickTest: Steve-Button-MacBook-Pro.local Mike
Performing a manual migration using the console, the singleton gets deactivated on the current server and activated on another.
[] INFO Deactivate on Steve-Button-MacBook-Pro.local Mike
[] INFO Executed unbind for: DemoSingleton

<Mar 2, 2012 3:25:34 PM CST> <Notice> <WebLogicServer> <BEA-000360> <The server started in RUNNING mode.> 
[] INFO Activate on Steve-Button-MacBook-Pro.local James
[] INFO Executed bind for: DemoSingleton
[] INFO Looking up JNDI_NAME returns: sab.demo.wlssingletoninstance.DemoSingletonImpl
[] INFO quickTest: Steve-Button-MacBook-Pro.local James
Using the Singleton
Applications wishing to use the singleton service then need to look it up from the cluster-wide JNDI tree, narrow it to singleton service type and invoke it's methods as needed.

  private DemoSingleton getSingleton() throws ClassCastException, NamingException {
    Context ctx = getInitialContext()
    DemoSingleton singleton = (DemoSingleton) PortableRemoteObject.narrow(ctx.lookup(DemoSingleton.JNDI_NAME), DemoSingleton.class);
    return singleton;
}
Using this in a servlet for example, you can see how the servlet running on the managed server Mike is able to access the singleton service running on managed server James.

When the singleton service is migrated, the servlet then seamlessly accesses it on the other managed server, where it is now co-located in this specific example below.

Summary
This is obviously a fairly simple example but it should highlight the basic requirements and method to create an cluster wide singleton that can be used by applications.

01 March 2012

WebLogic Server 11g (10.3.6) Documentation

The OTN documentation pages don't appear yet to have a link to the WLS 10.3.6 documentation set.

If you are looking for it in the interim you can find it here: 

http://docs.oracle.com/cd/E23943_01/wls.htm

While this is predominantly a patchset, there are a number of new features listed in the What's New in WebLogic Server document.

Some worthy examples are:

Web application filtering classloader documentation update

Following a posting on here last year that described using the filtering classloader within a web application, several folks commented that it wasn't described in the documentation.

The WebLogic Server 12c (12.1.1.0) documentation shows the prefer-application-packages and prefer-application-resources elements as being available in the weblogic.xml file.

http://docs.oracle.com/cd/E24329_01/web.1211/e21049/weblogic_xml.htm#autoId24

The WebLogic Server 11g (10.3.6.0) documentation should also include this when it gets pushed out to OTN.

<wls:weblogic-web-app>
     <wls:weblogic-version>12.1.1</wls:weblogic-version>
     <wls:context-root>FilterWeb</wls:context-root>
     <wls:container-descriptor>
         <wls:prefer-application-packages>
             <wls:package-name>com.oracle.foo</wls:package-name>
         </wls:prefer-application-packages>
     </wls:container-descriptor>
</wls:weblogic-web-app>