Java 8: What Streams can do for you.

In my previous post, I wrote about how Java 8 is starting to shift to Declarative programming. Today, I’ll expand on that and talk briefly about how the new Stream API will change the way developers work with data structures ie. Collections. The Stream API is very complex, but at the most basic level, it introduces various operations that perform tasks on a Collection. A Stream consumes a collection and pipelines the data from the collection. The Stream operations can be classified into two types:

  1. Intermediate – these operations take the original stream and produce a new Stream. Intermediate operations need a terminal operation to actually perform work. These operations are Lazy and don’t perform work until the terminal operation is called. Some examples include:
    • Filter
    • Map
    • Sorted
  2. Terminal – these operations consume a Stream, execute the terminal logic, and produce a result.
    • Collect
    • ForEach
    • Reduce
    • Sum, Count, Average, etc

Streams and their operations let us perform data manipulation that used to require Loops, Iterators, and complex inline logic. For example, lets consider the array of numbers in my previous post. This time I want to get the Sum of All Odd numbers.

List<Integer> numbers = Arrays.asList(1,2,3,4,5,6);

Using pre Java 8 approach I’d loop and add up all items that are Odd. If I were in post Java 5, I could use an Iterator.


int sum=0; // The sum of all odd numbers
for(int x=0; x<numbers.length(); numbers++){
 if(numbers[x] % 2 !=0)
  sum += numbers[x];
}

Using Streams, I can write code that is easily readable and more concise:


int sum = numbers.stream()
                 .filter(e -> e%2 != 0) // Intermediate op
                 .sum();  // Terminal op

This code is easier to maintain and it expresses the intent of the code without any comments. This is a simple example, but we need a more complex example to show the real power of Streams.

Most of the time you loop a Collection you actually want to manipulate the objects in the collection and do something more complex. Consider the same array full of numbers. This time, we want to make an HTTP post request for each element in the array, and Post the int to a REST endpoint.

 


numbers.stream()
       .forEach(e -> doHttpPost(e));

public void doHttpPost(int e){
  ... // DO HTTP POST HERE. Logic not relevant for this discussion.
}

We have no intermediate operation to perform, so we just use the forEach() terminal operation and call the doHttpPost() method for every element in the Stream. Now, lets say our requirements change and we only want to send the Odd elements that are greater than 1.  Just add both .filter() intermediate operations (you can also combine them):


numbers.stream()
       .filter(e -> e%2 != 0) // Satisfy our new "Odd only" requirement
       .filter(e -> e > 1) // Satisfy our > 1 requirement
       .forEach(e -> doHttpPost(e));
}

Now, lets pretend our REST service provider now requires us to wrap each int in a Number object. This is when the map() operation is powerful. Map is an intermediate operation that lets you create a new Stream. So, we filter only on Odds greater than 1, then create a new Stream of Numbers, and finally perform the HTTP Post.


numbers.stream()
       .filter(e -> e%2 != 0) //Odds only
       .filter(e -> e > 1) // Greater than 1
       .map(e -> new Number(e)) // New stream
       .forEach(e -> doHttpPost(e)); //do Post

// Example Number Object
public class Number(){
  int num;

  public Number(int newNum){
   num=newNum
  }
}

Finally, lets pretend that sequentially processing HTTP posts is the cause of a system bottleneck. We need a way to improve performance. Streams can actually pipeline the data in parallel, all you have to do is change the single stream() method to parallelStream(). The entire operation is now performed in parallel:


numbers.parallelStream()
       .filter(e -> e%2 != 0)
       .map(e -> new Number(e))
       .forEach(e -> doHttpPost(e));

As you can see, Intermediate stream operations can be chained to perform all sorts of logic. Converting from Sequential to Parallel processing is simple and does not result in a complete rewrite of the code logic. One thing to note is that you must be careful of the parallelStream() method, as it creates Threads and shares the common thread pool.

Obviously these are simple examples but I hope they demonstrate the power of Java 8 Streams and Declarative programming.

Advertisements

Java’s Functional and Declarative Evolution

Java 8 is the largest change in the Java platform to date. One of the primary goals was to move the language from an imperative model to a declarative model. Before Java 8, software engineers wrote code that explicitly modified the state of the program and provided instruction on how all operations should be performed. Let’s discuss the evolution of Java development. Consider this example:

We have an Array collection with a bunch of numbers {1, 2, 2, 3, 5, 8} and need to find the “sum of all numbers.” Using Java 4 or lower (imperative) you have to loop through the array like this:

int sum=0;
for(int x=0; x<array.size(); x++){
// do the summation
 sum+=array[x];
}

This code explicitly loops through the array, one element at a time. Java 5 simplified things a bit, with the introduction of the more concise For loop:

int sum=0;
for(int x:array){
 sum+=x;
}

So no longer care about the length, we just loop through the collection. But if you compare this to the previous code, it’s still the same approach – we tell Java to explicitly loop through each and every element in the array. We still need the same amount of code to do it (minus some < and ++ operators) and readability is more or less the same. We wrote more logic just looping the array than our actual business logic.

We can also use the Iterator pattern like this:

int sum=0;
Iterator i = array.iterator();
while(i.hasNext()){
sum+=i.next();
}

If we compare all three options, they’re all similar amount of code and complexity. The iterator pattern actually introduces even more objects for the JVM to manage.

Onto Functional Style
With the introduction of Java 8, we get two things: Lambadas and the ‘forEach’ method on all Collections. ForEach provides us with a reference to all items in the collection. The implementation is specific to the type of collection. We just have to call the ForEach method. Java will execute and provide us the implementation. This is a classic example of polymorphism. Here’s how we use it:

int sum=0;
array.forEach(n -> {
//implementation here
sum+=n;
});

With this approach, we don’t care how the array is looped — there is no need to manage iteration values or indexes. ForEach will handle it for us and call the body of our function, for every element in the array (commented area). The code that is in the forEach: (n-> { … }) is lambda notation.

This lets us focus on implementing the solution to our problem (summing the contents of the array), rather than worrying about how to access our Array. It’s the job of the Java API to handle things it *already* knows how to do.

Compared to our Java 5 implementation, the functional style is easier to read, is less complex, and helps us focus on code that represents our business logic.

More Features
This is just an example of how Java 8 will change the way developers write code. I’ll talk about further improvements including the Stream / Map / Reduce / Predicate APIs in my next article.

Quick Tip: (Un)Installing Apps on Google Glass

Installing new apps (or removing) them from Google Glass doesn’t require you to use the ADT IDE. You can use a few simple command lines via ADB (Android Debug Bridge) to install/uninstall APKs.

Here’s the simple steps:

  1. Plug in your device. Ensure Debug mode is turned on. Install the USB Drivers for the device. See this post if you need help installing USB Drivers for Glass.
  2. Open a command prompt. CD into / Browse to where you installed the ADB tool kit. Its in [ADT Install Dir]/sdk/platform-tools/
  3. Place the APK you wish to install into the same directory as the ADB.exe.
  4. To install any APK, just type: ‘adb install [APK Filename.apk]‘. You should see some status messages and finally ‘Success’.
  5. Once the APK is installed, you can check the package status by using: ‘adb shell pm list packages‘. You should see a listing of all installed packages, listed by Java package. Look for your package. For example, if your project was written in the ‘com.test’ you should see it in the list.
  6. To uninstall any APK, type adb uninstall [package name]. Example: ‘adb uninstall com.test’.

A note:

  • You can’t install a package on top of one that already exists. So to update a package on Glass, you want to uninstall and then install. There’s no ‘reinstall’ or ‘update’ if you are using this command line method.

That’s it!

Google Glass: Development & GDK!

Learning the Glass Development Kit was one of my immediate goals after getting Glass. So, just like learning any new Platform, I built a  “HelloWorld” LiveCard application 🙂

The GDK itself is not finalized and is still in preview stages. Google has some decent samples here.  Turns out, getting your development environment ready is a little tricky. The Quick Start Guide is a great place to start, but I’ll summarize the entire process here:

  1. Download the ADT Bundle. This contains the SDK Manager and Eclipse based Android Development Tools (ADT) IDE.
  2. Unzip the bundle. Run the SDK Manager and install the supported Glass Android version (currently, 4.4.2). Make sure you include the SDK Platform and Glass Development Preview Kit.sdk-manager
  3. You will need to install the newest Android SDK Build-tool (currently 19.0.1). I accidentally installed 19.0 and ended up with runtime issues.
  4. Finally, install the Google USB Driver. This allows the ADT to communicate with Glass. When installed, it will be located in <your install folder>/sdk/extras/google/usb_driver/.usb driver
  5. Next, you need to prepare Glass itself to accept custom built software. Go into the “Settings” live card, then scroll until you see “Device Info”. Tap once, choose “Debug” and enable it.
    settings
  6. Unfortunately, the provided USB Driver is not compatible with Glass. You’ll have to modify the “android_winusb.inf” file to include Glass entries before Windows will accept the driver. Add the following to the [Google. NTx86] and [Google. NTamd64] sections:
    ;Google Glass
    %SingleAdbInterface% = USB_Install, USB\VID_18D1&amp;amp;PID_4E11&amp;amp;REV_0216&amp;amp;MI_01
    %CompositeAdbInterface% = USB_Install, USB\VID_18D1&amp;amp;PID_4E11&amp;amp;MI_01
    

    Note: The actual VID , PID, REV, and MI values must match what your actual hardware device ID says. You can get your specific values by plugging Glass into your USB port. Open up your Device Manager, browse to the Glass device that has a missing driver (marked with !). Right click, goto Properties –> Details Tab –> Hardware IDs dropdown.
    adb device

  7. Install the USB Driver to Windows.  Open up your Device Manager, browse to the Glass device. Right click and choose Update Driver. Browse to the above folder (Step 4) and proceed with the install.
  8. With Glass plugged in, go back to <your install directory>/eclipse and start Eclipse. Switch to the DDMS perspective (Window –> Open Perspective –> DDMS).
  9. You should see Glass in the Devices tab.
  10. Now you’re all set!

Google Glass Explorer Edition V2: Week 1 Initial Impressions

Last Wednesday, I got an invite to the Google Glass Explorer program. I ordered the Shale color with Mono earbud and the Active Shade. Google overnighted Glass to me and I’ve been using it for a week. Here’s some of my thoughts on Glass Explorer Edition V2.

Shale Glass

Physical Design

  • Build quality is solid. It feels like it I can take it with me safely on any daily routine.
  • Weight is light. I didn’t weigh it but, it doesn’t feel much different than a pair of sunglasses. The right side has the equipment and battery, but it doesn’t cause any unbalanced feel at all.

The Experience

  • There are no glaring bugs. Everything I tried generally worked well.
  • Tilt your head up or tap on the touchpad to turn on Glass. Once on, you navigate through a Timeline, which is a series of Live Cards. This is done by swiping forward or backward on the touch pad. It scrolls through Live Cards and is very intuitive to use. As you navigate through the LiveCards, you can tap once for further action. Of course, there’s the main Google card that constantly listens for you to say “OK, GLASS”.
    card
  • The current primary functions are: Navigation, Googling random stuff, Google Now, Messaging/Calling Contacts, and Photos/Videos
  • The entire experience is highly integrated with Google+. Anytime you plug in Glass, it auto syncs with your profile, backing up photos, pictures, Vignettes, etc. Any media you’ve taken can be Shared to G+ or Facebook, or simply Messaged to a contact.

Limitations

  • You have to install the MyGlass app to manage/control/tether Glass to your phone. The app itself feels like the least mature part of the Glass Explorer experience.
  • MyGlass currently only lets you add 10 total Contacts. This means all your direct shares, sends, etc can only work with 10 people. I expect this will change as Glass matures, but I’m not even sure why you have to “add” contacts. You should just be able to create a Group or Circle on the web and Glass should connect to everyone in it.
  • The biggest limitation is you have to set a default Messaging method for any contact. When you ask Glass to message/call that person, it will use that method only. For example, I set my friend Mike to Hangouts. All messages to him goto Hangouts – I can’t SMS or Email him until I change it in the My Glass app.
    Mike

Future

  • Google is on XE12 – version 12 of the monthly release cycle. I haven’t been through another release, but it seems each release brings massive features and improvements.
  • I started learning the Glass Development Kit (GDK). It’s still in preview mode release, but I’ll report back next week on my results.
  • Overall, $1500 is probably a tough sell for 90% of people. But, the experience is something that is so completely new and different, both on the social and technology aspects. I cannot wait to Explore more.

My personal favorite feature is the Vignette option. It overlays what you see in Glass so you can show people what your perspective is.

Here’s a few:
Vinette
Google

Thats it! Feel free to send me any questions about Glass XE. Next up will be Development / GDK stuff …

An Intro to Node JS

Recently, I had a chance to learn a new platform: Node JS.
Over the next few posts, I’ll illustrate some things I’ve learned but I wanted to quickly compare how Node JS differs from the traditional J2EE or .NET based web applications. As you can guess, Node JS a server-side platform, based in Javascript. It blends some of the advantages (or lessons learned) of many different platforms.

If you’re like me, you might wonder how does something normally used for client side features work as a entire web platform?

Well, Node JS doesn’t actually run straight Javascript. Developers write code in Javascript, but the code is actually compiled and runs as machine code, using Google’s V8 Javascript Engine. What this means is, applications written in Node JS are actually extremely fast and efficient. There is no intermediary Virtual machine like the JVM or Microsoft’s CLR framework.

Here’s a bit of sample code:

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World!!');
}).listen(8080);
console.log('Server is up!');

As you can see, its just Javascript. Node can be used to build nearly any application. It can read files, interact with Databases, manage User Interfaces, and much, much more. However, there is one key difference: Node is Single threaded. Node can only serve 1 request at a time.

So how does Node handle multiple users or requests?
Well, it has something called an Event Loop. The entire concept behind Node is basically to save incoming requests and deal with them later when some work actually needs to be done. Don’t hold resources until we need them. Here’s how it works:

  1. Accept request
  2. Save request to the Event Loop along with a Callback
  3. Deal with the request later
  4. When we’re ready to fulfil the request. Execute the Callback

This model is very different from the typical multi-threaded Java or .NET application. As requests come in, a typical Java App Server (ie. Tomcat) will create a thread and dedicate it for that user. This includes memory and CPU costs associated with the thread. Regardless if you are actually doing anything or just sitting there watching a page, the memory and CPU are allocated and held, until they are released. As requests pile up, those costs also pile up.

Node doesn’t do multi-thread
Instead, when Node gets a request, it serves the request and adds it to the Event Loop, along with a callback function (assuming you’ve written the code properly). All resources are then released until we actually need to service the request. No cpu, no threads, and no resources are allocated to the request. When actual processing is needed, the Event Loop is used to look up the callback function and processing will occur.

Node JS has great support
Dependencies are managed with the Node Package Manager (NPM). It’s a concept taken from Ruby GEMS or Java Maven. You install modules as you need them. Need mysql support? Execute: npm install mysql.

The bottom line
Node JS is great for high volume/transaction applications that require immediate, fast response times. It’s not great for highly complex application logic because Javascript isn’t built do do that.

How to read J2C (Java 2 Connector) entries in IBM WebSphere

IBM WebSphere has an easy way to configure security / login data and apply it to any resource, such as JDBC connections, Email providers, etc. You simply goto the IBM Admin console and open the Global Security section. You can add a JAAS – J2C entry and then apply it for resources requiring authentication. Seems like a great way to configure login/password data on your container and avoid hard coding, a config file, or in a database.

j2c

I wanted to apply the same concept for custom functionality written in java code then look up a J2C entry for login & password data. For example, I had an outbound REST call that needed a login. However, I couldn’t really find any obvious examples or documentation on how to look up J2C entries.

Here’s what I ended up doing, hopefully it will help save someone some time:

public static javax.resource.spi.security.PasswordCredential getJ2CData(String j2cAlias) throws Exception {
        String methodName = "getJ2CData";
        javax.resource.spi.security.PasswordCredential result = null;
        try {
            // ----------WAS 6 change -------------
            HashMap map = new HashMap();
            map.put(com.ibm.wsspi.security.auth.callback.Constants.MAPPING_ALIAS,j2cAlias);
            CallbackHandler cbh = (WSMappingCallbackHandlerFactory.getInstance()).getCallbackHandler(map, null);
            LoginContext lc = new LoginContext("DefaultPrincipalMapping", cbh);
            lc.login();
            javax.security.auth.Subject subject = lc.getSubject();
            java.util.Set creds = subject.getPrivateCredentials();            
            result = (javax.resource.spi.security.PasswordCredential) creds.toArray()[0];
       } catch(Exception e) {
    	   e.printStackTrace();
            log.severe("APPLICATION ERROR: cannot load credentials for j2calias = " + j2cAlias);
            throw new Exception("Unable to get credentials");
        }
       
        return result;
}

All J2C entries are uniquely identified by an Alias when you create them. You just need to pass in that Alias and the method should return a PasswordCredential object.
The object has UserName and Password fields you can easily retrieve:

	javax.resource.spi.security.PasswordCredential credentials = getJ2CData("SOME ALIAS");
	System.out.println(credentials.getUserName());
	System.out.println(credentials.getPassword());

Note, these values are all encrypted by WebSphere but once you retrieve them they will be in plain text. Security should still be enforced after retrieval.

Processing Form Posts with JAX-RS

Here’s a quick example on how to use JAX-RS to accept & process POST data, for example from a user submtting a Form.

First, you need to tag a method with the @POST annotation. It will instruct a method to respond to requests that are POSTED.

Second, the @Consumes annotation must be added so that JAX-RS will respond to Content-Type: application/x-www-form-urlencoded/. You do this by specifying MediaType APPLICATION_FORM_URLENCODED on the annotation.

Third, all form fields should be added as parameters to the method. The @FormParam annotation should be used to tag all parameters you expect the form submission to populate.

Here’s an example:


@Path("/test")
public class RestTest(){

	@POST
	@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
	public Response acceptForm(@FormParam("name") String name,
			@FormParam("password") String password){
		//@Context HttpServletResponse servletResponse

		System.out.println(name + password);
		Response res = Response.ok("<response>200</response>").type("text/xml").build();

		return res;
		//servletResponse.sendRedirect("../create_todo.html");
	}
}
	

This would accept data from a form that has two fields (name and password). When the form data is posted, JAX-RS will call this method and populate the proper parameters, by name. The form action should point to the REST path, so in this case /test.

If the request was AJAX based, you might respond with a XML string or plain text, as seen in the example. Your client can then proceed based on the response.

If it is a traditional request, you will probably want to forward the user to a new page. In that case, you can use the code that is commented out and change the method return type to a void.

		@Context HttpServletResponse servletResponse

		servletResponse.sendRedirect("/somewhere.jsp");
	

JAX-RS Services with Jersey

In today’s “Web Services” world, two of the common implementations are SOAP based or JAX-RS based services.
Today, I want to briefly discuss how to implement services in JAX-RS using the Jersey implementation.

REST is based on the idea that calls made to an application should have very specific purposes (ie. retrieving data, adding data, deleting data, or updating data).
REST calls should not try accomplish more than one at a time and JAX-RS follows this design pattern. The 4 HTTP methods: GET, PUT, DELETE, POST align with this.

Exposing a JAX-RS service is fairly simple. First, you add the Jersey Servlet to your web.xml:

  <servlet>
    <servlet-name>Jersey REST Service</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
      <param-name>com.sun.jersey.config.property.packages</param-name>
      <param-value>somePackage</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Jersey REST Service</servlet-name>
    <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>

Note, you should configure the to something that makes sense. For the example above, any URL under /rest/ will be processed by this servlet.

Second, you need to annotate a class with the @Path(“abcdefg”) attribute to configure the URL pattern the class will handle:

	//Sets the path to base URL + /hello
	@Path("/hello")
	public class JerseyRESTService {
		...
	}

This would make the JerseyRESTService class respond to all requests in this pattern: /rest/hello/. Note, you can further refine the URL pattern on each individual method in the class.

Finally, we need to implement our functionality within the class.
Retrieving data should be done with the GET method. You can return almost any type of data you wish. The response format is configured using the @Produces annotation.

	@GET
	@Produces(MediaType.TEXT_PLAIN)
	public String sayPlainTextHello() {
		return "Hello Jersey";
	}

This method only responds to a HTTP GET request at the URL pattern, /rest/hello. It returns a text result. If want XML you can set @Produces(MediaType.TEXT_XML). If you want HTML, you can set @Produces(MediaType.TEXT_HTML).

Also, if you want the method to return more than one type of data, you can add them as a list, to the @Produces annotation:

	@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})

When this happens, your request must specify the data type you are requesting in the “Accept” header.

Adding data should be done with the PUT method. It must consume whatever data is being added via the @Consumes annotation:

	@PUT
	@Consumes({MediaType.APPLICATION_XML, MediaType.TEXT_XML})
	public Response saveCar(JAXBElement<Car> c){
		Car myCar = c.getValue();
				
		Response res = Response.ok("<response>200</response>").type("text/xml").build();
				
		return res;
	}

Car is an object I defined with 3 properties (manuf, model, color). To invoke this method, I would need to make a HTTP PUT request to /rest/hello, with an XML body like this:

<car>
	<color>Red</color>
	<manuf>Tesla</manuf>
	<model>Model S</model>
</car>

The XML will be serialized using JAXB and converted to a Car object for easy access.

Removing data should be done with the DELETE method. If you need to tell the method what to delete, use the @Consumes annotation.

	@DELETE
	@Consumes(MediaType.APPLICATION_XML)
	public void deleteCar(JAXBElement<Car> c){
		Car myCar = c.getValue();
		System.out.println(myCar.getColor());
	}

This example is similar to the @PUT example. It will respond to a HTTP DELETE request at /rest/hello and consume an XML body that matches the Car object.

Updating data should be done with the POST method. I won’t go into that because it should be self explanatory at this point.

One last thing I want to mention is how to pass data via a URL request instead of part of the HTTP body. You do that through the @PathParam annotation:

	@GET
	@Produces(MediaType.TEXT_XML)
	@Path("{name}")
	public String sayXMLHello(@PathParam("name") String name) {
		return "<?xml version=\"1.0\"?>" + "<hello> Hello " + name + "</hello>";
	}

This method would respond to GET requests at /rest/hello. However, it will expect a single parameter after the hello. That parameter will be inserted into the @PathParam attribute, name. A request in this format /rest/hello/george would print “Hello george”. This is useful for looking up objects by ID.

You can also deploy JAX-RS services to respond to Form Data that is posted by a browser UI. Its very similar to the @PathParam example, but instead, you use @FormParam.

Next article will show an example …

My thoughts on JSF 2.0

I started working with JSF, version 2.0. I’m actually quite suprised with the framework – it’s pretty well designed and learning it was fairly easy.

JSF isn’t really that different from other MVC frameworks (ie. Struts) but I wanted to quickly talk about 2 differences I noticed immediately.

First, both frameworks are added to your web app through web.xml entries, however Struts is added as a Filter and JSF is added a Servlet.

Struts 2:

<filter>
	<filter-name>struts2</filter-name>
	<filter-class>
        org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
</filter>
 
	<filter-mapping>
		<filter-name>struts2</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

JSF:

 <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.jsf</url-pattern>
  </servlet-mapping>

This is worth noting because since Struts is setup as a Filter – you get native access to the Request/Response within the API and all Struts Actions. In JSF, you need to retreive it externally, through the ExternalContext object:

ExternalContext context = 
FacesContext.getCurrentInstance().getExternalContext();  

The second item worth noting is that JSF doesn’t really have a direct replacement for Struts 2 Interceptors. Interceptors allow you to implement logic once and apply it across as many Struts actions as needed. A common use case is Login functionality via Session protection.

In JSF there is no direct replacement. I looked at PhaseListeners, but those are for performing actions on the 6 possible events of a JSF request lifecycle. Instead, JSF lets you “scope” your ManagedBeans. The possible scopes are: RequestScoped, SessionScoped, ViewScoped, or ApplicationScoped.

So, to implement what Struts could do with Interceptors, I ended up creating a LoginBean and annotated it to be SessionScoped:

@ManagedBean
@SessionScoped
public class LoginBean {
	public String login(){ ... }
	public String logout(){ ...}
}

The idea is that this bean will be created and life in the session until we expire it (or it times out).

I have 2 methods: A Login and a Logout. The Login is self explanatory – it just performs Username/Pass authentication. ULB is a helper class that authenticates a user.

	public String login(){
		if(ulb.isValidUser(user)){
			System.out.println("Authenticated!");
			return "/secure/dashboard.jsf?faces-redirect=true";
		}
		else{
			System.out.println("Failed login!");
			return "/login.jsf";
		}
	}

The log out will clear the session. You could link this to a logout button or timer:

	public String logout(){
		System.out.println("logging out ...");
		
		FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
		
		System.out.println("session killed ...");
        return "/login.jsf?faces-redirect=true";
	}

There are two key points here: The call to invalidateSession() – this clears all session data for the current user. And the final return must specify ‘faces-redirect=true’ to instruct the browser to perform a new request for login.jsf. Once the new request is made there will be an empty session.

Finally, I added a Filter to protect all secure pages within my app (anything under the /secure/* url pattern). This filter is called BEFORE the JSF servlet is called. It looks for the SessionScoped bean in the session. If the bean is in the session, then proceed thorugh the filter chain as normal and serve the requested page. If the bean is not present in the session, redirect to the Login page to protect all secure assets.

web.xml:

	<filter>
	    <filter-name>userLoginFilter</filter-name>
	    <filter-class>somePackage.GlobalFilter</filter-class>	    
	</filter>
	
	<filter-mapping>
	    <filter-name>userLoginFilter</filter-name>
	    <url-pattern>/secure/*</url-pattern>
	</filter-mapping>

GlobalFilter:

public class GlobalFilter implements Filter{

	@Override
	public void destroy() {	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		
		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse res = (HttpServletResponse) response;

		LoginBean userManager = (LoginBean) req.getSession().getAttribute("loginBean");

		if (userManager != null && userManager.isLoggedIn()) {
			System.out.println("logged in ...");
			chain.doFilter(request, response);
		} else {
			System.out.println("Not logged in ...");
		    res.sendRedirect(req.getContextPath() + "/login.jsf");
		}		
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {	}
}

By default all SessionScoped beans are added to the session by their class name. You can change this using the @ManagedBean (name=”abcd”) attribute.

There are other ways to implement this logic but I wanted to make use of built-in JSF functionality 🙂