Thursday, March 31, 2011

Useful things I've discovered about Glassfish (especially embedded glassfish) lately

I've been working with / struggling with Glassfish a lot lately. The documentation leaves much to be desired, so there are a few bits and pieces you might not know that might come in handy.

These notes refer to Glassfish 3.1.

Glassfish properties

Use asadmin list-commands to list supported commands, and asadmin help commandname for details. Read all of asadmin help since it contains important info the subcommand references should mention, but don't.

Use asadmin list * to list all Glassfish properties. This is important when working on embedded, because most configuration can only be done using asadmin set. In embedded glassfish you can run this on your embedded instance using:

commandRunner = glassfish.getService(CommandRunner.class);
CommandResult result = commandRunner.run("list","*");
System.err.println("Got command result: " + result.getOutput());

Use the get and set commands to manipulate the objects you discover with list.

Creating users in a file realm

Creation of users non-interactively - for batch/script use - is possible using the asadmin create-file-user command. It's not possible to pass a user password to the command directly because it rejects the --AS_ADMIN_USERPASSWORD argument with "passwords not allowed on command line". You must create an asadmin password file that contains the new user password to set as well as the admin password required to use the admin command. See asadmin help for details on the password file's weirdness and on the AS_ADMIN_USERPASSWORD variable. help create-file-user doesn't mention it at all.

maven-embedded-glassfish-plugin

The maven-embedded-glassfish-plugin is very limited. It doesn't offer facilities to deploy a glassfish-resources.xml, run asadmin commands pre/post deploy, etc. If you're using container provided resources, avoid it and run an embedded Glassfish instance directly in your application or tests instead. The Glassfish embedded API (see below) is pretty easy to use and unlike the Maven plugin gives you the flexibility to invoke asadmin commands to set up your domain to fit your needs.

There are references to a different maven plugin with a slightly different name out there. It's not the same thing, doesn't exist in Glassfish 3, and won't do what you want.

Documentation for the embedded glassfish 3.1 api

The Glassfish 3.1 embedded documentation is here: http://embedded-glassfish.java.net/nonav/apidocs/org/glassfish/embeddable/GlassFish.html. Most of the documentation has been removed from the Oracle Glassfish Embedded guide. The API has changed significantly from 3.0, so the 3.0 guide is just misleading.

asadmin from embedded

If you run your own standalone embedded glassfish, you can invoke asadmin commands using the CommandRunner. However, a frustrating bug caused by a feature removed without considering the impact on embedded means you can't create file users for a file realm this way. See http://java.net/jira/browse/GLASSFISH-16277. I don't have a solution for this issue yet.

REST admin

Glassfish has a REST driven admin interface in addition to asadmin and the web console. This can be a powerful facility for automation, but is almost totally undocumented. Exploring it using `curl' can be informative, because it's based on JAX-RS so paths can report the supported subpaths, etc.

8 comments:

  1. Hi

    What do you mean by "avoid it and use your own embedded glassfish instead." in maven-embedded-glassfish-plugin section? Do you mean starting glassfish in embedded mode directly from main/junit instead of using maven?

    ReplyDelete
  2. Yeah, I mean using the Glassfish embedding API directly to establish an embedded Glassfish instance from your main(), your unit tests, or whatever depending on your needs. See http://download.oracle.com/docs/cd/E19798-01/821-1754/6nmnfdnkk/index.html .

    These days for unit testing container-based apps Arquillian is a very attractive option. I only moved over to it after I dropped Glassfish in favour of JBoss AS 7 (I got sick of the bugs) so I don't know if it supports anything other than the maven embedded glassfish plugin for testing.

    ReplyDelete
  3. Thanks for your post. Question: Have you tried setting up testing of JAX-RS using embedded GlassFish?

    ReplyDelete
    Replies
    1. I no longer work with Glassfish; I've moved to JBoss AS 7. In JBoss AS 7 most things work most of the time, it's fast, it's easy to manage, and it has way fewer bugs+quirks despite being quite immature after a near total rewrite. Most importantly, unlike Glassfish, JBoss AS 7 is progressing *rapidly* with issues and oversights being fixed very quickly.

      Delete
    2. I guess the short answer is "No, I haven't". Sorry.

      Delete
  4. Good to know, Craig. I've hit another roadblock, this time with testing secured resources, and I'm about to give up. JB7 is cool; I wonder how hard the migration from GlassFish would be, including the app itself (JAX-RS, EJB, JPA, etc), testing (e.g., spooling up an instance, configuring it), and admin/deployment...

    ReplyDelete
    Replies
    1. With testing, I strongly recommend JBoss Arquillian. It works with Glassfish, though not I think with the embedded container. Arquillian 1.0 is the typical Java "only kind of finished" package, in that you'll want to use newer versions of ShrinkWrap Maven Dependency Resolver and ShrinkWrap Descriptors than it specifies in its bom, but it's really worth learning and using. It doesn't even take much learning. It appears that Arquillian supports Glassfish 3.1 in embedded and remote operation but I expect the embedded container suffers from the limitations inherent to the Glassfish embedded container.

      Don't expect JBoss AS 7 to be easy and bug free. Everything in Java EE is full of bugs, inconsistencies, incomplete implementations in "final" released software, etc. That's partly because the specs and reference implementations are largely written in isolation then smashed together into a finished product labeled "Java EE 6". It's also significantly because of the spec-before-implementation driven design and the fact that many of the implementers aren't also real-world production users of the technologies they're implementing.

      See eg a report on the DataSourceDefinition annotation which points out that it really doesn't specify anything much well enough to be portable or all that useful. Perhaps that's part of why I discovered that it didn't work with JTA in JBoss AS 7.1, producing an autocommit EntityManager even inside @TransactionAttribute(TransactionnAttributeType.REQUIRED) EJB business methods. Yikes!

      Real world use is one area where JBoss AS 7 has a big advantage. The JBoss guys use it, heavily, and it's the primary target platform for things like Seam 3, Arquillian, etc. Bugs get found and fixed. They're also much more open and much more welcoming of fixes from the community. By contrast, especially after the acquisition, Glassfish seems to be a 2nd-class alternative for WebLogic, despite the latter being even more buggy.

      OTOH, I don't think you get an embedded mode at all for JBoss AS 7, so if your problems with Glassfish are around embedded mode then AS7 won't help you. In that case I'd probably just drop support for embedded and do my testing with Arquillian.

      AS7 has its fair share of quirks, documentation holes, etc, so don't expect magic.

      Delete
    2. OTOH, I haven't seen "OutOfMemory: PermGenSpace" since moving to AS7, because its module loader works properly. You won't restart the appserver much, and if you do it takes about 3 seconds.

      If you're using standard EE6 APIs, one of your main migration pain points will be the change from the default EclipseLink JPA2 provider in Glassfish to Hibernate 4 in JBoss AS 7. Both have different sets of bugs, quirks, and areas where they're fussy about the spec. If you use Criteria queries you'll probably find a few that need fixing/tweaking. Both implementations like to choke on Criteria queries they don't like by throwing a NullPointerException or ClassCastException without any useful context. You can probably use EclipseLink with JBoss AS 7, but I haven't tried.

      The AS7 JAX-RS implementation isn't Jersey, it's RESTEasy. This was painful for me because I'd had to use some extension functionality in Jersey. If you haven't, you shouldn't notice any difference.

      The main difference will be the deployment descriptors - defining your datasources, etc. You'll probably run into disagreements on proper JNDI naming between JBoss AS 7 and Glassfish, but I don't recall the details of what I hit there.

      Overall, for a standards compliant app it should (in theory) be a relatively low pain move, but it'll depend a lot on the details of what you use and how.

      Delete