Friday, October 09, 2009

java.io.IOException: Not enough space

Seen that?
Caused by: java.io.IOException: error=12, Not enough space
at java.lang.UNIXProcess.forkAndExec(Native Method)
at java.lang.UNIXProcess.(UNIXProcess.java:53)
at java.lang.ProcessImpl.start(ProcessImpl.java:65)
at java.lang.ProcessBuilder.start(ProcessBuilder.java:452)

Yes, I hate this too. First of all, that's not what you think. It means not enough swap, because your Java suddenly wants lots of GB of memory. When Java launches fork, it starts a new VM as a fork from current process. Thus for a short period between fork and exec, there is two instances of your stuff. That's temporary though. Exactly at this moment your system cries for a lack of swap.

Now, how to cure this on Solaris as long as you're using old UFS. Simply add some space as a file to a swap:
mkfile 500m /opt/var/my.swap
swap -a /opt/var/my.swap
Uhm, OK. That's old way... But that won't work on ZFS as this file system can not use files for a swap. :-) To use this with ZFS, make another ZFS filesystem in your rpool. That's how I am using in my OpenSolaris global zone:
zfs create -V 2G rpool/additionalswap
swap -a /dev/zvol/dsk/rpool/additionalswap
To see the result, issue swap -l command and it will show you that new FS has been added to your swap, something like this:


swapfile dev swaplo blocks free
/dev/zvol/dsk/rpool/swap 182,1 8 2095096 1823456
/dev/zvol/dsk/rpool/additionalswap 182,3 8 4194288 4194288

Now you're safe. :-)

GlassFish + OpenDS = No Pain

You want LDAP and appserver work with it. But you also remember all the voodoo bloody massacre you've experienced, once you've tried to setup OpenLDAP and now looking to shoot its developers. Calm down, go an elegant and easy way instead.

My config is pretty much simple OpenDS on an OpenSolaris zone. Nothing special for OpenSolaris zone — just setup it as usual and configure OpenDS as you would do on a global zone. That's my scenario:

  1. Login to your OpenSolaris global zone and install OpenDS from IPS:

    pfexec pkg install opends

  2. Now, login to your zone where OpenDS is supposed to run and add an user, who will use it. In my case it is "opends" user (and a same group) and I've decided to put it separately, where entire OpenDS instance is:

    pfexec useradd -md /opt/opends/home opends

  3. I've also decided that OpenDS instance is running in /opt/opends/instance folder. So run configuration against "opends" user and that folder like this:

    pfexec /usr/opends/configure \
         --instancePath /opt/opends/instance \
         --userName opends \
         --groupName opends


  4. Great. Now is a time to finish it. :-) Login as "opends" user and run "setup" command. Please note, it will try run Swing GUI for you, so either SSH into your box with X11 forwarding or use command line mode ("--cli" option) and follow these few simple instructions (setup DN, admin password, port etc):

    /usr/opends/setup --cli

  5. There is no fifth step — your LDAP is up and running. Need more info about details and such? Here: https://docs.opends.org/wiki — depending on your version...

OK, we have LDAP done in four steps. Now we want GlassFish use it as realm. That's also elegant:

  1. Login into your GlassFish admin console (by default on 4848 port).
  2. Go to Configuration → Security → Realms and add one just straight-forward as it is:
    1. Set name to "OpenDS", let's say.
    2. Use class: com.sun.enterprise.security.auth.realm.LDAPRealm
    3. Set JAAS context as "ldapRealm"
    4. Set Directory to "ldap://your.host:port". If you're using SSL to make things thrice slower while no much change to security itself (because it is an internal network), then use scheme "ldaps://...". :-)
    5. Use your base DN that you've put to your LDAP, e.g.: dc=your,dc=host,dc=com or something like this.
    6. And then use your group whenever it is: ou=groups,dc=your,dc=host,dc=com etc.
  3. There is no third step.

Easy, is it? :-)

Thursday, October 01, 2009

IT Market Nowadays


Here I just thought how job specification would look like, if IT guys would need to drive a regular city bus. :-)


Job Specifications

City bus driver from 9:30AM to 3:30PM.

Job Type

contract, part time.

Salary

Negotiable, but no more than $1000 per month.

Requirements

Bicycle skydiving, motorcycle, car and truck licenses, repair and maintenance knowledge, tramway and trolley-bus at least 5 years experience. Additionally, ultra-high demolition excavators such as Caterpillar 385D operation, haulage and earthmoving equipment on off-road vehicles experience, military armored bulldozer D9, rocket launcher truck and tank Abrams driving at least 1 year experience.

Successful candidate also should have knowledge flying F16, PhD in engine manufacturing and engineering, license for shooting magnum .44 gun and must have at least 5 (five) jumps with a parachute.

Having 500 hours flight as a crew captain with Boeing 747 is a plus. Being an astronaut team leader with at least month in a space is a plus. Knowing some specific details about Apollo 13 and landing on a Moon is a plus, but not that much necessary, however it might affect salary negotiations.

If you are interested, we are waiting you for an interview. You will have 10 interviews, 4 tests and 2 brainbench in a gym.

Other notes

You must not be married.

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.