Showing posts with label glassfish. Show all posts
Showing posts with label glassfish. Show all posts

Thursday, November 14, 2013

Enable gzip HTTP filter in embedded glassfish

I had to google around a little bit to figure out how to enable glassfish's built-in HTTP gzip compression in my little fishRunner tool that I described in an earlier post. The fishRunner runs embedded glassfish to launch webapps (.war files) on heroku.

Anyway - there may be a better way, but the trick I used just issues the embedded equivalent of the asadmin set command-line with this block of code:

{ // enable gzip compression while we're at it
    final CommandResult commandResult = commandRunner.run(
     "set",
     "configs.config.server-config.network-config.protocols.protocol.http-listener.http.compression=on"
     );
    if (commandResult.getExitStatus().equals(CommandResult.ExitStatus.FAILURE)) {
 throw new RuntimeException("Failed to configure gzip compression", commandResult.getFailureCause());
    }
}

I pushed that patch to github.

Saturday, October 12, 2013

heroku glassfish runner

I wired up a little fishRunner tool (https://github.com/frickjack/littleware-fishRunner) that deploys a java web archive (.war file) to an embedded glassfish server. I setup the fishRunner to simplify launching web services on heroku - a cool polyglot PaaS offering that extends the IaaS from AWS with APIs that automate the load-based allocation of compute nodes for a linux web application, and also manages network load-balancing, logging, database provisioning, and an array of other services. A developer deploys an application to heroku by cloning the application's code to a heroku-hosted git repository. The code includes a configuration file that specifies a linux command line to launch the application. Each launched instance of the application runs in a container similar to a BSD jail that heroku calls a dyno.

Heroku's git-based deployment reflects its roots as a polyglot platform supporting dynamic languages like ruby and php that deploy a webapp by installing code behind a server. When heroku introduced java support in its blog, the company made a virtue out of its necessity to deploy by pushing code that is compiled and executed on the dyno - describing java's enterprise J2EE stack as ill-suited for software-as-a-service (SaaS) application deployment. Heroku encourages java web developers to package an application as an executable with an embedded http server like jetty rather than assemble the application into a web archive (.war file) suitable for submission to a J2EE server container.

I see two shortcomings in heroku's approach to java deployment. First, it requires the developer to manage an embedded server. Heroku's demo app (https://devcenter.heroku.com/articles/getting-started-with-java) shows how configuring jetty is easy for a simple web application, but the embedded container becomes more complicated to manage as the application's complexity increases with technologies like JPA, JDBC, IOC, JNDI, and others. I'm used to developing against a subset of the java EE API's, and delegating to a container (server) the responsibility to manage the environment required by those APIs. Deploying compiled code to a container is common in many java runtimes including android and plugins and extensions for OSGi based platforms like eclipse, netbeans, and glassfish.

My second complaint is that I don't like the idea of deploying java source code that is compiled on the production server. I'm used to a workflow where I build and test locally, and deploy a binary package. When working with a team I would introduce Jenkins or some similar continuous integration service into the mix, so that each patch submitted to a shared repository is automatically checked out, compiled, tested, and deployed to a shared test environment isolated from production. I can imagine a production-deployment setup where once the team is ready to release the code running in the test environment, then the code is deployed to a beta environment that shares the production database, but is not yet visible to the public. The code is finally released publicly by flipping a switch that moves the beta servers into production, and the old production servers stay online as a fallback if something goes wrong. Anyway - that's all just building imaginary castles - my personal configuration management needs are not complex, but back to the point - I don't like the idea of pushing code to the runtime server.

These are small complaints that have been commented on before other places (openShift's bLog, on java.net ). Heroku does now have an "enterprise for java" offering that supports war-file deployment to a tomcat container, and a sample application (https://github.com/heroku/java-sample) illustrates how to include tomcat's webapp-runner in the maven pom for a webapp project that compiles a war. There are also other PaaS clouds that cater to the java EE developer including RedHat's OpenShift, cloudbees, jelastic, Oracle's cloud, HP's cloud, AWS elastic beanstalk, and others.

In the end I'm still working with heroku - it's a great service whose benefits far outweigh its drawbacks: the price is right for development, it frees me from linux administration using IaaS like EC2 directly, my app comes up with a reasonable DNS name for an AJAX service (littleware.herokuapp.com) already network load balanced and with SSL (https), and heroku runs on AWS, so I can access AWS services ( dynamodb, S3, Simple queue, ...) without paying for off-AWS data-transfer. Finally, the fishRunner lets me deploy war-files to heroku in a nice way. The fishRunner takes a similar approach to tomcat's webapp-runner, but runs an embedded glassfish server supporting the java EE 7 web profile. Also - the fishRunner supports downloading a war file from an S3 bucket, so the workflow I envision deploys the fishRunner's code (something like 5 files) to a heroku app. At runtime the fishRunner downloads the war file and JAAS login config files defined in the heroku environment (via heroku config) from S3 (fishRunner can also just use local files for local testing), starts the glassfish server listening on heroku's environment-specified port, registers the postgres database connection pool defined by heroku's DATABASE_URL environment with glassfish's JNDI, configures JAAS, and deploys the WAR.

> java -cp 'target/*;.' littleware.apps.fishRunner.FishApp
...
SEVERE: Failed to launch webapp
littleware.apps.fishRunner.FishApp$ConfigException: Parameter must be specified in environment or on command line: DATASE_URL at littleware.apps.fishRunner.FishApp.main(FishApp.java:250)

Oct 12, 2013 3:52:38 PM littleware.apps.fishRunner.FishApp main
INFO:
fishRunner key value key value ...
Options pulled first from system environment,
then overriden by command line values:
S3_KEY
S3_SECRET
S3_CREDSFILE  - either both S3_KEY and S3_SECRET or S3_CREDSFILE must be defined
WAR_URI - required - either an s3:// URI otherwise treated as local file path
PORT - optional - defaults to 8080 if not otherwise specified
LOGIN_URI - optional - JAAS login.conf location either and s3:// URI otherwise treated as local file path
CONTEXT_ROOT - required - glassfish deploy context root for war
DATABASE_URL - required - ex: postgres://user:password@host:port/database
> heroku config
=== littleware Config Vars
CONTEXT_ROOT:               littleware_services
DATABASE_URL:               postgres://...
HEROKU_POSTGRESQL_NAVY_URL: postgres://...
JAVA_OPTS:                  -Xmx384m -Xss512k -XX:+UseCompressedOops
MAVEN_OPTS:                 -Xmx384m -Xss512k -XX:+UseCompressedOops
PATH:                       /app/.jdk/bin:/usr/local/bin:/usr/bin:/bin
S3_KEY:                     ...
S3_SECRET:                  ...
WAR_URI:                    s3://apps.frickjack.com/repo/littleware.apps/appsWeb/1.0-SNAPSHOT/appsWeb-1.0-SNAPSHOT.war

With heroku as a deploment platform, I'm back banging on littleware's simple JAAS authentication service. It's running now on my little dyno with CORS headers allowing AJAX access from pages hosted in my S3 bucket at http://apps.frickjack.com/. I'm working to implement the client-side javascript (or typescript) modules that will make the service easy to use on the client side, including support for OpenId via the littleId code I wrote a while ago, but currently the service just plugs in a null JAAS module that accepts any user password. You can get a feel for the service visiting these links in sequence:

Friday, June 28, 2013

CDI and Guice with jsr-300 javax.inject In Same Webapp

Things can get weird when java SE code developed with IOC is deployed into a java EE container that implements CDI. For example - the littleware code I work with implements simple modules and life cycle management with guice, so when I deploy that code in a webapp to a glassfish server I want guice's runtime to manage littleware's dependency injection, but I might also want CDI to inject a glassfish-managed JPA EntityManager into a servlet for me, and both guice and CDI are scanning for the same javax.inject runtime annotations. Fortunately - this kind of thing worked fine for me until recently, since CDI 1 as introduced in java EE 6 ignored jars that did not include a META-INF/beans.xml file.

Java Enterprise Edition 6 introduced JSR-330 (javax.inject annotations and provider interfaces) and JSR-299 (CDI - contexts and dependency injection) to the java-ee platform. The javax.inject package standardized the annotations and interfaces used by java's various inversion of control and dependency-injection systems (guice, spring, dagger, pico container, ...), so that code written with one IOC system in mind could be more easily used in an application that deployed to another system.

CDI introduced an IOC implementation for java enterprise edition (EE) technologies (servlets, JSF, EJB, JPA, ...) deployed in EE containers like glassfish, jboss, weblogic, and websphere.

I discovered CDI's behavior changed slightly in the new java EE 7 runtime when a webapp that ran fine in glassfish version 3 (a java EE 6 container) failed to deploy under glassfish 4 (the EE-7 reference implementation). The errors in the glassfish-4 logs lead me to this ticket in guava's bug database. It turns out that CDI's new version 1.1 runtime automatically scans all jars deployed with an enterprise application, and guava-14+ includes a couple classes with javax.inject annotations that CDI processed in an unintended way (littleware still uses guice's com.google.inject package annotations and interfaces, so CDI ignored those).

I eventually found one easy solution to this javax.inject - CDI 1.1 mix-up is to add a META-INF/beans.xml CDI config file to jars that include javax.inject annotations that require special or no handling by CDI. I added the following META-INF/beans.xml with a bean-discover-mode attribute set to "none" to the guava jar in my webapp, and that solved the problem. Hopefully guava's maintainers will add a similar beans.xml file to guava's binary distribution on maven central.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
       bean-discovery-mode="none">
</beans>