Search This Blog

Wednesday, October 10, 2012

How To Print A List of Comma-Seperated Values Nicely and Remove the Last (',') Comma Value


I recently wanted to take a list of Strings (i.e. List<String> list) and print that out with each value seperated by a comma and inside a set of brackets. The idea is I'd have something like this at the end:

    (String1,String2,String3)

However my first cut attempt at a loop was creating the list above but with a superfluous ',' at the end like so:

    (String1,Strng2,String3,)

Which was based on this code (where list was my List<String>):>

    StringBuilder sb = new StringBuilder("(");
    for (String string : list) {
        sb.append(string);
        sb.append(",");
    }
    sb.append(")");     //close the end bracket

So I decided to find a way or three to do this more nicely. What follows is 3 different ways of implementing this to get the correct implementation using a TestNG test case for testing. Each implementation, which achievs the same thing in each case is in one of the getVersion#() methods. Feel free to use any one of these 3 possible, simple implementations of the same thing to get the nicely comma seperated list with the end comma nicely removed.

  @Test
  public void testClass() {
    //Create a list of strings to be used in each test case
    List<String> list = new ArrayList<String>(Arrays.asList("String1", "String2", "String3"));
   
    //setup the expected result string based on the list above
    final String EXPECTED_RESULT = "(String1,String2,String3)";
   
    StringBuffer sb = getVersion1(list);
    System.out.println("1st string test:" + sb.toString());
    Assert.assertEquals(sb.toString(), EXPECTED_RESULT);
   
    sb = getVersion2(list);

    System.out.println("2nd string test:" + sb2.toString());
    Assert.assertEquals(sb2.toString(), EXPECTED_RESULT);
   
    sb = getVersion3(list);

    System.out.println("3rd string test:" + sb3.toString());
    Assert.assertEquals(sb3.toString(), EXPECTED_RESULT);
  }


  /**
   * This method puts the comma first so that we have the extra comma at the
   * start and then uses the deleteCharAt() method to delete the 1st ','
   */
  private StringBuffer getVersion1(List list) {
    //begin 1st case: ',' at start and deleteCharAt(0 or 1)
   
StringBuffer sb = new StringBuffer("(");
    for (String string : list) {
      sb.append(",");
      sb.append(string);
    }
    sb.deleteCharAt(1); //remove 1st ',' symbol (or if extra char's before bracket increse number)
    sb.append(")");     //close the end bracket


    return sb;
  }

  /**
   * This method puts the comma at the end in the common wayand then uses 
   * the deleteCharAt() method along with the length of the StringBuffer
   * to delete the last ',' symbol from the list before appending the ).
   */
  private StringBuffer getVersion2(List list) {
    //begin 2nd case: ',' at end and deleteCharAt(last character)
   
StringBuffer sb2 = new StringBuffer("(");
    for (String string : list) {
      sb2.append(string);
      sb2.append(",");
    }
    sb2.deleteCharAt(sb2.length() - 1); //remove the 1st ',' symbol
    sb2.append(")");     //close the end bracket


    return sb;
  }

  /**   
   * The final method of implementing this places the excess ',' at the end like 
   * is standard but then does the delete and append(")") steps in a single step
   * via the replace() call which replaces the lat ',' with the ')' bracket.
   */ 
  private StringBuffer getVersion3(List list) {
    //begin 3rd case:  ',' at end and replace the last character with the bracket achieving both at the same time
    StringBuffer sb3 = new
StringBuffer("(");
    for (String string : list) {
      sb3.append(string);
      sb3.append(",");
    }
    sb3.replace(sb3.length() - 1, sb3.length(), ")");


So there ya go, 3 different methods all very similar, to implement a comma-seperated list without the pesky comma at the end of the list and implemented in a TestNG test with Assertions to prove it worked as expected.  Note: In all 3 cases the performance is pretty much the same. When looking at the deleteCharAt() followed by an append() as compared to a replace() call they are pretty much identical in terms of what they are going to need to do. Although the internals vary the key performance hit is the call to the System.arrayCopy() which is where the time is spent. Either way there are 3 calls to System.arrayCopy() to perform this work, which reeally should be unsuprsing since in both cases we are doing pretty much the same thing just reducing the number of lines required to implement it. My choice is the 1st option as it looks the neatest (even if it does take one line more than the replace() method).

How To Use: javap With Eclipse IDE

I could write a blog post about this .... but instead ill let the following link do all the talking for me:

    http://stackoverflow.com/questions/7056987/how-to-use-javap-with-eclipse

So there ya go!

Wednesday, May 9, 2012

JDK8 Roadmap/Timeline to Release


JDK 8 Release Timeline Information


I’ve been following both the JDK7 and then JDK8 development blogs for java for some time now as they both have large numbers of changes to the language (much like the large number of changes in JDK5 (generics, enums etc) and unlike JDK6 which was not much of a change at all). Thought that you may be interested in the following links which now give a timeline for the release of the next Java version JDK8:

http://openjdk.java.net/projects/jdk8/

To quote from the above source, here is the proposed milestone development schedule:
2012/04/24 - M1
2012/06/14 - M2
2012/07/30 - M3
2012/09/11 - M4
2012/11/26 - M5
2013/01/30 - M6 – Feature Complete
2013/09/?? - GA – General Availability
The expectation at the end of M6 is that all features and new test development will be complete with the exception of work on component JSRs, which will be given additional time to bake until early May 2013. Between M6 and GA the tolerance for further changes will decrease in steps, with general bug fixes admitted up until early April 2013, only P1-P3 bug fixes until mid-June 2013, and only showstopper fixes after that.

This version should have the following main changes (of which the inclusion of closures/lambda calculus functionality will IMHO be one of the biggest changes ever introduced in Java ... larger even then the introduction of generics in JDK 5):

  • Project Coin – language changes...half of which were introduced in JDK7 and which you can read about on the web
  • Project Jigsaw – breaking up the monolithic sized JDK into separate MODULES with dependencies (a bit like Gradle/Maven/Ivy but for Java) ... more detail/links at: http://openjdk.java.net/projects/jigsaw/ and quickstart guide with examples on Mark Reinholds blog: http://openjdk.java.net/projects/jigsaw/doc/quickstart.html 
  • Project Lambda – long standing effort (discussed since JDK5 and maybe even earlier) to introduce closures and related functionality into java: http://openjdk.java.net/projects/lambda , see here for one of the latest documents providing information:  http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-4.html   IMHO this will be a huge change to Java and the way programming occurs (as this pushes java towards a LISP style functional programming type language) and this is without doubt the change I (and many other developers also) are looking forward to the most.

Its still a way away yet to the release date ... but worth keeping in mind when considering updates to the SOE used by your work place (or home projects) and when to make the jump from JDK6 to JDK7/8??

---------------------------
Notes: On JSR 337:

---------------------------


By the way the following link also has the dates for the JDK 8 JSR 337 Spec and its various Milestones:

http://openjdk.java.net/projects/jdk8/spec/

This is the primary web page for JSR 337, the Platform Umbrella JSR for Java SE 8.

Expert Group

  • Andrew Haley (Red Hat)
  • Steve Poole (IBM)
  • Mark Reinhold (Oracle)
  • TBD (Google)

Schedule

2012/7Expert Group formation
2012/9Early Draft Review
2013/1Public Review
2013/6Proposed Final Draft
2013/8Final Release

Mailing lists

There are two mailing lists:
  • java-se-8-spec-experts is the Expert Group (EG) list. Only EG members may subscribe and post to this list, but the archives are public.
  • java-se-8-spec-observers is for those who wish to monitor and, perhaps, discuss the EG's progress. Messages sent to the primary EG list are automatically forwarded to this list. Anyone may subscribe to this list, and any subscriber may post. EG members are under no obligation to follow the traffic on this list.
A formal feedback channel, most likely in the form of an issue tracker, will be set up when a draft specification is available for review.

Differences in Creating a Servlet in versions 2.5 and 3.0 Of the Servlet Spec.

Differences in Servlet Definitions between v2.5 and v3.0

The following 2 examples show the difference between how a Servlet Java Class and associated web.xml deployment descriptor was changed in the upgrade from version 2.5 to version 3.0 of the Servlet Specification. I found this a simple and interesting look at the way the definition of a Servlet in code has now been simplified through the use of annotations from JSR 175.

2.5 Version of Servlet Definition 

Java Class Of Servlet in 2.5

public class MyServlet extends HttpServlet {
    public void doGet (HttpServletRequest req, HttpServletResponse res) {
        ....
    }
}

Deployment descriptor in 2.5 (web.xml)

<web-app>
    <servlet>
        <servlet-name>MyServlet</servlet-name>
        <servlet-class>samples.MyServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/MyApp</url-pattern>
    </servlet-mapping>
    ...
</web-app>

3.0 Version of Servlet Definition 

Here is the much simplified version written to the Servlet 3.0 API. As MyServlet is annotated as a servlet using the @Servlet annotation, it gets initialized during the start-up of the web container. Note that the deployment descriptor is optional in this case.

Java Class Of Servlet in 3.0

@Servlet(urlMappings={"/MyApp"})
public class MyServlet {
    @GET
    public void handleGet(HttpServletRequest req, HttpServletResponse res) {
        ....
    }
}

Deployment descriptor in 3.0 (web.xml) - Optional


Saturday, July 30, 2011

Java JDK 7 - Finally Released

JDK 7 Released ... Finally!!!

A Detailed Overview Of New Features/Functionality in JDK7

 

Introduction

The following long-ish blog entry is a relatively detailed overview of information for the JDK 7 Release of 29th July 2011 by Oracle. Given the release has just occurred I have collected a large amount of relatively detailed information regarding the JDK7 release that developers looking to upgrade from Java 1.6.0_26 to JDK7 will find useful. This information includes a general overview of the entire release with access via links to the various documentation you may need, release notes, installation instructions, JavaDoc API's etc., as well as changes that have been included and whether they have caused compatability and generally known issues that you may encounter.  

More importantly for most people that will find their way here Ive also included information about the Programming Language enhancements (these are the ones that if you've heard anything about Java 7 you would've heard about these) and include the various Project Coin upgrades, and new functionality like try-with-resources, multi-catch, Strings in switch statements, upgrades to numeric and binary literals, etc. Besides these Ive also included other enhancements that generally you are less likely to hear about as they arent discussed as often as they arent focussed at the programming language level per-se but can include things like JVM, Garbage Collector and various new Framework (fork./join, NIO2, etc) inclusions and improvements.  If your primarily after this information which I think most people interested in Java 7 will be and you want to bypass the sections on JDK7 Release History, Release Notes and various JDK 7 Documentation, then simply skip ahead to the two sections on enhancements further down towards the end of this blog entry under the main title 'Overview of JDK 7 New Features' and each labelled with their respective titles:
  • General Enhancements in the Java JDK 7
  • Programming Language Enhancements in Java SE 7
Since a lot of this information is already accessible and has been provided by the implementers (Sun/Oracle) rather than copy/paste large slabs of text or re-write it myself with new examples etc., Ive focussed more on providing a brief introduction and over-view in all these cases and then providing a series of links to much more detailed information in the form of tutorials, explanations and specifications. The general idea of this blog entry is to provide a single point of entry for any and all information regarding Java 7 and to be able to get some initial info on what it is that your interested in before being re-directed to much more detailed information via outgoing links. Lets see how I do hey :-)!
 

Overview Of JDK7 Release History

So after almost 5 years (four years, seven months, and seventeen days) since JDK 6 and after 9,494 bug fixes, 1,966 enhancements, 9,018 changesets, 147 builds, and four JSRs, JDK 7 is done (Thanks Mark Reinhold for that info: http://mreinhold.org/blog/jdk7-ga).  Oracle announced the release of JDK 7 today (2011-07-29) which interestingly followed the scheduled release plan exactly which is reassuring to see for the future JDK8 release as it raises my level of trust that if they say they'll release JDK8 in 2012 that it'll actually happen unlike JDK7 which as we know see was delayed over and over for 5 years:

    http://openjdk.java.net/projects/jdk7/

The plan above was made up of 147 builds as mentioned comprising a total of 13 Milestones. Information on each of the milestones with further detailed information aboutwhat a particular feature in a milestone entails, along with a detailed calendar of build dates and milestones (for those interested in such things) is provided in the following two links:

Overview Of Release Notes

The next link below is the main download page:


This page has downloads for both the previous version of JDK6 (1.6.0_26) as well as everything related to the new JDK7 release (ie: JDK7 with EE, JDK7 with Netbeans 7.0). Incidentally Netbeans 7.0 is a version of Netbeans that is already built to work with JDK7.0 so you can start using JDK7 with the Netbeans IDE straight away and get access to the cool features within the IDE (ie: the Project Coin features are useable and visible in the IDE and it gives correct information and code-completion for them already, which as I say is nifty and great that its available so early on the same day as the JDK 7 release itself).

The index page for the Release Notes of JDK7 are at: 

These are detailed and include various documents. The first of these Ill look at is the Java SE 7 Features and Enhancments page located at:


Since this is a major feature release this link includes information on the various features and enhancements in Java SE 7 and JDK 7. The beginning of the document above has a number of sections that highlight the Technology Changes as well as the various RFE (Requests For Enhancements) that were addressed. You can follow these links for more detailed information and I suggest doing so. Furthermore one of the last sections is a list of the known issues which Im linking to below as this is an important section of information. Skimming through this section there are a number of known issues in this release which its important to be aware of. One are where there seems to be a number of issues in is the use of Genereics and how Re-ification of Generics affects the type of code that can and can't be written. I found these useful to skim through simply to be aware of what can occur and when writing code I'll now be aware of what to look out for. See link for known issues:

The Release Notes also provide info on compatability. Much like the known issues section this is also useful to read through to be aware of problems that may arise during upgrade from JDK6 to JDK7.  Although in general and despite the introduction of a number of new features (which JDK6 didnt have compared to JDK5) the upgrade from 6 to 7 is actually quite painless. The list of compatability issues in the link below is quite small and limited to very specific cases. Though still usefull to read through I would recommend upgrade to 7 as soon as possible as these few very specific cases can a) be dealt with should they arise and b) the benefits from the new features more than out weigh any very minor upgrade problems.

    http://www.oracle.com/technetwork/java/javase/compatibility-417013.html

Again the page above is very well written and the sections on incompatabilities are very detailed indicating which sections of the language are affected (eg: NIO, API, Language, etc):

    http://www.oracle.com/technetwork/java/javase/compatibility-417013.html#incompatibilities

The final parts of the Release Notes are info on a number of sections. These are listed along with their associated links and some short info below along with links to a variety of other docs and information links that are important for the JDK 7 release.

Overview Of JDK 7 Important Documentation and Links

  • Version Numbering and Naming Information - This is information on the various numbering and naming standards used within this release of the JDK. Useful information since Java has an unusual set of naming standards. ie: the version string for the product is reported as "java version 1.7.0_3", the product will be called JDK 7u3, JDK 7 update 3 or, when the update version is not important, JDK 7. http://www.oracle.com/technetwork/java/javase/jdk7-naming-418744.html
  • JDK and JRE 7 Installation Guide - Provides information on performing an installation of each of the modules. If you've ever done a previous install of the Java Platform this is all old hat and Im providing it mainly for completeness sake:  http://download.oracle.com/javase/7/docs/webnotes/install/index.html
  • JDK and JRE 7 README Files - High level README files which provide information on libraries, packages, endorsed override methods, the location of jars and libraries and packages within those libraries etc. 
  • JDK7 Specifications - This page contains links to the Java SE 7 Edition Language and Virtual Machine specifications. It also has archival links to previous specification versions. The specifications are important as they are the final word on how things SHOULD work and I  have often turnesd to them in the past when new versions have come out to see why and how an implementation has been done (ie: previous Java Versions introduced the Integer/Char/Short/Byte internal caches and the specifications provided the final word on initial cache sizes etc). http://download.oracle.com/javase/cmn/spec_index.html
  • JDK7 API Docs - This is one of the critical links and also one of the pieces of documentation any developer will return to time and again. The link is to the root of the java API doco (with new doco for new functionality added in JDK7 labelled using: since 1.7 in the JavaDocs as is standard). http://download.oracle.com/javase/7/docs/api/
  • JDK 7 Tutorials - A set of brand new tutorials has been created with the new functionality added in JDK 7 as a basis and added to the complete existing set of tutorials. All of the tutorials have been updated on the basis of the new release. The new tutorials based on the newly introduced JDK7 functionality are grouped at the start of the page and cover Project Coin functionality amongst other things and so are useful even for experienced Java developers to get a feel for the correct use of new functionality. http://download.oracle.com/javase/tutorial/ 
  • JDK 7 Trouble Shooting Guide - This Java 7 Trouble Shooting Guide contains numerous links to various trouble shooting blogs. Although many of the performance links are JDK6 (since JDK7 has minimal performance features as these are saved for multi-core processing imlementations in JDK8) they ar still valid in the context of this JDK 7 release. http://download.oracle.com/javase/7/docs/webnotes/tsg/index.html
  • JDK7 Documentation Index - This page contains the high-level overview index for all of the API's and various JDK 7 components as well as a section on 'Whats New in JDK7 Documentation' which covers the new features and components which were implemented in this JDK. The first section is a series of tech notes for each section (such as JDBC, JNDI, AWT, Java2D etc.) while the 2nd section gives a good indication of what was added in this JDK release (ie: changes made to the garbage collector, the API's, NIO packages and usage, etc). 

Ive list the changes mentioned in the second section in the final point above in more detail in the following section as these are a good way of seeing whats changed in the JDK for this version.

Overview Of JDK 7 New Features

A good source of an overview for fetaures included in this release is the wiki page (at: http://en.wikipedia.org/wiki/Java_version_history#Java_SE_7_.28July_28.2C_2011.29) and this provides not just the main features but also info on things less well publicised as they are not code features but underlying functionality (such as the info on the XRenderer etc). Another good source of detailed information discussing the various Project Coin features in detail is Oracle's page located at: 


General Enhancements in the Java JDK 7

The enhancements listed here cover the entire JDK 7 release. Actual code/coding enhancements will be listed in the section 'Programming Language Enhancements in Java SE 7' below while here I'll list things like changes to API's, the garbage collector, the JVM, etc.  While the programming language changes have been discussed at length in the leadup to the release of Java 7 the following set of updates and new functionality have in general received less coverage and so are covered at some length here.

Programming Language Enhancements in Java SE 7

The following programming language enhancements and new functionality (as mentioned earlier) have been discussed at some length on blogs etc., prior to the Java 7 release and so here I will cover the new features and aprt from a breif overview provide links to further information.

  • Binary Literals - In Java SE 7, the integral types (byte, short, int, and long) can also be expressed using the binary number system. To specify a binary literal, add the prefix 0b or 0B to the number.
  • Underscores in Numeric Literals - Any number of underscore characters (_) can appear anywhere between digits in a numerical literal. This feature enables you, for example, to separate groups of digits in numeric literals, which can improve the readability of your code.
  • Strings in switch Statements - You can use the String class in the expression of a switch statement.
  • Type Inference for Generic Instance Creation - You can replace the type arguments required to invoke the constructor of a generic class with an empty set of type parameters (<>) as long as the compiler can infer the type arguments from the context. This pair of angle brackets is informally called the diamond.
  • Improved Compiler Warnings and Errors When Using Non-Reifiable Formal Parameters with Varargs Methods - The Java SE 7 complier generates a warning at the declaration site of a varargs method or constructor with a non-reifiable varargs formal parameter. Java SE 7 introduces the compiler option -Xlint:varargs and the annotations @SafeVarargs and @SuppressWarnings({"unchecked", "varargs"}) to supress these warnings.
  • The try-with-resources Statement - The try-with-resources statement is a try statement that declares one or more resources. A resource is an object that must be closed after the program is finished with it. The try-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements the new java.lang.AutoCloseable interface or the java.io.Closeable interface can be used as a resource. The classes java.io.InputStream, OutputStream, Reader, Writer, java.sql.Connection, Statement, and ResultSet have been retrofitted to implement the AutoCloseable interface and can all be used as resources in a try-with-resources statement.
  • Catching Multiple Exception Types and Rethrowing Exceptions with Improved Type Checking - A single catch block can handle more than one type of exception. In addition, the compiler performs more precise analysis of rethrown exceptions than earlier releases of Java SE. This enables you to specify more specific exception types in the throws clause of a method declaration.

The Future .... JDK 8

Although Java 7 has only just been released today the future is coming (some might say its already here), since Java 7 was part of a two pronged strategy undertaken late last year (2010) to ensure a JDK release in 2011 (given that it had been 5 years since releases). With the takeover of Sun by Oracle last year and the Java release having been pushed back several times a proposal was made by Mark Reinhold on his blog  (http://blogs.sun.com/mr/entry/rethinking_jdk7) for one of two options. Push ahead with the current plans for Java and take another 2 or 3 years to the release or trim down the functionality set and aim for a mid-2011 followed by a late-2012 release with the remaining functionality initially proposed for Java 7 to be released in Java 8. The  descision to go with the second option can be seen on Marks blog:

Labelled Plan B it looked roughly like:
  • JDK 7 (minus Lambda, Jigsaw, and part of Project Coin)  Mid 2011
  • JDK 8 (Lambda, Jigsaw, the rest of Project Coin, ++)        Late 2012
A detailed list of functionality for the two JDK's followed:
Along with both a JSR for JDK 8: 
And a set of project pages for each of the JDK 8 features to be implemented still:
So there you have it....JDK 8 and definately stuff to look forward to in that lot, not too mention that there will be multi-core performance improvements made as part of JDK 8 on the non-programming side of things amongst other changes.
Keep watching this space!!!

    Wednesday, July 20, 2011

    (java.util.logging/SLF4J/Log4J) + Glassfish v3 + Per-Application Logging

    java.util.logging + Glassfish v3 + Per-Application Logging

    After reading a lot of stuff on the web ... java.util.logging in Glassfish (up to at least v3.1)...per application logging (ie: server.log captures all logs, then individual app1.log, app2.log etc logs capture logging just from app1, app2 etc.) is not possible (using just the /config/logging.properties) to configure. See the following (in a roughly chronological order over the last few years):


    As those all suggest there is a single loaded java.util.logging in the Java Classloader (as its part of java) and hence there is a single logging.properties for configuration. This means you can only define a single java.util.logging.FileHandler in logging.properties and hence output can only be sent to a single location rather than one per app. Whats more....as a cool thing, since there is only a global logging solution, theres no reason why my app cant get the root logger, set its log.level programatically to FINEST and Bobs your uncle I have every possible log, logging in Production (possibly spilling out usernames and passwords or any other info developers may want to see in DEV but lock down in Production...DB connection details anyone?). So not so good on the security (tho this does require you to have access to deploy to the domain so where not exactly hacking anything here...more just subverting). Funny thing is this is known, and has been for years if you read the links above...but personally I dont see how they can get around this security risk...which is why it probably is still an ongoing issues after 4 or 5 years.

    What ways are there around this? A number but none are really pretty. First of all you can add the following code to each and every application in a block in some class that you know will be loaded by the classlaoder initially:


        private static final Logger loggerRoot = Logger.getLogger("org.some.app");
        private static final Logger logger = Logger.getLogger(AppMainClass.class.getName());
        {
            logger.warning("This will only go to server.log");

            Handler h = null;
            try {
                h = new FileHandler("app-1.log");
                h.setFormatter(new SimpleFormatter());
                loggerRoot.addHandler(h);
            }catch(IOException ioe){
                ioe.printStackTrace();
            }
            logger.severe("This will now get logged to both server.log and to app-1.log.");
        }

       
    This works but .... theres always a but and in this case theres 2 .... but 1) you have to add this initialiser block within some quickly loaded class because until the classloader loads this class and hence initialises this block you wont have you app-1.log defined. So its kinda YUCK to have to add this programmatically to every class. But 2) Sometimes if you redeploy without stopping and starting the domain completely app-1.lck lock files hang around and before you know it you have a app-1.1.log app-1.2.log, app-1.3.log with a new log file after every deploy and ... get this .... the logging going not just to the latest log file ... but too ALL the log files. Thats gotta be great for performance once we get to a stage of logging the same log statement to 20 different log files. Maybe theres some way around this....I tried setting various parameters like append=true (append to existing file) and count=1 (max count of xxx.#.log files...ie: create only a single log file) but of course neither of these setting helped and my log files continued to grow, require domain bounces and manual cleanups. Its about at this stage, when I saw this, that I chucked in the towel in disgust with this method.

    So, secondly you could extend java.util.logging.FileHandler with say MyApp1FileHandler, MyApp2FileHandler, and then define each of these in the logging.properties per app. But you need a new file handler per application whose logs you want to seperate, and further more you also have to package and deploy these MyXXXFileHandlers into glassfish in a MyXXXHandler.jsr, so that they can be picked up by the Glassfish Classloader....which makes this probably more complicated and annoying than just the initialiser block above.  However as an example this shows how to create a CustomHandler should this nightmare tickle your fancy:


    So what next ... cant be that hard to get per-application log files can it ? Surely not? Thats what I thought but turns out ... well at least with java.util.logging and Glassfish (and most likely other servers that dont use custom extensions) ... it is. 

    So what else can we do ?



    SLF4J + Glassfish v3 + Per-Application Logging

    SLF4J Rocks! Everything I read about it rocks! The ideas and concepts (ie: parameterised log statements, greater speed + everything from Log4J that was good...thanks Ceki Gülcü) rock! Its the successor to Log4J which also rocked...so SLF4J is even more 'rock-in'! So lets use that for per-application logging in Glassfish. Right? Not so fast...that'd be frankly too damn easy. What you think you can use the greatest logging framework out there and just get per-application logging working. No...of course you cant. Nothings that easy. But why? Well again its all to do with classloaders (in particular Glassfish's), although in a slightly different way to the java.util.logging issues mentioned earlier.

    Turns out that Glassfish uses WELD internally (WELD being the implementation of: JSR-299: Java Contexts and Dependency Injection for the Java EE platform (CDI)). So what you say .... well turns out that the WELD implementation in Glassfish (at least up to v3.1 when I last checked) includes SLF4J internally. This means that when you deploy your app with its SLF4J libs and config ... errr .... well Glassfish ignores them cos the beauty of classloaders is we go up the tree via the parents as far as we can to get our implementation (which in this case means that we end up using the WELD SLF4J version) and hence we ignore our own per-application logging SLF4J properties file. Beautiful ... screwed again!!!


    Again ... known issue and in fact has/had the 2nd largest amount of votes for a fix in Glassfish JIRA bug tracker. But that doesnt help people stuck on a non-bleeding edge version of Glassfish for the foreseeable future...even if there was a fix implemented....which at present (July 2011) there is not.


    Yay!!! Or....in the immortal words of John McClane/Bruce Willis(Die Hard) .... YippeeKaaayey Motherf*cker.


    I mean seriously ... Im not asking for the world here....per-application seperated out log files....surely given this was possible back in the 70's using a couple of shell scripts I should be able to achieve it today ? Considering were so technologically advanced and all after all. (Oh and in case it doesnt come across through text so well....insert a heavy dose of SARCASM right here).


    So what next?


    Log4J + Glassfish v3 + Per-Application Logging (+ Me Screaming If This Fails Like java.util.logging & SLF4J Above...)

    So what fun things did I discover with Log4J. Well for starters the classloader hierarchy and associated configuration of Log4J properties works in reverse to something like JUL. The lowest classloader in the hierarchy overrides the config from any higher classloaders. So if you setup a properties file in /config/log4j.properties using the system property added (-Dlog4j.configuration=file:///${com.sun.aas.instanceRoot}/config/log4j.properties) as described in this guys blog: 


          http://weblogs.java.net/blog/2007/08/28/hell-jdk-logging-ii


    and the log4j.properties looks like:


          log4j.logger.xxx.yyy.zzz=DEBUG,stdout,GF_XXX_FILE


    .....and then later in your app you do :


          log4j.logger.xxx.yyy.zzz=DEBUG,stdout


    ...you will only get the stdout appender added to this logger not both of stdout,GF_XXX_FILE that server property file had defined.


    Whats more things arent cumulative as I found out so defining the GF_XXX_FILE appended in the glassfish server log4j.properties and then attempting to use it from the application log4j.properties wont work (which is to be expected i guess). I initially wanted to have a server level properties file that I could use to define appenders to at least seperate files and perhaps to standard out as well and then assign those appenders to loggers. This would've been great as you go to the single log4j.properties file and modify that for each app in the domain. However, as always this wasnt so simple for me. Since I already had some apps that defined their own props files within the app deploy these would over-ride the domain level prop file and Id end up with config in two places (server level for some apps and app level for the rest).


    So i decided to finally only use application-level log4j.properties and package them up with the deployed modules per application with the config for seperate file logging within each prop file. 

    And.....this works for us!!! A little anti-climactic after that entire spiel but hey....


    And so now, 3 days later, Ive spent probably an order of magnitude longer on this than I should've .... frustrating .... but on the other hand I know everything about every known logging framework and their quirks. Hmmmm....I wonder how I can use that on a CV ??? :-)

    Notes: