Monday, December 31, 2012

JSF 2.x Tip of the Day: Dynamic <ui:include/> with <f:viewParam/>

Introduction

I encountered a situation the other day where I need to include a JSF page based on a parameter passed in via a <f:viewParam>. This seems like a very reasonable kind of idea. I expected to be able to make the <ui:include/> use a dynamically set src parameter using EL from the <f:viewParam>. This is where I went wrong (the idea was good...). The <ui:include/> is a tag handler. It is evaluated on Restore View Phase. The value processing does not take place until the Apply Request Values Phase. This presents a problem since the EL binding for my <ui:include/> is based on the <f:viewParam> which is a UIInput object. So we are out of phase. The page will display the results, but all the AJAX will not work.

A Solution

A solution to the problem involves using static <ui:include/> elements wrapped in <ui:fragment/> elements. This allows the tag handler to resolve the page to include, and then the fragment determines (via late binding) whether to display the page based on the <f:viewParam> passed. The page is supported by a @ViewScoped bean to keep the page in scope.

Code

Here is an example of how to do it.
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
31
32
33
34
35
36
37
38
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      >
    <h:head>
        <title>Index</title>
        <f:metadata>
            <f:viewParam name="page" value="#{index.page}"/>
        </f:metadata>
    </h:head>
    <h:body>
        <p>
These examples use static binding on the <ui:include/> and use the the <ui:fragment/> <code>rendered</code>
 
            attribute to determine which page to display. Since these elements are evaluated after the component tree is restored,
 
            the AJAX will work.
        </p>
<ui:fragment rendered="#{index.page eq 'page1'}">
            <ui:include src="page1.xhtml"/>
        </ui:fragment>
        <ui:fragment rendered="#{index.page eq 'page2'}">
            <ui:include src="page2.xhtml"/>
        </ui:fragment>
        <h:button id="button1" value="Page 1" outcome="good.xhtml?page=page1"
                  includeViewParams="true"/>
         
 
        <h:button id="button2" value="Page 2" outcome="good.xhtml?page=page2"
                  includeViewParams="true"/>
         
 
        <h:button outcome="index" value="Home"/>
    </h:body>
</html>

Conclusion

I have put the complete NetBeans 7.2.1 project using Mojarra on Bitbucket. The project uses Apache Maven, and was tested using GlassFish 3.1.2. Here is the complete project: dynamic-include

Creating and Implementing An HttpSessionWrapper

Introduction

I am faced with a problem currently where I have an application that was written before the J2EE specification was written. The application has its own application server, session, and state management. I am in the process of modernizing this application and transforming it into a standard Java EE application. However, there is a lot of code over 1.5m LOC. That makes this process very intensive.

One of the issues I have been wrestling with is session management. As I previously noted, the application has its own session and state management mechanisms. The session object is not too vastly different from a standard HttpSession object. This has given rise to an idea that I could wrap a standard HttpSession object with a decorator similar to HttpServletRequestWrapper and perhaps a implementation of the old session mechanism.

Currently there is no HttpSessionWrapper like HttpServletRequestWrapper, or HttpServletResponseWrapper so I wrote my own. It was simple to do and I hope others who may need a HttpSessionWrapper will use it. Once I wrote the wrapper, implementing it was the harder part.

Implementation

Implementation requires a little knowledge of how HTTP requests are handled by servlets, and request and response handling in general. The most important thing to remember is: the HttpSession is created from the HttpServletRequest object. This important fact can help determine how to implement our HttpSessionWrapper. I think that the easiest mechanism is to use an HttpServletRequestWrapper in a @WebFilter. Filters are the first items that a request will pass through to reach the servlet, and the last thing it will pass through in the response.

If you use this mechanism, for implementing your HttpSessionWrapper, you must ensure that this is the first filter that the request will pass through. If it is the only filter, that should be very easy to implement. If you are using multiple filters with annotations, you will need to use a web.xml file to place them in the order you want them applied.

The example code I have below takes advantage of the fact that I can use a filter and that once I pass in my HttpServletRequestWrapper with its modified getSession() methods that return my HttpSessionWrapper. The HttpSessionWrapper can be downloaded here: session-wrapper

Code

The code below includes the HttpSessionWrapper and an example implementation of how to use it.

HttpSessionWrapper.java


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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package com.bluelotussoftware.session;
 
import java.util.Enumeration;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionContext;
 
/**
 * A Wrapper (decorator) for the {@link  HttpSession} object.
 *
 * @author John Yeary
 * @version 1.0
 */
public class HttpSessionWrapper implements HttpSession {
 
    private HttpSession session;
 
    /**
     * Constructor that takes an {@link HttpSession} object to wrap.
     *
     * @param session
     */
    public HttpSessionWrapper(HttpSession session) {
        this.session = session;
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    public long getCreationTime() {
        return session.getCreationTime();
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    public String getId() {
        return session.getId();
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    public long getLastAccessedTime() {
        return session.getLastAccessedTime();
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    public ServletContext getServletContext() {
        return session.getServletContext();
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    public void setMaxInactiveInterval(int interval) {
        session.setMaxInactiveInterval(interval);
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    public int getMaxInactiveInterval() {
        return session.getMaxInactiveInterval();
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    public HttpSessionContext getSessionContext() {
        return session.getSessionContext();
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    public Object getAttribute(String name) {
        return session.getAttribute(name);
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    public Object getValue(String name) {
        return session.getValue(name);
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    public Enumeration<string> getAttributeNames() {
        return session.getAttributeNames();
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    public String[] getValueNames() {
        return session.getValueNames();
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    public void setAttribute(String name, Object value) {
        session.setAttribute(name, value);
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    public void putValue(String name, Object value) {
        session.putValue(name, value);
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    public void removeAttribute(String name) {
        session.removeAttribute(name);
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    public void removeValue(String name) {
        session.removeValue(name);
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    public void invalidate() {
        session.invalidate();
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isNew() {
        return session.isNew();
    }
}

HttpSessionWrapperImpl.java


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
package com.bluelotussoftware.session.impl;
 
import com.bluelotussoftware.session.HttpSessionWrapper;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import javax.servlet.http.HttpSession;
 
/**
 *
 * @author John Yeary
 * @version 1.0
 */
public class HttpSessionWrapperImpl extends HttpSessionWrapper {
 
    public static final String INFO = "HttpSessionWrapperImpl/1.0";
 
    public HttpSessionWrapperImpl(HttpSession session) {
        super(session);
    }
 
    public List<string> getAttributesNames() {
        Enumeration<string> names = getAttributeNames();
        return Collections.list(names);
    }
}

HttpServletRequestWrapperImpl.java


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
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.bluelotussoftware.session.impl;
 
import com.bluelotussoftware.session.HttpSessionWrapper;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpSession;
 
/**
 *
 * @author John Yeary
 * @version 1.0
 */
public class HttpServletRequestWrapperImpl extends HttpServletRequestWrapper {
 
    public HttpServletRequestWrapperImpl(HttpServletRequest request) {
        super(request);
    }
 
    /**
     * {@inheritDoc}<p>
This method will return an instance of
     * {@link HttpSessionWrapper}</p>
*/
    @Override
    public HttpSession getSession() {
        return getSession(true);
    }
 
    /**
     * {@inheritDoc} <p>
This method will return an instance of
     * {@link HttpSessionWrapper}</p>
*/
    @Override
    public HttpSession getSession(boolean create) {
        HttpSession session = super.getSession(create);
        if (session != null) {
            return new HttpSessionWrapperImpl(session);
        } else {
            return session;
        }
    }
}

WrappingFilter.java


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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package com.bluelotussoftware.example;
 
import com.bluelotussoftware.session.HttpSessionWrapper;
import com.bluelotussoftware.session.impl.HttpServletRequestWrapperImpl;
import java.io.IOException;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
 
/**
 * {@link Filter} used for wrapping the {@link HttpServletRequest} with an
 * implementation of the {@link HttpServletRequestWrapper} that provides a
 * custom {@link HttpSessionWrapper}.
 *
 * @author John Yeary
 * @version 1.0
 */
@WebFilter(filterName = "WrappingFilter", urlPatterns = {"/*"},
dispatcherTypes = {
    DispatcherType.FORWARD, DispatcherType.ERROR,
    DispatcherType.REQUEST, DispatcherType.INCLUDE
})
public class WrappingFilter implements Filter {
 
    /**
     * Default Constructor
     */
    public WrappingFilter() {
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest hsr = (HttpServletRequest) request;
        HttpServletRequestWrapperImpl hsrwi = new HttpServletRequestWrapperImpl(hsr);
        chain.doFilter(hsrwi, response);
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    public void destroy() {
        //NO-OP
    }
 
    /**
     * {@inheritDoc}
     */
    @Override
    public void init(FilterConfig filterConfig) {
        //NO-OP
    }
}

Conclusion

Implementing a HttpSessionWrapper can be done very easily with a little thought, and perhaps a good blog article on it. The session-wrapper and session-wrapper-example code is available on BitBucket as Mercurial projects.. The projects were developed using NetBeans 7.2.1 and Apache Maven and was tested using Glassfish 3.1.2.

Thursday, December 27, 2012

Tomcat 7: Custom Valve

I was asked today by a colleague for some help on creating a valve for use with Apache Tomcat 7. I had never done one before, so I thought I would give it a quick try. +Craig McClanahan  had done a great job on creating a simple mechanism for creating a Valve with a lot of the heavy lifting done by ValveBase.

Creating your own valve is really simple using NetBeans 7.2.1 along with Apache Maven.

  1. Create a Maven Java Application.
  2. Add the following dependency:
    1
    2
    3
    4
    5
    6
    <dependency>
        <groupid>org.apache.tomcat</groupId>
        <artifactid>tomcat-catalina</artifactId>
        <version>7.0.34</version>
        <scope>provided</scope>
    </dependency>
  3. Create your Java class and extend it from ValveBase.
  4. Implement invoke(Request request, Response response)
  5. Build your library (.jar) file
  6. Install the library in the ${tomcat.home}/lib directory.
  7. Configure server.xml to use your new Valve. For example:
    1
    <valve className="com.bluelotussoftware.tomcat.ProcessingValve"/>
  8. Start the server to see your new valve in action
Here is my simple example.

ProcessingValve.java

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
31
32
33
34
35
36
37
38
package com.bluelotussoftware.tomcat;
 
import java.io.IOException;
import java.util.Enumeration;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ValveBase;
 
/**
 *
 * @author John Yeary <jyeary@bluelotussoftware.com>
 * @version 1.0
 */
public class ProcessingValve extends ValveBase {
 
    private static final Logger logger = Logger.getLogger(ProcessingValve.class.getName());
 
    /**
     * {@inheritDoc}
     */
    @Override
    public void invoke(Request request, Response response) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = request.getRequest();
 
        Enumeration<String> headerNames = httpServletRequest.getHeaderNames();
 
        while (headerNames.hasMoreElements()) {
            String header = headerNames.nextElement();
            logger.log(Level.INFO, "Header --> {0} Value --> {1}", new Object[]{header, httpServletRequest.getHeader(header)});
        }
 
        getNext().invoke(request, response);
    }
}
Here is the output...
INFO: Server startup in 1442 ms
Dec 27, 2012 5:54:01 PM com.bluelotussoftware.tomcat.ProcessingValve invoke
INFO: Header --> host Value --> localhost:8080
Dec 27, 2012 5:54:01 PM com.bluelotussoftware.tomcat.ProcessingValve invoke
INFO: Header --> host Value --> localhost:8080
Dec 27, 2012 5:54:01 PM com.bluelotussoftware.tomcat.ProcessingValve invoke
INFO: Header --> host Value --> localhost:8080
Dec 27, 2012 5:54:01 PM com.bluelotussoftware.tomcat.ProcessingValve invoke
INFO: Header --> host Value --> localhost:8080

As you can see it was very easy to implement. Here is the code for my example: valve-example.zip

The source can also be found on Bitbucket: valve-example

Popular Posts