Bridging the Gap – The File Upload saga continues…

Last week on LOST….
What’s the issue with a File Upload control in a WebSphere Portlet (and please, if you’ve done something like this and know an easier way, I’m all ears)?

WebSphere portlets aren’t keen (they don’t listen for) forms that use multi-part encoding. The portlet action gets ignored, your file delivered to the heavens and your customer left feeling blue (IBM Blue?).

So the first part of the two part problem is getting the file up to the server. The second involves what to do with it once it arrives. The image files needs to be persisted to the user’s Member record inside LDAP.

Portal provides a nice facade for dealing with Members. It’s called WMM (WebSphere Member Manager). WMM masks things like attribute mapping and LDAP syntax, it’s just the gate keeper. Works nicely…provided you’re within the Portal context (making a Portlet request).

Let me try tying the two issues together with the solution I devised.

The Portlet now calls an external (from the Portal context) Servlet to grab and parse the file (using Apache’s wonderful FileUpload library from their Commons project).

So now I have the file…how do I get it into a valid WMM context (knowing the receipt of the file came via HTTPServletRequest rather than Portlet Request)?

Here’s a little pattern I tried, using Observer. I call it the PhotoBooth/PhotoLab pattern.

When the portlet’s Session bean instantiates from the Portlet, I create an Envelope. The Envelope contains the user’s unique id and a property to house the image (byte[]). The Envelope is then ‘dropped off’ at the PhotoLab, a singleton with a Map of Envelopes. The Map’s key is the unique ID. So the empty envelope has been left at the PhotoLab. When the FileUploadServlet receives and parses the file, it asks the PhotoLab for the envelope (the key was a parameter passed to the FileUpload servlet). The photo gets placed into the envelope and then guess what happens?

Yep, the trusty old Observer pattern kicks in. When the image setter is called on the envelope, the state gets changed (calling setChanged(); ) and then Observers are notified: The Session bean’s update() method gets called and the envelope is dropped of.

The Portlet now has the photo and can use WMM to persist it when the user clicks ‘Save Profile’ (via PortletRequest)

I’m happy with how it works, I just need to clean up the implementation a little bit. Ted O’Grady did a great job of defining the code’s current state as the Speculative Solution…time to clean that speculation up a bit and get the Durable code in place.

Advertisements

2 Portlet Specs and URL encoding…

Still working on the file upload portlet for my current client. I’ve decided to change gears and parse the request in a servlet rather than the portlet itself. Why? I think it will allow me to create a second form on the Portlet’s JSP and encode it in whatever way I need.

The portlet complies with JSR168, not the WebSphere portlet API. Seeing as it’s portal, I need to encode the URL to the servlet…easy enough.

String servletURL=response.encodeURL("/UploadServlet");

and pass this variable into the form’s action attribute and I’m done.

…except…I get a “Page Not Found” error and the following shows up on the console:

Servlet Request Processor Exception: Virtual Host/WebGroup Not Found ….

hmmm

So I could go into everything I tried in figuring out why this very simple little example didn’t work but I’ll save you the time and anguish. Turns out the IBM’er beside the IBM’er I was working with knew what the issue was….had he chimed in a little earlier (hint for the future Jimmy), we would have saved a little grief but I’m still grateful for his involvement.

Turns out a JSR168 portlet needs an additional bit of magic to encode a url. You need to use the following:

String servletURL=response.encodeURL(renderRequest.getContextPath()+ "/UploadServlet");

with renderRequest doing the heavy lifting. Add that and you’re gold.