Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

Monday, February 15, 2010

Step 4.5 – Spring DM Extender Logging

I’m going to sneak in a bonus blog post in the Enterprise OSGi series as I think some people may have had issues in getting the last step to work and will be relatively stuck without a little help in debugging what the heck is going on with Spring DM Extender. Enabling logging on a bundle that you did not write may seem tricky. Some may even attempt to download the source, tweak it and re-bundle the extender. A cool feature of OSGi is the ability to extend bundles that you’ve not written by developing a Fragment. Fragments allow bundles to be closed for modification, but open for extension. They are typically used to customize web bundles with separate UI skins (as we’ll see later), internationalization, separate OS installations, and a few other niche cases. In our case, we’ll leverage a fragment to customize the log level of the dm extender so that we can figure out what is going on when say, our bundle doesn’t start and there are absolutely zero messages explaining why. Let’s get started by creating another bundle

Screen shot 2010-02-15 at 8.28.05 PM

I passed another couple of flags to maven on this command to ensure that it doesn’t create any internal or interface classes that we’ll have to delete. In our simple case of enabling some logging, we really only need to add a single log4j.properties file to get the magic to happen. I placed it in a src/main/resources/ to keep in line with a typical maven project and added some simple verbose logging configuration.

log4j.rootLogger=info, A


log4j.appender.A=org.apache.log4j.ConsoleAppender


log4j.appender.A.layout=org.apache.log4j.PatternLayout


log4j.appender.A.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n


The last order of business is to adjust the manifest to attach this fragment to a host bundle. As usual, we accomplish this task by adding the following line to the BND file



Fragment-Host: com.springsource.org.apache.log4j


Compiling the project and running pax-provision should provide a slew of information regarding the process spring uses to look for bundles and resolve dependencies



Screen shot 2010-02-15 at 8.58.21 PM



If you’ve had issues, this will hopefully provide some clues as to why the dm extender was not able to find your dependencies. My most frequent mistake is to misspell the directory containing the context files. In the next post, we’ll resume our regularly scheduled programming by providing a database backed persistence layer in our application.



Examples, as always available on github.

Thursday, February 11, 2010

Step 4 – Spring Dynamic Modules

Our previous installment finally began to show the benefits of OSGi. Service production, consumption and registry were all accomplished programmatically with the APIs of the OSGi specification. While this does provide the benefit of reduced coupling and improved cohesion in an enterprise application, the end result was an invasive and difficult to test implementation. Surely there has to be a better way?

The good people at SpringSource asked the same question and they came up with a solution that feels very natural to Spring developers: Spring Dynamic Modules. Spring DM provides OSGi developers with a declarative means of wiring bundles together in much the same manner that the Spring framework allows developers to wire together Java classes. Getting up and running requires a couple of new repositories and an import from the root project level.

Up until now we’ve been able to download the few OSGi bundles that we’ve needed from the typical maven repositories. When we begin to use the Spring extender for OSGi, a number of other bundles will come into the picture. Downloading these bundles from the maven repositories can be hit or miss, so instead let’s use the SpringSource Enterprise Bundle Repository as our main repository for OSGi bundles. EBR is basically a collection of commonly used libraries for Java in valid OSGi bundle form.  Add the two repository locations with pax construct using the following commands from the root directory:

pax-add-repository \
-i com.springsource.repository.bundles.release \
-u http://repository.springsource.com/maven/bundles/release
pax-add-repository \
-i com.springsource.repository.bundles.external \
-u http://repository.springsource.com/maven/bundles/external


Then we can slightly adjust the pax import command to pull in the Spring DM extender and all of it’s dependencies in one fell swoop.



Screen shot 2010-02-11 at 7.34.37 AM



This command is a little different from prior imports in that we have added a couple of properties to the maven command. The importTransitive property instructs pax-construct to not only pull in the spring-osgi-extender, but also all of the other bundles that it depends on. The widenScope property instructs it to import not only those compile time bundles, but also the runtime dependencies as well. This should result in a slew of downloads occurring in your main project directory.



Using Spring DM extender will remove the OSGi programmatic approach to wiring and activating bundles, in favor of autowiring bundles together in a Spring context. By default the extender will look in META-INF/spring for any .xml files that it can sink it’s teeth into. I follow the pattern of using an OSGi specific context and an other file for all the rest. Change to the directory of the service bundle and from there create a src/main/resources/META-INF/spring directory. Within that directory, we’ll create two application context files. The first, service-context.xml will just declare the service implementation as a bean:



<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
  
  <bean id="raffleService"
    class="com.pillartech.raffle.service.internal.RaffleServiceImpl" />
</beans>


The osgi-context.xml is fairly straightforward as well:



<beans:beans xmlns="http://www.springframework.org/schema/osgi"
  xmlns:beans="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/osgi
  http://www.springframework.org/schema/osgi/spring-osgi.xsd
  http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
  <service ref="raffleService" 
    interface="com.pillartech.raffle.service.RaffleService" />
</beans:beans>


This context decalres the osgi namespace as the default and can then simply publish the service to OSGi via the <service> tag. You’ll note it uses a reference to the raffleService bean in the other context, make sure these match. With these two files in place the activator for this bundle is no longer necessary. Remove that entire file and you should be able to compile and deploy.



OSGi also provides a means for consuming services. Let’s change the Rigged bundle to make use of it. Start by creating the same src/main/resources/META-INF/spring structure so that the dm extender will find all of the contexts. The OSGi context for a consumer is very similar to the producer:



<beans:beans xmlns="http://www.springframework.org/schema/osgi"
  xmlns:beans="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/osgi
  http://www.springframework.org/schema/osgi/spring-osgi.xsd
  http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
  <reference id="raffleService" 
    interface="com.pillartech.raffle.service.RaffleService" />
  
</beans:beans>


The major change is that instead of using a service tag to produce a service, we use a reference tag to consume one. The rigged activator class will need changed to consume this service via dependency injection. Let’s tweak that class so that all OSGi based lookups are removed and replace it with a simple setter. While we’re in here, let’s also remove the APIs for bundle activation as well. The end result is a ServiceBasedRiggedRaffleActivator that looks like this



package com.pillartech.raffle.rigged.internal;
import java.util.Set;
import com.pillartech.raffle.service.RaffleService;
public final class ServiceBasedRiggedRaffleActivator {
  private RaffleService service;
  
  public RaffleService getRaffleService() {
    return service;
  }
  
  public void setRaffleService(RaffleService svc) {
    service = svc;
  }
  
  public void start() throws Exception {
    if (service != null) {
      addEntrants();
    }
    else {
      System.out.println("Unable to rig the raffle, cannot get a handle on the service");
    }
  }
  private void addEntrants() {
    System.out.println("Adding entrants");
    final int COUNT = 10;
    for (int i = 0; i < COUNT; i++) {
      service.addEntry("Todd("+i+")", "toddkaufman@gmail.com");
    }
    System.out.println(COUNT + " entries added to the raffle.");
  }
  public void stop() throws Exception {
    System.out.println("And the winner of the raffle is ...");
    Set<String> winners = service.pickWinners(1);
    for (String winner : winners) {
      System.out.println(winner + " won!");
    }
  }
}


You can tell by the imports that this code now has zero reliance on OSGi APIs so it is easier to understand and maintain, with the benefit of also being able to be tested in isolation. The final step in getting this to work is to create a context file that wires up the rigged class with it’s dependency on the external service bundle. The rigged-context.xml is



<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
  
  <bean id="riggedActivator"
    class="com.pillartech.raffle.rigged.internal.ServiceBasedRiggedRaffleActivator"
    init-method="start" destroy-method="stop">
    <property name="raffleService" ref="raffleService" />
  </bean>
</beans>


Here we make use of the init-method and destroy-method properties of a spring bean to automatically kick off the raffle and shut it down, just as we did with the bundle’s OSGi start/stop lifecycles. One last item of cleanup is to tweak the BND files for both bundles to reflect the removal of a BundleActivator. While we’re in there I would add the following line so that Spring does not expose the bundle’s context to other services:



Spring-Context: META-INF/spring/*.xml;publish-context:=false


Executing a mvn clean install and pax-provision command should provide you with a more verbose lifecycle to these bundles, but the main functionality remains the same. Starting and stopping the rigged service will create a raffle and pick a winner as you would hope.  We’ve deleted a slew of code and added just a handful of configuration to the application to get a simpler and easier to test set of bundles. In the next installment we’ll build upon the use of Spring DM from this point on by adding some database interaction as 90% of the apps we write would.



Source is available as always on githhub.

Monday, February 1, 2010

Step 3 – Service Consumption

OSGi has often been referred to as SOA inside a JVM and I think that’s a fair analogy. The beauty of OSGi is that you do not have to deal with much of the <ceremony /> involved in traditional web services approaches. Comparing OSGi to traditional SOA implementations shows that the complexity is lower, performance is better, and all of the power is still there with OSGi. The one exception to this rule is when your application needs to connect to non-JVM based dependency, you’ll still need to use web services.

In the last few posts, we’ve managed to create a domain bundle and create a rigged raffle bundle that makes use of it. Let’s change this implementation to have a domain agnostic service layer that can leverage the domain bundle under the hood (or a database, web service provider, or something else in the future). Attentive readers will know the drill by now. Start out by creating a service bundle using pax-create-bundle from the project directory.

Screen shot 2010-02-01 at 2.15.40 PM

Creating the service is pretty straightforward. We’ll provide a publicly accessible interface in the com.pillartech.raffle.service package.

package com.pillartech.raffle.service;
import java.util.Set;
public interface RaffleService {
  public void addEntry(String name, String email);
  public Set<String> pickWinners(int numOfWinners);
}


This service allows a consumer to add an entry, and pick  a certain number of winners which is all our rigged consumer really needs at this point. A common practice in OSGi is to create an internal package underneath this main package to store all of non-public classes. Only packages explicitly exposed in the manifest will be made public for other bundles, not directories underneath, so we’ll store our service implementation and activators in this internal directory. Create a com.pillartech.raffle.service.internal package and define a class within this package that implements the service interface. My implementation is fairly straightforward:



package com.pillartech.raffle.service.internal;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import com.pillartech.raffle.domain.Entry;
import com.pillartech.raffle.domain.Raffle;
import com.pillartech.raffle.service.RaffleService;
public class RaffleServiceImpl implements RaffleService {
  private Raffle raffle = null;
  public RaffleServiceImpl() {
    raffle = new Raffle();
  }
  public void addEntry(String name, String email) {
    Entry e = new Entry();
    e.setName(name);
    e.setEmail(email);
    e.setCreated(new Date());
    raffle.addEntry(e);
  }
  public Set<String> pickWinners(int numOfWinners) {
    raffle.setNumberOfWinners(numOfWinners);
    Set<Entry> winners = raffle.pickWinners();
    
    Set<String> winnerNames = new HashSet<String>();
    for (Entry entry : winners) {
      winnerNames.add(entry.getName());
    }
    return winnerNames;
  }
}


As you can see, this trivial example just stores the domain objects internally and translates the simplistic arguments passed in to domain objects within the raffle. This may seem like a zero sum gain compared to our last implementation and in all honesty it is. It does pave the way for our service bundle to do things like leveraging a database, and managing transactions across separate DAOs which we’ll accomplish in due time.  Now, we are one activator away from having a viable service published in our container. In the internal directory create an activator class and plumb in some code like this:



package com.pillartech.raffle.service.internal;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import com.pillartech.raffle.service.RaffleService;
public class RaffleServiceActivator implements BundleActivator {
  public void start(BundleContext bc) throws Exception {
    bc.registerService(RaffleService.class.getName(),
        new RaffleServiceImpl(), null);
  }
  public void stop(BundleContext bc) throws Exception {
  }
}

This activator leverages the BundleContext passed into the start method to register the service. We’re using the common practice of publishing the service using the fully qualified class name of the interface. At this time we could provide a file location, database connection, or other such dependency into the constructor of the implementation, but we’ll get to that soon enough. If you do provide such dependencies, make sure that they are cleaned up and destroyed in the stop method of the activator as well. All that is left is to update the BND file to the name of your activator and you should have a deployable service bundle. Feel free to run mvn install and pax-provision to test the waters.

Publishing the service is the easy part, we still need to consume this service from the rigged raffle bundle. From the rigged bundle directory, run a pax-import-bundle, providing the information used when creating the service.



Screen shot 2010-02-01 at 2.40.00 PM 



Now, we need to re-implement the activator in the rigged bundle to take advantage of the beautiful service waiting out there for us. My updated copy is this:



ackage com.pillartech.raffle.rigged.internal;
import java.util.Set;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.util.tracker.ServiceTracker;
import com.pillartech.raffle.service.RaffleService;
public final class ServiceBasedRiggedRaffleActivator implements BundleActivator {
  private ServiceTracker tracker;
  private RaffleService service;
  
  public void start(BundleContext bc) throws Exception {
    System.out.println("Grabbing a handle on the raffle service");
    tracker = new ServiceTracker(bc, RaffleService.class.getName(), null);
    tracker.open();
    
    service = (RaffleService) tracker.getService();
    if (service != null) {
      addEntrants();
    }
    else {
      System.out.println("Unable to rig the raffle, cannot get a handle on the service");
    }
  }
  private void addEntrants() {
    System.out.println("Adding entrants");
    final int COUNT = 10;
    for (int i = 0; i < COUNT; i++) {
      service.addEntry("Todd("+i+")", "toddkaufman@gmail.com");
    }
    System.out.println(COUNT + " entries added to the raffle.");
  }
  public void stop(BundleContext bc) throws Exception {
    System.out.println("And the winner of the raffle is ...");
    Set<String> winners = service.pickWinners(1);
    for (String winner : winners) {
      System.out.println(winner + " won!");
    }
    
    System.out.println("Releasing handle on the raffle service.");
    tracker.close();
  }
}


You’ll notice in this example we now have to make use of a ServiceTracker to access the published service. In OSGi land, services can come and go at any time. ServiceTracker’s can be used to grab a handle to a service and optionally wait if one is not available.  Leveraging the service tracker we then access the published service via the interface and interact with it as any normal java class would. Also, take note that we need to close the service tracker in the stop method to ensure that the integration of the two bundles is gracefully decoupled should the rigged raffle go away. If we would prefer to wait for the service should it not be available, we would call tracker.waitForService instead of getService and provide a time in ms to wait should the service not be available immediately. Craig Walls warns against waiting for services in the activator in his Modular Java book though as it may cause a traffic jam of bundles waiting to activate on startup. You should be able to execute a mvn install on the entire project and a pax-provision from the main directory to see everything up and running.



Screen shot 2010-02-01 at 2.55.18 PM



Beauty! We have a working consumer interacting with a service all through the OSGi container.  We’re starting to see how modular bundles can interact within an OSGi container, but if you are like me you are probably feeling pretty dirty about the amount of OSGi APIs that are leaking into your code. Testing these bundles in isolation would require a significant amount of mocking now and we had to manually construct a service implementation using the new keyword. Fear not, there are better, less invasive ways of accomplishing this and we’ll go through them in the next installment.



Examples as always available on github.

Monday, January 11, 2010

Step 0 - Simple OSGi

OSGi is a longstanding framework for building modular applications. I won't go into the details as I'm assuming you are somewhat interested in the framework to have found my blog. Two of the best resources I've found are:

Craig Walls' blog
Kirk Knoerschild's blog

Craig and Kirk are helping many (including myself) to grok the benefits of OSGi and dispel the myths around it's adoption. Specifically, Craig's post refuting the challenges with OSGi covers almost all of the issues usually brought up.

Now that that's settled, let's get a simple example up and running.

I'm going to be using Equinox for my examples. Primarily because it supports all of the features we'll need and also because it's bundled with Eclipse so you can easily find it and get it started.

Download equinox from here. You can just get by with the framework jar. You can start the eclipse container with

java -jar org.eclipse.osgi_3.5.1.R35x_v20090827.jar -console

Issuing a short status command with ss shows



Since we haven't built a bundle yet, the only thing available is the osgi core bundle. A bundle is simply no more than a jar file with a quirky META-INF/MANIFEST.MF file. Building the equivalent of Hello World can be done with this:

    1 package com.pillartech;
2
3 import org.osgi.framework.BundleActivator;
4 import org.osgi.framework.BundleContext;
5
6 public class SuperSimple implements BundleActivator {
7
8 public void start(BundleContext ctx) throws Exception {
9 System.out.println("Starting Up!");
10
}

11
12 public void stop(BundleContext ctx) throws Exception {
13 System.out.println("Shutting Down!");
14
}

15 }


This is just a java file though until we add the magic to a MANIFEST.MF file and jar the thing up. Here is a simple manifest to get started:

    1 Bundle-ManifestVersion: 2
2 Bundle-SymbolicName: com.pillartech.SuperSimple
3 Bundle-Name: SuperSimple
4 Bundle-Version: 1.0.0
5 Bundle-Activator: com.pillartech.SuperSimple
6 Import-Package: org.osgi.framework


As long as you include the symbolic name of the bundle it should work, but the rest of it gives you a feel of the meaning of the manifest. It provides all of the information used by other bundles to consume it, and also a list of the other bundles that it imports.

Compiling this class and jar-ing the class and manifest together allows you to deploy it and start it



From there you can see descriptive information about this bundle and it's manifest with the bundle and headers commands



Stopping the bundle will produce an equally productive message and return it to the INSTALLED state. Finally issuing an exit command will shutdown the container.

So with this example we've done the simplest thing we can to get a bundle installed, started, described, and stopped in equinox. These commands are the core to developing and manipulating bundles in a runtime with OSGi. We'll leverage them further in the subsequent examples to build our solution.

Enterprise OSGi in 10 steps

I'm presenting a Modular Java pre-compiler session at Codemash and in preparing I have learned a good deal about OSGi. My mode of learning was to take small granular steps towards a front to back solution to a typical project problem, but with the benefit of using OSGi. If you want to follow my footsteps, the best thing you can do is come to Codemash and attend the pre-compiler. If you aren't fortunate enough to get there, I'm going to post 10 blog posts to build up your knowledge of OSGi and the accompanying tools. This post will serve as a table of contents.

Step 0 - Simple Bundle
Step 1 - Creating your Domain
Step 2 - Importing from another Bundle
Step 3 - Service Oriented OSGi
Step 4 - Spring DM
Step 4.5 - Spring DM Extender Logging
Step 5 - Persistence
Step 6 - Integration Testing
Step 7 - Web Development
Step 8 - Skinning a UI
Step 9 - Deploy Time Configuration

Sunday, July 27, 2008

NFJS - Day 3

Spring Talks by Keith Donald
Spring has largely been my focus for the last few years so I was happy to see one of the Spring Source crew stepping up at NFJS. Keith Donald is the lead of almost all Spring web related technologies and he tends to give a very down to earth, code centric presentation so I devoted all of my final day to his talks.

Someone in the audience asked Keith if he missed the common XML file that shows exactly how all your beans are wired when you move to annotation driven POJOs and that question is an important one. I've recently become much more comfortable with developing Spring applications due to the Spring Facet in IntelliJ. Moving to annotations tends to make me question exactly which resource or component is plumbed in to fill a dependency. Keith mentioned that an emerging best practice is to use annotations for self describing application dependencies, XML for infrastructure concerns. He also gave a soft sell for Spring IDE to show a nice dependency graph regardless of annotations or XML.

Spring 2.5 is downright giddy with it's extensive use of annotations and it didn't really dawn on me until Keith's talk that it might be the better way to go in some scenarios. I've traditionally balked a little bit at the extensive use of annotations as it feels very invasive to the code at hand, especially when the annotations are Spring specific. More importantly, swapping out facilities for testing purposes is not trivial when you are doing component scanning and autowiring with annotations. I think Keith articulates an appropriate scenario for use though. Swapping out mock classes via XML is not a benefit that is needed as much for application dependencies as it is one that is needed for infrastructure (data access, email service, file reader, etc...). Go nuts with annotations at the app level, but use a good editor and keep the XML where it belongs for infrastructure pieces.

Keith spent a good amount of time in all of his talks using an IDE focused on Spring MVC controllers. The thing that stood out to me was how Spring web controllers are truly just POJOWAs now (I know that's not a term that will stick but a distinction needs to be made between POJOs and POJOs with annotations). This means that you will rarely see HttpServletRequest or ModelAndView type classes in these POJOs. What's the benefit here? You don't have to waste many of your test cycles mocking up the container objects. Wanna test your login method on the controller? Send in a User object and a String password and then validate whether you are getting a success or error redirect back. Very simple, and anything that we can do to lower the barrier of entry to good testing is well worth it.

Keith demonstrated another key change in coding Spring apps is the impact that Rails has had on the Spring community. The focus has shifted in Spring 2.5 to more sensible defaults and a true convention over configuration model. Controllers in Spring web apps now mimic Rails controllers in URL and request parameter resolution. Additionally, there are a set of special parameter types that are automagically injected. An arg of type Principal will be supplied by the container if the user is already logged in. Very cool.

One final note on the Spring web side. Why do we have another javascript framework? If you have improvements to make to DOJO, please just contribute them to DOJO. Don't create an abstraction layer over DOJO that does what you need. We have finally whittled the .js framework comparison down to a handful in my mind (prototype/scriptaculous, dojo, jquery, yui, and ext). Don't lead us back in the other direction.

Conference conclusion
NFJS again provided some immediate exposure to worthy technologies and processes. I was able to touch base with a lot of people in the Java community that I hadn't seen in some time and I feel like I have more tools in my belt than when the conference started. A special note to the organizers though. If the prices go up again next year while the number of conferences goes up as well, then you won't see me there for the first time in 4 years. It was evident to me this year that the conference is not the value that it was 2 and 3 years ago. If the trend continues, I'd rather spend my training dollars on codemash, erubycon, and books.

Saturday, July 26, 2008

NFJS - Day 2

Stu Halloway's Refactoring Javascript was a topic I did not expect to see at NFJS this year, but I walked away truly impressed. Stu presented a totally different mindset on developing, testing and refactoring javascript code. The gist of it is to use a mock browser that will allow you to run tests against your javascript code in an automated environment. Here is the mock browser but it is still in a beta state so expect to have to bend it to your will. Stu made extensive use of JSSpec for writing BDD specs against an existing javascript framework (livepipe). It was truly telling in the presentation that the first hour was spent trying to get a solid safety net of tests up and passing before we even began thinking about refactoring. Stuart accurately identified this as the norm when refactoring legacy code and it lines up directly with my experience as well. Refactoring can't be done w/o that safety net. When we finally did get around to refactoring, Stuart boiled it down to four areas:

Extract and Shorten
- If your method does more than one thing it does too much
- Keep method size to around 5 - 7 lines

Reduce Clutter
- Nix out of scope variables
- Keep the effort to duplicate a method greater than the effort to understand it

Choose Good Names
- Probably the most difficult of the refactorings
- Definitely the refactoring most in need of pair programming

Use Existing Libraries
- If you are typing document.getElementById then punch yourself first and download prototype.js second.

The talk was extremely hands on and valuable and made me wish I had a bucket of crappy javascript to go back to on Monday. Other things mentioned included another mock browser env: Crosscheck. Stu also mentioned a lack of code coverage tools for Javascript, but I found one during his talk. One last thing, he mentioned a very important refactoring anti pattern. Mirror methods (get and set on cookie) used in each others tests. If you are testing the get method on a cookie object don't explicitly use the mirror method (set). Instead, roll it by hand as a bug in code shared by these methods could offset each other in the test execution.

The second talk I went to was Stu's GIT talk. I've been looking into GIT for a little while and Stu gave a good gentle intro into it by basically walking through scenarios at a command prompt for 90 minutes. That format doesn't necessarily translate to a blog so here are some highlights:

- When using GIT, think less in terms of verbs
- GIT is not SVN++
- It's crazy fast. Branching and tagging for instance are instantaneous
- The entire source history is in every copy of the repo
- It doesn't store deltas, it stores the begin and end and calculates the deltas.
- You are forced to tell git what you are committing. It's not tracking it like SVN
- GIT encourages agility. You may not know what makes a package/release/hunk of functionality until sometime in the future. Additionally, you can stash your current task deliverables, go do something else, and come back to them later.
- Bisecting allows you to do a binary search through releases of code to identify the release that caused a bug. Kick ass.


Metaprogramming in Groovy by Brian Sam-Bodden was the third session I attended. BSB did a good job of going over the major metaprogramming techniques in Groovy. Additionally he had enough examples of Groovy code with TextMate that forced my hand to download it and see if it will cure what ails me with IntelliJ in dealing with Rails and Grails. Stream of conscience notes on metaprogramming with Groovy:
- Much simpler than using dynamic proxies in Java
- Similar to ruby it allows on the fly evaluation of code via evaluate
- Duck typing like ruby with respondsTo
- See yesterday's bits on methodMissing and invokeMethod
- obj."$methodToCall"() is valid Groovy code that will try to call the contents of methodToCall as a method on obj. In my opinion that code is utterly disgusting.

Also, the inevitable Ruby v Groovy topic came up as it did at lunch with me and a few others. There still seem to be zealots on both sides and I wish for the life of me they would just shut up.

My 2 cents are this. Use whatever makes most sense for your environment and team. At my consulting company, that is Ruby b/c I have a lot of .NET fellas that I would like to roll into and out of projects whether it is deployed on MRI, JVM, or DLR. The differences at my admittedly noob perspective are few and far between with the two languages. If it was a room full of Java developers, Groovy might make more sense because it is an easier transition for Java heads. I don't care what you choose for your environment, just quit bitching about the other side.

EJB3 Testing by Joseph Nusairat was my final session of the day. Joseph covered a wealth of testing frameworks in a very code centric presentation. The session was very interactive and covered some cool mocking techniques outside of the realm of EJB3, like dealing with mocking static methods. My attention span was slipping this late in the day, but here is a set of highlights:
- Easymock provides the typical set expectations, record and playback functionality. It is still probably the most proven, well documented, and easy to learn of the mock frameworks.
- JMockIt is a relatively new player with some cool support for AOP and Hibernate. Please notice the IT at the end of the name. JMock is a different framework. Unlike EasyMock and JMock, JMockIt is a very small and straightforward API that can be used to test methods w/o dynamic proxies or cglib.
- EJB3Unit has some very cool facilities. It provides an in memory database out of the box (HSQLDB), uses CSV files for populating the data and provides mocks of almost everything that you would need in an EJB 3 bean. If you have to use EJB3, this framework seems like a valid contender.
- Embedded JBoss is the last one covered and it seems like a good fit for mocking out an entire container when necessary and using JBoss.
- Mocking for unit testing, other tools still necessary for integration and functional tests.

I'm tired. See you tomorrow.

Monday, May 5, 2008

And then there were 3

Oracle has now officially acquired BEA, leaving the app server marketplace for Java EE at 3 major vendors with IBM and JBoss completing the trinity. After having personal experience with both BEA WebLogic and Oracle's Application Server, I plea to Oracle, just use BEA's app server and don't mess with it. Orion was a good product and you turned it into a trainwreck. There is no reason that an application server install should take 4 days and 300 gb of memory. JSPs shouldn't be stored in the database. Oh, and your installer should not need to install JDK 1.2 to run. Leave it alone Oracle and focus on improving your DB.