Glassfish uses per default java.util.logging (JUL) for logging. Third-party frameworks are often using different logging frameworks. For my company and private projects I’m using slf4j for all kind of logging. I found some rare resources on the web how to consolidate the different logging frameworks to just have one single logging file.

slf4j is delivery with a bridge to redirect JUL logging to slf4j. The steps to enable slf4j with log back are:

You need these 4 artifacts:

  • slf4j-api-1.5.10.jar
  • jul-to-slf4j-1.5.10.jar
  • logback-core-0.9.20.jar
  • logback-classic-0.9.20.jar

You can download either from the slf4j and log back websites, or grab them from the maven repository

Step 1:

Copy these jar’s to the $GF_INSTALL/glassfish/lib/endorsed

Step 2:

Create a logback.xml at $GF_INSTALL/glassfish/domains/domain1/config containing:

<configuration debug="true" scan="true">
  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file</tmp/gf_server.log>/file>
    <append<true>/append>
    <encoder>
      <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{52} - %msg%n</Pattern>
    </encoder>
  </appender>
  <root>
    <level value="INFO" />
    <appender-ref ref="FILE" />
  </root>
</configuration>

Step 3:

Modify $GF_INSTALL/glassfish/domains/domain1/config/logging.properties

handlers=org.slf4j.bridge.SLF4JBridgeHandler
com.sun.enterprise.server.logging.GFFileHandler.flushFrequency=1
com.sun.enterprise.server.logging.GFFileHandler.file=/tmp/server.log
com.sun.enterprise.server.logging.GFFileHandler.rotationTimelimitInMinutes=0
com.sun.enterprise.server.logging.GFFileHandler.logtoConsole=false
com.sun.enterprise.server.logging.GFFileHandler.rotationLimitInBytes=2000000
com.sun.enterprise.server.logging.GFFileHandler.alarms=false
com.sun.enterprise.server.logging.GFFileHandler.formatter=com.sun.enterprise.server.logging.UniformLogFormatter
com.sun.enterprise.server.logging.GFFileHandler.retainErrorsStasticsForHours=0
com.sun.enterprise.server.logging.GFFileHandler.level=ALL
.level=INFO

Step 3:

Modify $GF_INSTALL/glassfish/domains/domain1/config/domain.xml and add two JVM options at the server-config JVM section:

-Djava.util.logging.config.file=${com.sun.aas.instanceRoot}/config/logging.properties
-Dlogback.configurationFile=file:///${com.sun.aas.instanceRoot}/config/logback.xml

Now you can restart Glassfish and you should only see two entries in the server.log:

16.06.2012 17:19:40 com.sun.enterprise.admin.launcher.GFLauncherLogger info
INFO: JVM invocation command line:
-XX:+UnlockDiagnosticVMOptions
-XX:PermSize=64m
-XX:MaxPermSize=192m
-XX:NewRatio=2
-Xmx512m
-d32
-client
-javaagent:/srv/glassfish-3.1.2-logback/glassfish/lib/monitor/flashlight-agent.jar
-Dfelix.fileinstall.disableConfigSave=false
-Djavax.net.ssl.keyStore=/srv/glassfish-3.1.2-logback/glassfish/domains/domain1/config/keystore.jks
-Djava.awt.headless=true
-Dfelix.fileinstall.poll=5000
-Djava.endorsed.dirs=/srv/glassfish-3.1.2-logback/glassfish/modules/endorsed:/srv/glassfish-3.1.2-logback/glassfish/lib/endorsed
-Dfelix.fileinstall.bundles.startTransient=true
-Djavax.net.ssl.trustStore=/srv/glassfish-3.1.2-logback/glassfish/domains/domain1/config/cacerts.jks
-Djava.util.logging.config.file=/srv/glassfish-3.1.2-logback/glassfish/domains/domain1/config/logging.properties
-Dcom.sun.enterprise.security.httpsOutboundKeyAlias=s1as
-DANTLR_USE_DIRECT_CLASS_LOADING=true
-Djava.security.auth.login.config=/srv/glassfish-3.1.2-logback/glassfish/domains/domain1/config/login.conf
-Dgosh.args=--nointeractive
-Dosgi.shell.telnet.maxconn=1
-Djdbc.drivers=org.apache.derby.jdbc.ClientDriver
-Dfelix.fileinstall.dir=/srv/glassfish-3.1.2-logback/glassfish/modules/autostart/
-Dosgi.shell.telnet.port=6666
-Djava.security.policy=/srv/glassfish-3.1.2-logback/glassfish/domains/domain1/config/server.policy
-Dfelix.fileinstall.log.level=2
-Dcom.sun.enterprise.config.config_environment_factory_class=com.sun.enterprise.config.serverbeans.AppserverConfigEnvironmentFactory
-Dosgi.shell.telnet.ip=127.0.0.1
-Dcom.sun.aas.instanceRoot=/srv/glassfish-3.1.2-logback/glassfish/domains/domain1
-Dcom.sun.aas.installRoot=/srv/glassfish-3.1.2-logback/glassfish
-Djava.ext.dirs=/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/lib/ext:/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/jre/lib/ext:/srv/glassfish-3.1.2-logback/glassfish/domains/domain1/lib/ext
-Dfelix.fileinstall.bundles.new.start=true
-Dlogback.configurationFile=file:////srv/glassfish-3.1.2-logback/glassfish/domains/domain1/config/logback.xml
16.06.2012 17:19:41 com.sun.enterprise.admin.launcher.GFLauncherLogger info
INFO: Successfully launched in 16 msec.

all the rest is logged to the gf_server.log file located at /tmp/gf_server.log. The logging bridge jul-to-slf4j is redirecting all JUL logging to slf4j ant then to the logging backend of your choice. I used log back instead of log4j. Logback has some advantages over log4j which are described here.

It took me half a day to figure out, why redeploying a Atmosphere war bundle always fails with a stacktrace. Atmosphere packages, e.g. the jersey into the war archive. This behavior could be changed by setting a JVM environment variable in Glassfish.

In the GF admin console, going to:

Configuration->JVM Settings

switch to the JVM Options tab and add this option:

-Dcom.sun.enterprise.overrideablejavaxpackages
=javax.ws.rs,javax.ws.rs.core,javax.ws.rs.ext

Atlassian Jira LogoAt work I’m currently evaluating Jira as our “Scrum Tool”. Currently we work with various tools:

  • Physical Taskboard
  • TestTrack Pro
  • Excel Sheets
  • Timetracking Tool

to assist our scrum process. As a java develepors I endeavore to reuse source code and encapsulate responsibilities within components with precisely defined interfaces. In my daily work I have to manage 4 tools and keep all the information synchronized, so I gave Jira a try to replace some of the current tools.

I am currently evaluating Jira in the running sprint, and so far it seems to manage all our requirements. But there is information I couldn’t get out of Jira: My Daily Worklog. I need the daily worklog to generate productivity reports and to invoice our customer.

I haven’t found such a report in the Jira Plugin list, so i wrote a small java application to get this done by utilizing the Jira SOAP web-service:

 JiraSoapServiceService jiraSoapServiceGetter = new JiraSoapServiceServiceLocator();
 JiraSoapService soap = jiraSoapServiceGetter
     .getJirasoapserviceV2(
          new URL("http://url.to.jira/rpc/soap/jirasoapservice-v2?wsdl"));
 String token = soap.login("myUsername", "mySecret");

 RemoteIssue[] issuesFromTextSearch = soap
     .getIssuesFromJqlSearch(
         token,
         "project = MYPROJECT AND assignee = myUsername AND fixVersion = 'Sprint 46'",
         10000);

 List<WorklogEntry> entries = new ArrayList<WorklogEntry>();

 for (RemoteIssue remoteIssue : issuesFromTextSearch) {
      RemoteWorklog[] worklogs = soap.getWorklogs(token, remoteIssue.getKey());

      for (RemoteWorklog remoteWorklog : worklogs) {
           entries.add(new WorklogEntry(
                remoteWorklog.getCreated().getTime(),
                remoteWorklog.getTimeSpent(),
                remoteIssue.getKey(),
                remoteIssue.getSummary()));
     }
 }

 DateTime today = new DateTime();

 for (WorklogEntry worklogEntry : entries) {
      DateTime worklogDateTime = new DateTime(worklogEntry.getCreated());
      if (worklogDateTime.getDayOfYear() == today.getDayOfYear()
           && worklogDateTime.getYear() == today.getYear()) {
           System.out.println(
                 worklogEntry.getIssueKey() +" - "
                 + worklogEntry.getIssueDescription()
                 + " - "+ worklogEntry.getTimeSpent());
      }
 }

This is a quick hack and far away from any clean code. Maybe I’ll write a cusomt Jira Report in my spare time to get the above data out of Jira in the future.

Currently, there isn’t so much hype concerning the Wave Federation Server and with particular regards to the Gadgets API or the Robot API. But there are some people around the world starting their own client application. Unfortunately, the Wave Federation Server is a moving target and there are daily changes to the code base. The client-server RPC (based on protocoll buffers) communication is far from feature complete. Some people are complaining they won’t start projects until the Wave Federation Server is stable and almost feature complete.

As far as i know there are three projects working on a client:

As the first two projects do not have any implementation yet I took a first look into the “Java Desktop Client”:

A very simple GUI based client to be used with the reference server. This is a small experiment I investigated and thus unfortunately I cannot keep the project updated or fix bugs etc at the moment, especially as google keep updating the reference code. This may or may not work with the current distribution of the google wave reference server again I haven’t tested it.

The desktop client implements a very basic set of funtcions: new wave, open wave, add and remove participants, send a message. I took a screenshot so you can see how the desktop client looks like:

Unfortunately, there is no binary or webstart version of the Desktop Client, but you can pull the sources from github and build a binary. There is no ant or maven file, so i give you a short step-by-step installation guide how to get a running version:

  • git clone git://github.com/Thomas101/GUI-client-for-google-Wave.git
  • create a new eclipse java project in the newley created directory
  • add the “console” directory to sources
  • create a new package “org.waveprotocol.wave.examples.fedone.waveclient.console” and move all classes to this package
  • add the fedone-client.jar from the wave-protocol project to the classpath
  • run the application with the parameters: ConsoleClient <userAtDomain> <server> <port>

If everything is fine you’ll see a Java GUI:

Java Desktop Client