Archive for the ‘java’ Category

Useful Patterns for BlazeDS

Tuesday, June 3rd, 2008

Neustadt, Dresden, Deutschland

While running the Los Angeles Flex Users Group I got a lot of questions from people about how BlazeDS could fit into their existing infrastructure.

Typically, they will have an application container, such as JBoss, or maybe just a servlet container, like Tomcat, and a SQL backend. Usually MySQL or PostgresSQL. JSPs are used for the presentation layer and, sometimes, they may use Struts or SpringMVC as a web application framework. If you’re using ColdFusion this post is likely of little use to you.

Many programmers are understandably weary of introducing yet another component into their system and BlazeDS sounds like such a complex component that it’s often mistaken for a standalone application container that doesn’t readily integrate with standard Java application containers. This couldn’t be further from the truth. Those programmers who follow the bundled BlazeDS examples get stuck trying to figure out how to expand the example to fit their application or how to even start from scratch.

Let’s tackle the first misconception, that is, that BlazeDS doesn’t play well with Java application containers. To put it simply, BlazeDS is configured as a standard servlet. When a Flex client wants to make a request to a BlazeDS server it will issue a POST request to a defined servlet path. That path is whatever you configured the BlazeDS MessageBrokerServlet to. Flex sends the request as an AMF binary payload or an XML version of AMF. I’m glossing over some details but just knowing that you can access BlazeDS as a servlet is a good starting point for figuring out how you can start integrating BlazeDS into your existing application.

What this means to you is that BlazeDS can use container authentication or even work with Spring.

Let me make it even more clear by putting some sample configuration and code.

Here’s the part of the web.xml in which you declare and configure the MessageBrokerServlet:

<servlet>
<servlet-name>MessageBrokerServlet</servlet-name>
<display-name>MessageBrokerServlet</display-name>
<servlet-class>flex.messaging.MessageBrokerServlet</servlet-class>
<init-param>
<param-name>services.configuration.file</param-name>
<param-value>/WEB-INF/flex/services-config.xml</param-value>
</init-param>
</servlet>

Here’s the part where you map the MessageBrokerServlet to a path:

<servlet-mapping>
<servlet-name>MessageBrokerServlet</servlet-name>
<url-pattern>/messagebroker/*</url-pattern>
</servlet-mapping>

The file “services-config.xml” is the primary configuration file for BlazeDS. Here is where you define a “channel”:

<channel-definition id="amf" class="mx.messaging.channels.AMFChannel">
<endpoint url="http://localhost:8080/sample_bds/messagebroker/amf"  .... />
</channel-definition>

This tells the Flex client where to make an HTTP POST request when using the “amf” channel on a RemoteObject, for example.

In fact, try it out on a browser, startup BlazeDS and point to htp://localhost:8080/blazeds/messagebroker/amf/

You’ll get a blank page. That’s a good thing!

The next question I usually get is, “do I have to dump my JSP/WebServices/Struts in order to use BlazeDS?” The answer is definitely no! In fact, if you have a JSP AND a WebServices front end to your application you’re a good bit along the way towards integrating BlazeDS. The reason for this is that if you have two front-ends to your application, and these two front-ends share some functionality, then you have probably structured your application in such a way (using a Service Layer, for example) that makes it easy to add a third front-end.

So what architectural patterns are useful for BlazeDS? To cut to the chase, I use Service Layer, Data Transfer Objects, and Mapper (or Assembler) on the server side. I’ll have a post on what I use on the client side later.

If you have played around with BlazeDS or used it to create a production application you’ve probably followed the examples bundled with the turnkey solution. And you probably have a hunch and instinct about how to create your app. I’m guilty of jumping right in and starting to code from my gut, but after a few days of learning a technology I like to step back and formalize my approach. My first place to consult is Martin Fowler’s Patterns of Enterprise Application Architecture (PEAA), and Design Patterns: Elements of Reusable Object-Oriented Software (Typically referred to as The Gang of Four Book, or GoF).

Service Layer

A Service Layer can have many methods, each using a variety of domain objects and models. Service Layer have application logic, like telling an emailing component to notify administrators that a payment has been processed, while delegating the business logic to the domain models. It’s pretty easy to figure out what types of methods a Service Layer should support; you can use the user interface as a guide to what sorts of things a client can do or you could base this off your use cases, if you’ve taken the time to do this.

The defining characteristics of Service Layers are the following:

  • Defines application boundaries
  • Defines available services from the perspective of interfacing clients
  • Encapsulates business logics
  • Provides convenient place for handling transactions, logging, etc.
  • Prepares the response appropriately for the client

That last one brings me to the next pattern I use.

Data Transfer Objects

These are objects that have a bunch of properties, contain no domain logic, and may be structured in a simple hierarchy. When I first started with BlazeDS I was using an Hibernate as my object-relational mapping (ORM) solution and so I was happily transporting the objects I got from a database straight through BlazeDS and over to Flex. Some of my objects had few methods for domain logic, some had more. Few had a complex hierarchies.

Once I started adding parent child relationships and collections then I suddenly encountered a problem where retrieving one of these objects would cause Hibernate to recreate a pretty huge hierarchy. Just as bad was a problem with transactions; when you’re about to send an object down the wire, BlazeDS will call each of its getter methods and each of those Object’s getter methods in turn. This is why it recreates entire hierarchies, but if you close the Hibernate session before BlazeDS has a chance to get to these methods then you’ll get an exception because the Hibernate proxy object can’t get a hold of a session with which to get the rest of the objects out of the database.

There are ways to go around this, such as using the Open Session in View approach, and that works well, though I found it felt awkward because of the name, since the “view” part of this is that hibernate objects are being used by the view and so the session should not be closed, but I also didn’t need to load all the objects that were connected to the one measly object I wanted to read.

I could have used the custom serialization method specified here: Using custom serialization between ActionScript and Java.

So, the simples solution I finally adopted was to use Data Transfer Objects. Characteristics of DTOs are the following:

  • May contain aggregated data
  • Fields are simple, such as primitives, or other DTOs

The pain of adding DTOs is that you now have to transform some of your domain models, in my case, for example, some of the objects gathered with Hibernate into DTOs. So you have to use the Assembler (or Mapper) pattern. An Assembler can take care of:

  • Knowing how to transform an object into a DTO
  • How to reconstruct hierarchies for DTOs
  • Keeps the domain model independent of external interfaces
  • May make use of more than one assembler per dto based on the semantics of the request.

Now I have no problem with building deep hierarchies when I only need one object. If I do need the complete hierarchy I can use a different assembler that knows how to reconstruct that. That’s what the last bullet point on that list is talking about; if it makes sense in one request to bring in all children and grandchildren objects then an assembler can know how to do that, if, instead, all you need, is the one object, then that’s all the other assembler needs to do. In my case, I now had better control over when I could close the session without having to worry about Session closed exceptions.

An additional benefit with respect to BlazeDS and Flex is that the RemoteClass mapping from Flex to Java can always map to DTO and you won’t have to worry about changing your actual Domain Objects and having those changes reflected in the mapped actionscript class; if you remove a property from your domain object then the Java compiler will complain because the assembler will be unable to access that property. You’ve caught the error earlier on.

I didn’t talk about the client side much. I’m working on another post that will address that side.

BlazeDS, Spring, and Acegi Security - Part 3

Sunday, June 1st, 2008

Update: The “start”-method-not-getting-called bug is now a filed in the adobe bug tracker: http://bugs.adobe.com/jira/browse/BLZ-190

This post is another baby step in getting acegi/spring security and blazeds to work together. The whole purpose of these exercises is to for acegi to handle authentication/authorization and destination security. Even bypassing container security.

In the last part I talked about how I was stumped by the LoginCommand and how the “start” method is never called. The reason I want the start method to be called is so that I am passed a ServletConfig and from there I can get access to the ServletContext, and thereby access to the Spring WebApplicationContext but unfortunately this method never seems to get called. I traced the BlazeDS source in SVN, not very thoroughly I should admit, and never found a spot where the start method gets called.

That’s not such a big deal because I can get access to the ServletContext by using the FlexContext singleton. I’m not generally a fan of singletons but what the hell; if it gets it to work =p

Anyway, here’s a brief outline of my AcegiLoginCommand, which extends AppServerLoginCommand:

.. class AcegiLoginCommand extends AppServerLoginCommand …

public AcegiLoginCommand() {
    initAuthenticationManager();
}

private void initAuthenticationManager()
{
    ServletContext servletContext = FlexContext.getServletContext();
    String beanId = servletContext.getInitParameter("loginCommandBean");

    if (beanId == null) {
        beanId = "authenticationManager";
    }

    WebApplicationContext context =
        WebApplicationContextUtils.getWebApplicationContext(servletContext);

    authenticationManager = (AuthenticationManager)context.getBean(beanId);

    if (authenticationManager == null) {
      throw new RuntimeException("AuthenticationManager could not be found.  Tried beanId='"+ beanId+"'");
    }
}

The LoginCommand needs access t othe authenticationManager so that it can pass it call the manager’s “authenticate” method. To make it more configurable, I added a little bit of code that will get the bean name from a web.xml init-parameter.

Finally, my “doAuthentication” method looks like this:

public Principal doAuthentication(String username, Object password) {
  Authentication authentication =
        new UsernamePasswordAuthenticationToken(username, password);
  authentication = authenticationManager.authenticate(authentication);
  SecurityContextHolder.getContext().setAuthentication(authentication);

  return (Principal)authentication;
}

I don’t need to override doAuthorization because when I’m doing MethodSecurityInterceptor, that class takes care of looking at the Authentication token’s “GrantedAuthority”es to see if they can execute the method.

That’s pretty much it. I need to figure out the extent of the security integration. I know that at the moment the authentication will not work on RTMP channels.

A good explanation and example for Spring and BlazeDS is important for driving adoption of BlazeDS into environments that run on Java. I know a potential client of mine is looking into using BlazeDS as a transport layer for a product they have running on a Tomcat container. They want to try following established practices in Java and want to use off-the-shelf, tried-and-true technologies like Spring and Hibernate, and having information on using these with BlazeDS would make them more confident when adopting BlazeDS.

Hope this helps. Also, I just found out someone else had documented a similar approach at this blog post:

http://blog.f4k3.net/fake/entry/acegi_logincommand_for_fds

BlazeDS, Spring, and Acegi Security - Part 2

Friday, May 30th, 2008

In an earlier post I talked about BlazeDS and Spring Security and gave a high level overview of how to get a BlazeDS destination to be secured with Acegi security instead of BlazeDS’ security. However, I overlooked a simple thing that would make the whole system play nicer with Flex. That is, I didn’t translate the authentication exception into a flex.messaging.SecurityException and did not set its code to Client.Authentication. It’s not really necessary to do so as you will get an error message anyway because BlazeDS catches Acegi’s exception and wraps it in a MessageException, but it’s nicer if it’s wrapped in a semantically appropriate exception.

I first thought I’d add an exceptionTranslationFilter to my filterChainProxy but this doesn’t work because BlazeDS wraps the exception after the proxied bean invocation and doesn’t let it percolate to the container filter. Duh! That took me about an hour to figure out.

The next step would have been to pass an afterInvocationManager to the method SecurityInterceptor but this guy never gets called when an exception occurs.

So, the next step, which I think is kinda hacky, is to extend the MethodSecurityInvocation class and override invoke. Catch any AuthenticationExceptions and translate them into SecurityExceptions so that BlazeDS can transfer that exception to Flex as appropriate. Here’s the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<pre lang="Java" line="1">
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
    try {
        return super.invoke(mi);
    } catch (AuthenticationException ae) {
        SecurityException se = new SecurityException();
        se.setMessage(ae.getLocalizedMessage());
        se.setRootCause(ae);
        se.setDetails(ae.getLocalizedMessage());
        // This is an authorization error instead of an auth error 
        if (ae instanceof InsufficientAuthenticationException) {
            se.setCode(SecurityException.CLIENT_AUTHORIZATION_CODE);
        }
        else {
            se.setCode(SecurityException.CLIENT_AUTHENTICATION_CODE);
        }
        throw se;
    }
}

My next step is to bypass BlazeDS’s authentication mechanism and just do it through Acegi. I’ll keep you posted.

Flex Data Services and Tomcat Authentication - Part 2: Simple webapp and Eclipse Tomcat Debugging

Friday, January 19th, 2007

It’s warming up in Los Angeles. Yay! So, before I take off for a nice walk along the beach I bring to you the second part in my series of flex+tomcat posts.

In this post I’ll create an Eclipse project for a simple web app and then hookup the Eclipse debugger to a possibly remote instance of Tomcat. The files are somewhat long so I’ve created a zip file that you can download and use. You’ll have to modify the paths to match your system paths.

I’m using Eclipse 3.1.2 on Windows XP with Java JDK 1.5.0.10 and the Tomcat from the previous post. My tomcat installation resides at “c:\java\tomcat\”
Startup Eclipse and create a new Java Project and call it “flex-auth-webapp”. Accept the default options.

Eclipse projects will output .class files either to the source directories or to a “bin” directory that is created during the project creation phase. When you modify a .java file in Eclipse it will recompile the file into the destination build directory. I want the class files to be generated in my webapp directory so that Tomcat can see the class file changes and then reload the webapp. This cuts down my write-test cycle because I don’t have to perform any manual or extra steps when I make a source modification. That’s the motivation for the following step: Create a webapp directory in the tomcat/webapps directory and then have Eclipse output class files into this folder.
In Eclipse, right-click on your new project’s folder and select New > Folder.

Click on the “Advanced >>” at the bottom of the dialog.

Check the checkbox that says “Link to folder in the file system”

Click the “Browse …” button.

Navigate to the tomcat webapps directory. Should should end up in c:\java\tomcat\webapps\ or whatever your path is.

Create a new directory called “flex-auth-webapp”. Then navigate into this directory, and create another directory, call it “WEB-INF”. Navigate into this directory and call it “classes”. You should end up with the following path:

c:\java\tomcat\webapps\flex-auth-webapp\WEB-INF\classes

If you don’t like clicking all these buttons it’s easier to just use the command line window and navigate to the path and then mkdir the path.

In the “Folder Name” text field enter “tomcat-classes”.

When you’re done, click “Finish”

You’ll see the folder inside the path with a little arrow that means this is a linked folder, outside of the project’s workspace directory.

Now we have to tell Eclipse to use this new folder, tomcat-classes, as the output folder. So, right click on the project’s folder and select “Java Build Path”. Select the “Source” tab. At the bottom, in the “Default output folder:” section click on “Browse…”. Pick “tomcat-classes” from the list and click OK. Click “OK” again on the project properties window.

Copy the files in the archive into your project. You should end up with the following project structure:

Tut 2 Directory Structure

Let’s test that the project can be accessed over the web. I use ant for making my build process easier. It’s a great tool and if you don’t use it then first get familiar with it: http://ant.apache.org/
Open up the ant.properties file and change the path as appropriate for your system. You’ll probably only have to change the tomcat.home property. Be careful of extra spaces at the end of these paths because ant won’t take off trailing spaces.
After you’ve properly setup your paths, right click on “build.xml”, select “Run As > Ant Build …”. From the dialog, make sure that the target “deploy” is checked. It probably is because it’s the default target. Hit “Run”. Watch the Console for any errors. If you see errors, it’s very easy to click on the error message and jump to the line in the build.xml that threw the error. If everything went well there should be a success message at the end, and if you go to the c:\java\tomcat\webapps\ directory you should see a directory called flex-auth-webapps with the following directory structure:

Web App Structure

If you haven’t already, startup tomcat and the go to the following location:

http://localhost:8080/flex-auth-webapp/

You should see the following page:

Web App Page

This is just a simple jsp page that creates a new class DebutTest and calls a method in it. I did this just so we could test the debugger in the next section.

Debugging With Eclipse.

There are several plugins available for eclipse that let you star and stop an instance of Tomcat from inside eclipse. One of these lets you debug jsps. You can find them on google. It’s not that hard to hook up Eclipse, however, so, why not do it manually. So, here goes:

Shut down tomcat if it’s still running. Then open up setenv.bat (or setenv.sh if you’re on a unix machine). Add the following lines:

SET JPDA_TRANSPORT=dt_socket
SET JPDA_ADDRESS=localhost:8000

This tells the JVM that will run Tomcat to use the socket transport during debugging and to listen to connections on port 8000 at the localhost address.

Now startup tomcat with the following command line:

catalina.bat jpda run

This tells tomcat to start in debug mode and to run on the same window. The first line of the console should say something like this:

“Listening for transport dt_socket at address: 8000″

This means Tomcat is now waiting for any debugger connections on port 8000.

Go over to Eclipse and select: “Run > Debug …”

In the dialog, look for the Configuration titled “Remote Java Application. Select it and click on the ‘New’ button.

Select the Project to “flex-auth-webapp”, select the Connection Type to “Standard (Socket Attach)”. In the connection properties make sure the Host is “localhost” and the Port is “8000″.

Click Debug. It will look like nothing will happen but if you go over to the Debug perspective you should see an instance of the Java HostSpot hooked to localhost:8000.

Let’s go put a breakpoint in a file and have Tomcat stop at that breakpoint. Open up the file test/DebugTest.java. Add a breakpoint on line 8. In a browser, navigate to http://localhost:8080/flex-auth-webapp/. Go back to Eclipse and the debugger should now be stopped at line 8 of DebugTest.java. You can now step through the lines and do whatever you’re used to doing while debugging java apps, including inspecting the variables, changing their values, adding watches.

Next Steps

In the next post I’m going to create a service and a flex app that accesses this service. This will be the app we’ll use to explore authentication and security in a Tomcat+flex application.

Ok, I’m off for a walk.

Code

flex-auth-webapp.zip