Wednesday, September 23, 2009

Google Web Toolkit + JSR 168 portlets

I want GWT. No, not JSF or other stuff like Struts (uugghh!) with JavaScript libraries, where you also have to care about sort of XML configs, JSP etc etc etc. Forget it. Use GWT.

But Enterprise wants portal with portlets (and me too). So how to make a "standalone" portlet in a nice .war file, while using GWT and such for this? I use GlassFish server and NetBeans IDE, so my sharing here towards these components only. Here is how I managed this to work:
  1. Get Portlet Container Driver from OpenPortal for a start and follow the instructions to let it get working on your GlassFish (simply run configurator jar and point directory and domain).
  2. Install Portal Pack in your NetBeans IDE.
Now, how to create a portlet with GWT:
  1. Create a new project, called "Java Web Application" in your NetBeans with GWT and PortalPack support enabled. Nothing else is needed for our example.
  2. Let's say, the name of our project is "GWTPortlet" and let's say it is in "net.maryniuk.portlet" package.
  3. NetBeans will generate for you a skeleton for your portlet. It is all what you actually need from non-GWT part.
  4. Create GWT client, that should be in "net.maryniuk.portlet.client". It will add some JavaScript and meta tags to "welcomeGWT.html" file, which you can find in "Web Pages" folder. Get these two tags (javascript and meta) and put them into "GWTPortlet_view.jsp" file, that you can find in "Web Pages/WEB-INF/jsp" folder.
  5. Change path in JavaScript tag the way it find generated JavaScript by GWT. For example, if your tag looks like: <script src="foo.js">, then change it to <script src="/GWTPortlet/foo.js">.
  6. Add a <div id="foo"></div> tag with an ID (in our example "foo") somewhere inside that JSP page.
  7. In your GWT entry point, change RootPanel.get()... to RootPanel.get("foo")... so then GWT can lookup an element with an ID "foo" and place itself there.
  8. Build your project. You're done — subdirectory "dist" contains your .war file with GWT portlet!
  9. Now just deploy it inside your Portlet Driver and see the result.

Here how it looks like for me:

Later on, after you sure your portlet works as expected, you can deploy it on Liferay or Sun Webspace:

Sunday, September 20, 2009

ORM sucks. Hibernate sucks even more.

For years, I already have my own opinion about ORM. The opinion is built on a quite a number of various trials, different practices, multiple measures and just a real life. Thus it sounds this way: ORM sucks big time and should not exist. Why? Shortly, because of noise ratio is tremendously high, while good factor is miserably low.

Being with a time, I would expect them get better. But what happens actually? Take a look at one of them: Hibernate — a powerful, high-performance Java persistence mechanism wannabe. I will tell you honestly: it sucks so much that any decent C++ developer would just hate Java as in whole. This thing just emphasizes whole Java "heaviness" and "bulkiness" that normally scares all tech people who are not just "an average Joe".

Hey, just look at all its glory: https://www.hibernate.org/116.html! Especially take a spot at the moment, when it keeps recreating collection. Now, how you gonna apply "Defensive Copy", once you have immutable objects? Think about of it. Or, take a look how even a silly CRUD application would suffer, once you've got "not-very-recent" object from the session! And the workaround for this? — right, get the object again just to make sure it is recent version...

What I am doing? I am using plain JDBC drivers with a little wrapper that does all the hassle and dirty jobs for me behind the scenes, leaving no XML to me at all. Footprint of the thing is very small and I've got it running on an embedded stuff as well as on a GlassFish cluster.

P.S. No, you're not gonna change any corporate RDBMS from one to another, like you would change your socks. But stuff, like JaQu would help a lot, once support all required dialects.

Friday, September 11, 2009

Upload file in SmartGWT

Upload a file to a server from your browser is not a big deal. But how to do it, if you have:
  • SmartGWT (a Google Web Toolkit with a SmartClient library)
  • It is LGPL, so no proprietary extension on a place
  • You don't want to use ExtGWT just only for one single upload function and thus risk your project won't really work on older browsers that are still might be in use.
  • You want it nicely done at background with a clean callback, of course. :-)
Here how you do it:
  1. In com.smartgwt.client.widgets.form.DynamicForm, set it to multipart by passing it Encoding.MULTIPART.
  2. Create an internal iframe, using com.google.gwt.user.client.ui.NamedFrame and call it, let's say "foo" (sure no better name came into my head now, LOL). Make it 1x1 pixel width and set visibility to false. It is not actually a thing user needs to see.
  3. Now use setTarget("foo") method to let your DynamicForm use that it as a target.
  4. Also use setAction(url-to-your-processing-servlet) to let DynamicForm actually send stuff there. You can do it like ("upload" — is your servlet accessible):
    .setAction(GWT.getModuleBaseURL() + "/upload");
  5. Now, add mouse click handler to your IButton and use submitForm() method out of DynamicForm instance object. It will send the form and that iframe we created earlier will receive a result. This way we achieve upload in background.
  6. Add a native JavaScript method, that will be seen normally in the loaded page, so parent windows can simply call it. That's exactly what do we need, when upload has been finished. More how to add JavaScript native methods, refer to GWT documentation about JSNI.
Now, time to write our Servlet for file upload. Great Java that comes with power station to your computer, yet has zero API to process multipart forms. This is just frustrating. But here is a cure: Apache File Upload library. Read the API how to use it. But generally, you simply iterate over fields and once you've got a filename out of the stream, you have the file. In this way you can send lots of files at once.

Your servlet should call back our method, we've defined in step #6. You simply set content type to text/html, write some simple html and a JavaScript that would call parent on window load — this way your iframe will call your client back. You may pass anything you want and respond anything. In my case it just closes upload dialog and says job done.

That's it. Implementation is up to you — use imagination... :-)

Sunday, September 06, 2009

Bye-bye, Apache. I won't miss you.

You've got an Enterprise Application Server — a GlassFish. At some cases it outperforms Apache, at some cases it is just equal. Yet, you out of luck to use it fully, just because you need running it on a port 80/443. You do not want to run GlassFish as a root user. On the other hand, running Apache or nginx (or whatever else) in front of it as a proxy is an ugly hack and unnecessary component in a front.

Interested to get a cure for this? OpenSolaris is your answer. :-)

Here what you need to do:
1. Wipe away your FreeBSD or Linux because these are impotent to do so (also good riddance anyway because at least for starter, Solaris Zones and ZFS and D-Trace just rules).
2. Install OpenSolaris (if you still want Linux — well, fsck your ext3 and just skip this blog entry).
3. Add a user, let's say "appserv", and disable login.
4. Modify its permissions this way:

usermod -K defaultpriv=basic,net_privaddr appserv

Now "appserv" user has permissions to run GlassFish on a 80/443 port, while be completely non-root. That's all, folks!

One more thing: Apache on your Linux usually runs from root anyway, then just drops privileges. It is much more secure, if your GlassFish runs within Solaris Zone and not as root from the very beginning.