Skip to main content

swchan2's Blog

startAsync in Servlet 3.0

Posted by swchan2 on September 8, 2011 at 5:15 PM PDT

Prior to Servlet 3.0, a servlet may need to wait for a long operation to complete and can cause thread starvation in web container. In Servlet 3.0, asynchronous processing is introduced to handle this situation.

There is a lot of information about asynchronous processing in Servlet 3.0. In this blog, we will take a look at two aspects of startAsync.

When will javax.servlet.AsyncListener#onStartAsync(AsyncEvent event) method be invoked?

Let us take a look at a simple example.

         AsyncContext asyncContext = httpServletRequest.startAsync();     <br />
    AsyncListener myAsyncListener = new AsyncListener() { .... };     <br />
    asyncContext.addListener(myAsyncListener);

Notice that myAsyncListener.onStartAsync(AsyncEvent) method is not invoked in above example because asynchronous processing has already been started. When will it be called? According to Servlet 3.0 spec, AsyncListener#onStartAsync(AsyncEvent) will be invoked when the AsyncContext is reinitialized, for instance, when AsyncContext#dispatch() is invoked. As a remark, all the asyncListeners added will be removed during reinitialization and one has to add async listeners if necessary.

In a servlet with given request and response, are the AsyncContext request.startAsync() and request.startAsync(request, response) the same?

The above two AsyncContext are almost, but not the same. The difference is in the behavior of AsynContext#dispatch(). From javadoc of AsynContext#dispatch(),

If the asynchronous cycle was started with ServletRequest#startAsync(ServletRequest, ServletResponse), and the request passed is an instance of HttpServletRequest, then the dispatch is to the URI returned by HttpServletRequest.getRequestURI().
Otherwise, the dispatch is to the URI of the request when it was last dispatched by the container.

The following example illustrate what it means. Suppose we have three HTTP servlets: A, B, C with resource paths /a, /b, /c (relative to context root) respectively.
In Servlet A, we have
            request.getRequestDispatcher(&quot;/b&quot;).forward(request, response);   

In Servlet B, we have
            request.getRequestDispatcher(&quot;/c&quot;).forward(request, response);   

In Servlet C, we have following two cases:

  1. request.startAsync().dispatch(); // to /b
    It will dispatch to the last dispatched URI, which corresponds to /b.
  2. request.startAsync(request, response).dispatch(); // to /c
    It will dispatch to request.getRequestURI(), which corresponds to /c.

Cross-site request forgery prevention filter in GlassFish 3.1.1

Posted by swchan2 on May 31, 2011 at 3:06 PM PDT

Cross-site request forgery (CSRF)
is a malicious attack exploiting the trust of a site from a user's browser.
As an example, an user may be tricked to invoke a url to do a bank transaction
by either clicking on the url or accessing the url through <img>.

In GlassFish 3.1.1, there is a
CSRF prevention filter,
org.apache.catalina.filters.CsrfPreventionFilter,
which is based on Tomcat 7.
The filter basically uses nonce exchange to a secure the communication.

There are three possible initialization parameters for the above filter:

Filter init-param Short Description Default

entryPoints A comma separated list of URLs that will not be checked for nonce in HTTP GET method. none

nonceCacheSize number of cached nonce based on LRU. This is used for parallel requests, for instance from frames. 5

randomClass The name of the class to generate the nonces. The class must extends java.util.Random. java.security.SecureRandom

By default, the filter is not turned on.

One can prevent the CSRF attack for a given web application as follows:

  1. enabling the filter in web.xml

    For instance,
            <br>&nbsp;&nbsp;&lt;filter&gt;
            <br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;filter-name&gt;csrf&lt;filter-name&gt;
            <br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;filter-class&gt;org.apache.catalina.filters.CsrfPreventionFilter&lt;filter-class&gt;
            <br>&nbsp;&nbsp;&lt;filter&gt;
            <br>&nbsp;&nbsp;&lt;filter-mapping&gt;
            <br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;filter-name&gt;csrf&lt;filter-name&gt;
            <br>&nbsp;&nbsp;&nbsp;&nbsp;&lt;url-pattern&gt;/myservlet&lt;url-pattern&gt;
            <br>&nbsp;&nbsp;&lt;filter-mapping&gt;
       
  2. sending the nonce in each HTTP request associated to the filter

    One can do this with the help of HttpServletResponse#encodeURL(String url)
    and HttpServletResponse#encodeRedirectURL(String url).
    Or one can pass back the nonce as a request parameter with name org.apache.catalina.filters.CSRF_NONCE, which is the value of the constant org.apache.catalina.filters.Constants.CSRF_NONCE_REQUEST_PARAM.

    For instance, in a jsp page, instead of having

    &nbsp;&nbsp;&lt;a href="index.jsp"&gt;Go to index&lt;/a&gt;

    we will have
            <br>&nbsp;&nbsp;&lt;a href="&lt;%=response.encodeURL("index.jsp")%&gt;"&gt;Go to index&lt;/a&gt;
       

Note that one can also enable the CSRF prevention filter for a given domain
by adding the filter in default-web.xml for the domain.

Turning off default error page in GlassFish 3.x

Posted by swchan2 on April 18, 2011 at 5:23 PM PDT

In GlassFish, when no error page is specified for a given web application, a default error page will be displayed. In some use cases, it is desirable to turn off the default error page.
In this blog, we will summarize different ways to achieve this.

In a Virtual Server

One can turn off the default error page in a given virtual server by specifying a property with name <b>errorReportValve</b> and value "".

For instance, in domain.xml, it is as follows:

    &nbsp;&nbsp;&lt;config name="server-config"&gt;<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&lt;http-service&gt;<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;access-log&gt;&lt;access-log&gt;<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;virtual-server id="server" sso-enabled="false" network-listeners="http-listener-1,http-listener-2"&gt;<br>
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property name="errorReportValve" value=""&gt;&lt;property&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;virtual-server&gt;

Or one can acheive this through CLI:

asadmin set configs.config.server-config.http-service.virtual-server.server.property.errorReportValve=""

In a Web Application

One can create a file with no content and then specified it as a default error page for a given application.
A snapshot of web.xml is as follows:

&nbsp;&nbsp;&lt;error-page&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&lt;location&gt;defaultErrorPage.jsp&lt;location&gt;<br>
&nbsp;&nbsp;&lt;/error-page&gt;

In a Servlet

One can specify a servlet init-param, <b>org.glassfish.web.isDefaultErrorPageEnabled</b>, in web.xml to turn on and off default error page for a given servlet as follows:

&nbsp;&nbsp;&lt;init-param&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&lt;param-name&gt;org.glassfish.web.isDefaultErrorPageEnabled&lt;param-name&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&lt;param-value&gt;false&lt;param-value&gt;<br>
&nbsp;&nbsp;&lt;/init-param&gt;

Comments

<p>I suppose you can also set &lt;error-page&gt; and ...

I suppose you can also set <error-page> and <init-param> in config/default-web.xml for a domain-wide configuration.

If one modify <error-page> in default-web.xml, then one need ...

If one modify in default-web.xml, then one need to make sure that the corresponding error page is accessible for all web application in the given domain.

keepstate, keepSessions, keep-state, save-sessions-enabled in GlassFish 3.1

Posted by swchan2 on March 9, 2011 at 6:34 AM PST

GlassFish supports the preseving of HTTP session data across the redeployment of web application.

Prior to GlassFish 3.1, one can achieve this through the command line as follows:
&nbsp;&nbsp;asadmin redeploy <b>--properties keepSessions=true</b> --name ${APP_NAME} ${A_WAR}

In GlassFish 3.1, web sessions, Stateful Session EJB instances and persistently created EJB timers can be retained between redeployments. A new option is introduced as follows:
&nbsp;&nbsp;asadmin redeploy <b>--keepstate=true</b> --name ${APP_NAME} ${A_WAR}

In addition, one also supports the preseving of HTTP session data through the deployment descriptor in glassfish-web.xml as follows:
<glassfish-web-app>
  <keep-state>true<keep-state>
<glassfish-web-app>

As an alternative, one can use weblogic.xml as follows:
<weblogic-web-app xmlns="http://xmlns.oracle.com/weblogic/weblogic-web-app">
  <container-descriptor>
    <save-sessions-enabled>true<save-sessions-enabled>
  <container-descriptor>
<weblogic-web-app>

In this case, the command options override the deployment descriptor. And as usual one will ignore the presence of weblogic.xml if there is a glassfish-web.xml. Hence, for HTTP session data, we have the following precedence:

     &nbsp;&nbsp;<i>--keepstate</i> <b style="font-size: 170%;">&gt;</b>     <i>--properties keepSessions</i> <b style="font-size: 170%;">&gt;</b>     <i>&lt;keep-state&gt;</i> <b style="font-size: 170%;">&gt;</b>     <i>&lt;save-sessions-enabled&gt;</i>

High Availability Single Sign On in GlassFish 3.1

Posted by swchan2 on March 1, 2011 at 4:36 PM PST

Single Sign On allows web applications to share the same authentication state.

GlassFish v2 supports virtual server level Single Sign On (SSO). Web applications with the same authentication realm in a given virtual server can share the authentication state in GlassFish v2.

GlassFish 3.1 supports SSO failover at cluster level. So one has high availability for Single Sign On in a virtual server of a cluster in GlassFish 3.1.

One can set up the SSO failover in a cluster easily as follows:

  1. Create and start a cluster.
    For instance, one can create a cluster with two instances having ports 18080 and 28080 respectively as follows:
             asadmin create-cluster ${CLUSTER_NAME} <br />     asadmin create-local-instance --cluster ${CLUSTER_NAME} --systemproperties HTTP_LISTENER_PORT=18080 instance1 <br />     asadmin create-local-instance --cluster ${CLUSTER_NAME} --systemproperties HTTP_LISTENER_PORT=28080 instance2 <br />     asadmin start-cluster ${CLUSTER_NAME}    
  2. Enable SSO in a virtual server of the given cluster.
    asadmin set ${CLUSTER_NAME}.http-service.virtual-server.${VIRTUAL_SERVER}.sso-enabled=true
  3. Enable SSO failover for the given cluster.
    asadmin set ${CLUSTER_NAME}.availability-service.web-container-availability.sso-failover-enabled=true
  4. Use a cluster level realm for web applications.
    For instance, one can create a cluster level file realm user as follows:
                 echo AS_ADMIN_USERPASSWORD=${A_PASSWORD} &gt; pwdfile <br />     asadmin create-file-user --target ${CLUSTER_NAME} --authrealmname file --passwordfile pwdfile --groups ${A_GROUP} ${A_USER}        
  5. Specify &lt;security-constraints&gt; and &lt;login-config&gt; in web.xml and &lt;security-role-mapping&gt; in <code>glassfish-web.xml as in any security web application. Note that all web applications participating in a SSO session must use the same realm. In addition, one has to specify &lt;distributable/&gt; in web.xml of web applications.
  6. Deploy web applications with --availabilityenabled=true.
                 asadmin deploy --target ${CLUSTER_NAME} --availabilityenabled=true ${A_WAR}

Download GlassFish 3.1 and try it today!

Related Topics >>