Tuesday Mar 30, 2010

Authentication Without the Form

The nice thing about form-based authentication is that it allows a simple way for an application to let the container handle common security tasks. The bad thing about it is that, well, you need an HTML form. For a "Rich Internet Application" (RIA) that doesn't normally use JSPs or HTML pages, this means tacking on some extra files that don't have a natural fit in your application: the JSPs and/or HTML pages themselves, along with a deployment descriptor to specify the security settings. With the new features of the Servlet 3.0 spec, form-based login is no longer needed. Instead, your application can collect username and password credentials however you'd like and simply pass them to the container during an HTTP request. (Logout is equally simple.)

With form-based authentication, you would normally select some set of URLs and protect them with a security constraint. To access these URLs, a user would have to be authenticated and properly authorized. In some RIAs, this pattern no longer makes sense. For example, there may be few (or one) URL for the entire application. Instead, you can apply declarative security at the EJB level to protect any sensitive information (remember that EJBs can be used within a war file in Java EE 6!)

In this blog, I'll show an example of user authentication that doesn't involve an HTML form (or any JSP or HTML pages). There is a simple session bean acting as our back end service, and one of the two "hello world" style methods can only be called by a caller in the 'ADMIN' role:

    @RolesAllowed("ADMIN")
    public String getAdminMessage() {
        return String.format("Hello again '%s', it's great to see you!",
            context.getCallerPrincipal().getName());
    }

While the entire application is available in this zip file, you can see the full session bean, copiously commented, here. The rest of the sample application is simple as well: there is a main, servlet-based application class using Vaadin that includes these two panels (the authentication panel has been broken out into a separate class). See the code in the authentication panel for the full details, but the code to log the user in is this simple:

    String name = // retrieved from web UI
    String pass = // retrieved from web UI
    
    // exception handling omitted here
    // app.getRequest() returns the current HttpServletRequest
    app.getRequest().login(name, pass);

Logging the user out, of course, uses the logout() method instead. Here is the full user interface:

The ee6auth example application

In the "Actions" panel, there are two buttons that call a method in the EJB when clicked. The top button can be used whether there is an authenticated user or not. The other will result in an exception if there is not an authenticated user who is authorized to make the call (a user in the 'ADMIN' role). The exception is popped up in the browser to let you know what happened. Please see the three class files for comments describing the details of each part of the application. Note: while we're keeping this example simple, remember to use SSL any time you're dealing with user credentials such as passwords. The only other file in the application is a deployment descriptor that maps users in the authentication realm to the proper application role.

Before using the application, you need to add some users in the proper group in the default realm in the application server. The group we're using is 'ADMIN_GROUP,' but you can use any group you'd like as long as the mapping is correct in sun-web.xml. To help get you set up, here is a screen cast that shows how to create users in the default realm in GlassFish. We're keeping this very simple by using the file realm in the server, but you could use any realm you'd like. To use a realm other than the default one, add a web.xml file to specify it:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <login-config>
        <realm-name>your-realm-here</realm-name>
    </login-config>
</web-app>

Important note: because of this issue, you need a post-3.0 build of GlassFish v3. You can download a promoted build of v3.0.1 here -- to install, just unzip it. One more time, here's a link to the example application.

To build the application, you can use any IDE that supports Maven or use the command 'mvn clean package' to build it directly. Then deploy with the admin console or use this command (the --force option is only necessary on the 2nd or later deployment):

asadmin deploy --force --contextroot /ee6a <somepath>/ee6auth/target/ee6auth.war

Then you can access the application in a browser with http://localhost:8080/ee6a/. Let me know if you have any problems with the example. For any general questions, you'll get an answer more quickly at users@glassfish.dev.java.net.

I'd like to give a big thanks to Petter Holmström from the Vaadin team for his help, especially the article Creating Secure Vaadin Applications Using JEE6 that explains the steps needed to use regular form-based authentication (and a lot more) with a Rich Internet App such as Vaadin.

Thursday Mar 04, 2010

A Simple UI for Exploring Java EE

Java EE 6 has greatly simplified life for the EE developer. New annotations like @Startup and packaging options such as EJBs inside a war file save time and brain cycles. However, this makes writing the web UI for an application all the more time-consuming by comparison. If you're like me, you may have found yourself creating some entities and a session bean or two for controlling them, and then you just want to test it all out. Maybe step through the code in a debugger. Here's what I've done over and over -- it's simple, but it's silly. Just create a servlet, inject my session bean, and do something when the page is loaded:

    @EJB
    private MyBean myBean;
   
    @Override
    protected void doGet(...) throws ... {
        myBean.someMethod();
    } 

Then it's a simple matter to load the page in a browser and kick off the cool EJB code that you want to try. To check what really happened in the database, I use another tool (e.g., the database explorer in NetBeans). Simple, yes, but almost useless. In this blog, I'll show you a UI for testing Java EE services that is simple to write and trivial to adapt to your own applications. Not only can it provide a slick front end for calling business methods, but also access the database directly to show you what happened after the transactions have committed. As a bonus, it will show you the stack trace when something doesn't go quite right.

Yes, there are a number of tools that provide simple drag-and-drop interfaces for creating things like JSF front ends, but my goal is to create a UI with useful features as easily as I've created the session beans and entities. If you've ever written a Swing application, this should look very familiar. And there are no cryptic deployment descriptors, configuration files, or html/jsp templates needed. The only non-Java file in the application is a simple persistence.xml file.

To give you an idea before diving in, here is a screencast of the application in action.


Part 1: The Application

All of the application code is included in this zip file. I've included a pom.xml file so you can build with maven 2 without any additional setup. If you'd like to compile the sources and create the war another way, you just need the Java EE APIs in your classpath along with Vaadin, which comes in a single jar file that you can download from here. Look for the "Just the jar-file, please" text if you only want the one resource.

The back end consists of two simple entities, a SimplePerson and SimplePet. They both have a name, age, and one-to-one reference to each other. There is a PersonService session bean that has some normal CRUD operations on the person (which are cascaded to the pet). This bean is injected into the web UI -- see below for more details. Finally, there is a singleton bean loaded on startup that simply makes sure there is a pet named "Fred" in the database: FredCreatorBean. All of the classes are fairly simple and include comments to guide the reader. The persistence.xml file is very simple and uses a JTA data source jdbc/EE6Vaadin -- instructions for creating the resource are in part 2 of this blog. If you use a different JNDI name when creating the JDBC resource, make sure you change the name here. Also, after deploying the first time, you may want to comment out this line to avoid some warnings upon subsequent deployments:

    <property name="eclipselink.ddl-generation" value="create-tables"/>

For the presentation layer, I'm using Vaadin, a Java framework for creating rich internet applications. Since it's all Java, you write code that looks like Swing -- there are objects for layouts, widgets, and event handlers. GWT is similar, but with Vaadin the code you write stays on the server rather than being compiled into JavaScript objects. This is why I can inject a session bean into the presentation code to call my business logic. (Vaadin uses GWT for rendering the client in a web browser.) I should note that I'm not a Vaadin expert, so there may be better ways to create the UI. The Vaadin site has a nice forum for discussions like that -- I'll add a link here if there is any related discussion there.

Vaadin applications are loaded by a servlet com.vaadin.terminal.gwt.server.ApplicationServlet that you can configure in your web.xml file. This servlet creates the application object your write, initializes it, and the web page is displayed. In this example, I have included my own subclass of the Vaadin servlet in order to inject the session bean, and then I pass this bean to a custom constructor of my application. This also allows me to avoid having any configuration files except for persistence.xml. Here is the code included at the end of the main application class VaadinEE6App:

    /\*
     \* This code is adapted from the Vaadin example here:
     \* http://vaadin.com/wiki/-/wiki/Main/Hello%20GlassFish%203
     \*/
    @WebServlet(urlPatterns = "/\*")
    public static class Servlet extends AbstractApplicationServlet {

        @EJB
        private PersonService service;

        @Override
        protected Class<? extends Application> getApplicationClass() {
            return VaadinEE6App.class;
        }

        @Override
        protected Application getNewApplication(HttpServletRequest request)
            throws ServletException {
            return new VaadinEE6App(service);
        }
    }

In the application constructor, I store the EJB and create a couple class-level fields such as some panels that handle display and creation of the person/pet POJOs. The init() method creates some simple layouts, adds the panels, buttons, text field, etc., and connects the buttons to some actions for calling the back end. See the (hopefully) well-commented VaadinEE6App.java file for all the details. Everything there should look more or less familiar to a Java developer who has seen any Swing code.


Part 2: Setup and deployment using GlassFish v3

I'm using GlassFish v3 for this example, along with the JavaDB database that is included. In production, we would create the DB tables with SQL, but for a simple demo the JPA provider will do this for us. We just need to create the database connection pool, create a JNDI resource for it, and then build and deploy the application.

If you haven't already, download and unzip GlassFish v3, which supports Java EE 6. The database and server can be started with:

    asadmin start-database
    asadmin start-domain

Then visit the administration console at http://localhost:4848 -- the default username is admin with no password if prompted. On the left side, open the Resources->JDBC node and click Connection Pools. Click the New button and enter the following information, then click Next:

Step 1 of creating JDBC connection pool

In step 2, scroll to the Additional Properties table at the bottom. Delete properties as needed and enter information as shown below. Then click Finish.

Step 2 of creating JDBC connection pool

In the table above, the "create=true" property tells JavaDB to create the database when it is needed. The database name, user name, and password can be set to whatever you'd like, but you'll need to remember to change this information in the com.sun.bobby.ee6vaadin.presentation.SQLPanel class, which access the database directly.

Before moving on, you can check to make sure the database connection is working by clicking your new EE6VaadinPool entry in the Connection Pools list and then click the Ping button.

The last setup step is simple: creating the JDBC resource that points to the connection pool you just created. In the administration console, open the Resources->JDBC node again and click JDBC Resources. Click the New button, enter the following info, and click OK. If you choose a different name here, it has to match the jta-data-source element in the persistence.xml file in the application. That's all there is for setting up the database and server.

Creating the JNDI resource

Now you can create and deploy the war file. If using maven, you can use a simple "mvn package" from the ee6vaadin directory to build the war file. One more time, I'd like to point out that we have EJBs running without an ejb-jar file or an application .ear file! Good stuff.

To deploy, you can use the admin console or the following from the command line. The "--force" option isn't necessary the first time, but it is used in subsequent deployments to overwrite the deployed application. After your first deployment, you may want to comment out the table-creation property in persistence.xml and rebuild. Here is the command, but feel free to use whatever context root you'd like:

    asadmin deploy --force --contextroot /ee6v target/ee6vaadin.war

Assuming deployment proceeds without an issue, you can access the web application at http://localhost:8080/ee6v/ and give it a spin. It's not meant to include every conceivable feature -- there are even a couple "homework" features left for the user. But I hope it's enough to show how easily a web UI can be constructed that a) avoids configuration files, expression languages, templates, etc.; and b) can take full advantage of the Java EE server and use EJBs directly.

Update: I noticed I left an entity manager call in the code that isn't necessary at all. The 'else' block in the only method of FredCreatorBean looks like this:

        } else {
            // doesn't matter which one for this demo
            SimplePet fred = (SimplePet) fredPets.get(0);
            fred.setAge((fred.getAge() % 10) + 1);
            em.merge(fred);
            System.out.println(String.format(
                "Wow, Fred is %s years old already!",
                fred.getAge()));
        }

The 'em.merge(fred);' statement isn't necessary since the entity is still being managed throughout the method.

Wednesday Jan 20, 2010

Upgrading to GlassFish v3

As you probably know by now, Java EE 6 has made life simpler for developers (ear files not required, local EJB interfaces optional, singletons, all good stuff!). But of course you want to run your old applications as well. With GlassFish v3, moving them over to the newest application server is also a lot easier. In fact, you can upgrade a domain from GlassFish v2.1 or GlassFish v3-Prelude in zero steps. It doesn't get easier than zero, at least until the JSR for "Java API for Mind Reading" gets implemented.

By "zero steps," I mean you can simply start GlassFish v3 with an older domain and it will recognize the domain version and attempt to upgrade it before proceeding with startup. Below is the kind of output you'll see. In this case I've copied a v3-Prelude domain over to my v3 installation and called it "predomain" to not clobber my existing domain1.


hostname% asadmin start-domain predomain
Domain needs to be upgraded before it can be started.
Attempting upgrade now...
Upgrade was successful, starting domain...
Waiting for DAS to start ......
Started domain: domain1
Domain location: /Users/bobby/servers/glassfishv3/glassfish/domains/predomain
Log file: /Users/bobby/servers/glassfishv3/glassfish/domains/predomain/logs/server.log
Admin port for the domain: 4848
Command start-domain executed successfully.

Now before you start upgrading all your previous domains, you should remember that only developer profiles are supported in v3 -- clustering will come later. You should make a copy of your existing domain and upgrade that domain to be safe. Also, if you have installed any 3rd party jars in your glassfish/lib directory (as opposed to the domain's lib dir), you should move those over to your v3 installation as well. In fact, the above is exactly what the asupgrade tool does for you in v3. It will copy over the source domain, making sure not to clobber anything if there is a name collision. It will look for jars to move over, and then will run asadmin start-domain --upgrade <your_domain>. Be sure to check the server.log file for information on the upgrade, especially in case there were warnings or errors.

Check out the Upgrade Guide for more information on upgrading, especially the sections on which previous server version are compatible and notes on application compatibility between Java EE 5 and Java EE 6.

Thursday Jul 02, 2009

RIA without XML

One of the cool things I discovered at JavaOne this year was a framework for building rich internet applications (RIAs) called Vaadin. Besides being a very nice tool, they also had the good idea of giving away printed copies of their free book at the booth. Since my laptop battery time is limited, having a hard copy to read gave me plenty of time to learn about it between sessions, while waiting to meet people, while sitting at the bar, etc.

Vaadin is a web application framework that lets you write Java code to create your web pages. No JSP, no HTML (unless you want to), no XML, etc., and only one jar file needed for the framework. Somewhere in my reading or while talking to one of the Vaadin people, I came across the one exception to the "no xml" statement: Vaadin is still a Java EE application, so of course there is still a web.xml file needed to deploy an application. My first thought was, "We can fix that, right?" So for no particular reason, here is how to create a rich internet application with no XML files at all using Vaadin and Servlet 3.0 inside GlassFish v3 Preview.

To get rid of the web.xml file, use the @WebServlet annotation on your servlet class. Vaddin is open-source, so of course you could add it to the class and rebuild it. But let's do the proper thing and subclass the servlet. I've put it in the same package as the parent in case it's looking for any resources relative to the package. Here is the entire class:

package com.vaadin.terminal.gwt.server;

import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;

@SuppressWarnings("serial")
@WebServlet(
    name = "Noxml Application",
    initParams = {
        @WebInitParam(name = "application",
            value = "com.example.noxml.NoxmlApplication")
        },
    urlPatterns = { "/\*" }
)
public class EE6ApplicationServlet extends ApplicationServlet {
    // nothing here
}

Pretty simple stuff. Thank you Servlet 3.0. Now, to give you a sense of what Vaadin is like and to show that this really works, here is the application I wrote. It simply adds a couple blocks of text to the web page and a button. Clicking the button switches the text between the two lines (called "labels" in Vaadin). Here is the entire class:

package com.example.noxml;

import com.vaadin.Application;
import com.vaadin.ui.\*;
import com.vaadin.ui.Button.ClickEvent;

@SuppressWarnings("serial")
public class NoxmlApplication extends Application {	
    /\*
     \* A very simple application with two labels and a button.
     \* To keep this short, I've added an anonymous listener
     \* for the button that calls my very exciting swap method.
     \*/
    @Override
    public void init() {
        // create components
        Window mainWindow = new Window("Noxml Application");
        final Label label1 = new Label("Hello RIA.");
        final Label label2 = new Label("Goodbye XML.");
        Button button = new Button("Very Exciting Button",
            new Button.ClickListener() {
                public void buttonClick(ClickEvent event) {
                    swapText(label1, label2);
                }
            });

        // add 'em
        mainWindow.addComponent(label1);
        mainWindow.addComponent(button);
        mainWindow.addComponent(label2);

        // add window to the application
        setMainWindow(mainWindow);
    }

    // where is my tuple unpacking?
    private void swapText(Label l1, Label l2) {
        Object temp = l1.getValue(); // a string in this case
        l1.setValue(l2.getValue());
        l2.setValue(temp);
    }
}

That's all there is to it. My entire web application contains only three classes (one is the anonymous inner class in NoxmlApplication), a single jar file in the lib directory, and no xml files. It's not much to look at since I kept it simple, but all of the Ajax requests/responses are taken care of for me and I just wrote a little Java code. Speaking of not much to look at, here is a very exciting screen cast of the web application in action.

I've included the Vaadin links above. If you'd like to try out GlassFish v3 and the great developer features of Java EE 6, here are some instructions on setting up the application server with NetBeans and with Eclipse (the latter only shows v3 Prelude, but you can use a v3 server as well). For more on creating a servlet using the 2.0 annotations, see Arun's blog. Have fun.

About

Whatever part of GlassFish or the Java EE world that catches my attention. (Also, go Red Sox.)

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
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
   
       
Today