Wednesday, September 29, 2010

Suppress logback initialisation messages

Recently I noticed logback logging lots of joran messages, I'm sure it just started happening one day.

With a little playing around I believe that the messages are a symptom of the element deprecation. If you replace the layouts with the correct tags the messages go away.

I used to see this

00:52:57,820 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
00:52:57,820 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
00:52:57,821 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback.xml] at [file:/home/michael/src/stickycode/trunk/net.stickycode.examples/sticky-example-mockwire/target/classes/logback.xml]
00:52:57,954 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - debug attribute not set
00:52:57,962 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
00:52:57,971 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [CONSOLE]
00:52:58,016 |-INFO in ch.qos.logback.core.joran.action.NestedComplexPropertyIA - Pushing component ...
...


But by changing


<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>info</level>
</filter>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{yyyy-MM-dd} %d{HH:mm:ss} %.-1level %thread %logger{36}: %m%n</Pattern>
</layout>
</appender>



to


<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>info</level>
</filter>
<encoder>
<pattern>%d{yyyy-MM-dd} %d{HH:mm:ss} %.-1level %thread %logger{36}: %m%n</pattern>
</encoder>
</appender>


All the joran/logback messages have disappeared. Yay.

Monday, September 20, 2010

Subversion, kwallet and eclipse hangs

I noticed recently that subversion had added kwallet support, awesome.

But it makes eclipse hang if you use javahl with subclipse and most like other integrations.

There are two possible solutions that i've found

1) use svnkit with subclipse

2)Or you can tell svn command line to use a different config, eclipse will store the password encrypted as well but thats ok as long as its not plain text.

I just copied my .subversion/ to .subversion-cli and added an alias to .bashrc

alias svn='svn --config-dir ~/.subversion-cli'

Tuesday, June 29, 2010

Finally exceptions as parameters in slf4j 1.6

Exceptional parameters

So with slf4j 1.6.0 you can do

try {
something
}
catch (SomeException e) {
log.error("some message {}", parameter, e);
}


That just makes slf4j that much easier to use.

Gotcha
Be aware it is ONLY the last parameter. If the last parameter is an exception the stacktrace will be logged. Looking briefly it appears that the exception remains available for replacement so


log.error("Message {} error {}", "parameter", exception)"

Would look like "Message parameter error exception.getMessage", with a trace after. Don't quote me though, try it for your self.

The old way
It used to be that the e would just be ignored which is very substandard. As you would just never know until you deployed it and it failed and you really wanted the error.

Or you would have to write

try {
something
}
catch (SomeException e) {
log.error("some message " + parameter, e);
}


Logback
If you use logback you should use 0.9.22 to go with slf4j 1.6.0 I found other combinations troublesome.

Friday, May 14, 2010

The correct Maven release plugin in may 2010 UPDATED

In my current contract we use subversion for source control and maven2 for release management.

Release plugin running even when there are mods
I've been using the maven-release-plugin for years without issue however recently we realised that using maven 2.1.0 and release plugin 2.0-beta-8 allowed releases with working copy modifications. This is a major drawback it means if different people makes tags of the same artifact they might be different even if made seconds apart and one of the reasons for using the release plugin in the first place.

After a day of testing different combinations i've ended up using Maven 2.1.0 and release-plugin 2.0-beta-9 with remoteTagging disabled. Why?

Why Maven 2.1.0 and maven-release-plugin 2.0-beta-9
We use ranges and release plugin v2.0 can't resolve ranges.

Maven 2.2.1 generates bad checksums for the repository metadata (or calculates it incorrectly locally) so when you are resolving dependencies you get checksum warnings everywhere, not a good look for a professional contractor to leave warning all over and build and release process. So Maven 2.2.1 is out.

Release plugin 2.0-beta-8 does not fail when there are working copy modifications.

Remote tagging. Well after thinking about that for a few minutes I realised it was a terrible idea so I switched it off.

In nearly every project I've ever worked on you don't need to generate a site for each artifact, attaching the sources is sufficient for IDE's and well they don't really have a site. If there was decent aggregation my depedencies into one site I might use it. But doing site just slows it down. All the test reports are in hudson anyway.

And then I realised it didn't work
You have to force the scm version being used too. Which is not too hard just set the dependency for the plugin

The resultant config

<plugin>
<artifactId>maven-release-plugin</artifactId>
<version>2.0-beta-9</version>
<configuration>
<preparationGoals>clean enforcer:enforce verify</preparationGoals>
<goals>enforcer:enforce deploy</goals>
<tagBase>${svn.repo.base.url}/tags/release/${project.groupId}/</tagBase>
<remoteTagging>false</remoteTagging>
</configuration>
<dependencies>
<dependency>
<groupId>org.apache.maven.scm</groupId>
<artifactId>maven-scm-provider-svnexe</artifactId>
<version>1.3</version>
</dependency>
</dependencies>
</plugin>

Wednesday, March 24, 2010

Eclipse is building my maven release!

Who will find this article useful?
If you want to develop with eclipse and use the maven-release-plugin, and not have to have a special working copy for doing release:prepare

Hold on I can't clean
You will find that if you use eclipse and maven and share output directories, doing a clean from the command line will trigger eclipse to rebuild the project.

Whos is really compiling those classes
It looks innocent initially but consider that eclipse is using a different compiler and classpath. Eclipse does not understand scopes for classpaths so you end up with compiler errors not being seen - i.e. class leaks from test scope for example - until someone else tries you build the project later.

How to configure it the right way using the maven-eclipse-plugin and m2elipse
You should alway configure eclipse and maven to use different output directories. See an example pom that shows how to configure the maven-eclipse-plugin to allow you to generate eclipse project files.

With that configuration you should run mvn eclipse:clean eclipse:m2eclipse



How to configure it the right way using eclipse without the m2eclipse plugin
Configure the output path to be target-eclipse/classes

How to configure when using IAM
I imagine the process would be similar to the m2eclipse plugin but I've never tried, sorry.

The release plugin is your friend
When using the maven release plugin - which you should do if you are thinking of using maven at all - makes this all the more important as the standard release process involves, clean, build, tag. If that build is done by eclipse you don't have the two factor validation i.e. command line and IDE to show you build is coherent.

Get rid of the extra working copy
A common solution is to release from a separate working directory than the one you use to develop. Its just an extra overhead you just don't need.

Hope this is useful for people out there, anything to encourage people to use the release plugin.

Tuesday, November 24, 2009

M2Eclipse and the case of the missing sources

I overheard Richard complaining the other day that no matter what he did eclipse would not download the source for one of his dependencies. The source was for a third party library that we manually added to archiva but forgot the source the first time around.

I just remembered reading a note about dependency:sources caching unsuccessful requests. The cache is stored in the target directory so using mvn clean will clear it. I can't imagine why you would want this at the artifact level esp when its cached in the target directory. The whole repository manager idea is a ad-hoc solution to solve a fundamental flaw in the approach to artifact management. But I'll leave that for another day.

I assume that a similar thing happens in m2e. So if you Right click on project -> Maven -> Download sources and nothing happens, try doing a project clean first. And see if that helps.

Friday, November 20, 2009

M2Eclipse and the dreaded ClassNotFound

M2Eclipse and split output directories
Recently I had the experience of some pain using m2eclipse, maven and eclipse. I thought i would share this with you and hopefully save you the same pain.

If you use maven2 and eclipse, m2e is very handy tool.
  1. It resolves dependencies and gives you a classpath as defined by the pom.
  2. You can edit the pom live and autocomplete things like dependency names and plugin configurations
  3. It will link snapshoted projects together for refactoring
  4. It will automatically link up source jars so you can browse the source of dependencies

I think those benefits outweight many of the issues that other people seem to baulk at.

Eclipse is my IDE

To me it seems natural that Eclipse is my IDE I use it to develop quickly with refactoring support and all the other goodness. I use maven to manage my dependencies and releases. I keep them separate so always had separate output paths for eclipse and maven. I never run maven from inside eclipse.

If you ask why, consider I want to do a release:prepare which does a clean, test then a tag. Now if eclipse is open and using the same output paths it will rebuild the classes as soon as I do the clean. The whole point of using maven for the release is that the classpath is very well defined for main compile. Eclipse merges test and compile scope and add its own jars in if you're not careful. So that means the class that are compiled might not be using the well defined classpath and I've wasted my time.

So everything in my world was good until I started a new project and was forced to install a new machine. Naturally I got the latest version of the M2Eclipse plugin and everything went to custard.


ClassNotFound

So I carried on with my standard approach of defining different output folders for eclipse. Maven would build to target/classes and eclipse to target-eclipse/classes. However without rhyme nor reason junit or my application runners would not find classes that eclipse had built.

Richard mentioned the note on the m2eclipse website saying that as of 0.9.4 the classpath was tweaked for maven in eclipse.

So I'm running Junit in eclipse so why should I care? Well I went trawling in the code base and comparing revisions to see what was going on and this is what I found.

  1. It was actually the third 0.9.4 release that made the change. I was previously using the first 0.9.4 release and had no problems.
  2. M2Eclipse intercepts the application, junit and testng launchers and scopes them properly. That means application run in runtime scope only. Tests run in test scope.
  3. Did you click?... that means that the output folders in the classapth for applications, unit and testng are the maven ones NOT the eclipse ones.
  4. M2Eclipse stores the output directoris in the workspace metadata separately from how eclipse defines them. It IS possible for this to be stale and that is incredibly confusing. This is when everything looks right everywhere but regardless your classes are still not found.
On pondering for a while I can see the reasons

  1. This was too allow proper scoping of tests and applications to stop the eclipse scope bleed.
  2. And because of this pearler... some maven plugins hardcode there paths and won't run in eclipse. I would have thought fixing the plugins would be a better idea but in any case...
It was a bit mean to just change the default rather than allowing a new option to configure it so if you had issues with a plugin you could work around it till the plugin was fixed. As stated above I think its pretty crazy to share the output paths cause you never know what you are actually getting.

Not to the solution...

How to set things up properly
So you should follow the instructions on the m2eclipse website and set up a profile for maven in your parent pom. Or check out my example. The following assume you are using my example which differs only in the profile name.

Because you are configuring how maven will run in eclipse as well as eclipse the easier approach is to use the maven-eclipse-plugin with the m2clipse goal
mvn eclipse:m2eclipse
You will need to make sure however that
  1. You enable the profile when you do that... mvn -Prunning-in-eclipse eclipse:m2eclipse
  2. You run eclipse:clean do remove the old config file mvn -Prunning-in-eclipse eclipse:clean eclipse:m2eclipse
  3. You don't have the project open in eclipse otherwise the workspace will end up stale and m2eclipse will see the old path. You might even need to clean your workspace if things go pear shaped
  4. Configure the maven eclipse plugin to enable the profile by default otherwise when you regenerate it will be turned off again
The easiest way to see this in action is to check out

svn co http://gholam.googlecode.com/svn/trunk/net.gholam.example/m2eclipse

and look at the README, you will find instruction for using the maven-eclipse-plugin in the different ways to see it generate correctly.

Don't panic
Ultimately using maven2 and eclipse you will get unexpected thing happening. M2Eclipse is only 0.9.8 so still not a release. Hopefully I have provided a little insight into the things that might go wrong when spliting output directories in eclipse.

If you done everything and you still have issues try starting eclipse with -clean to refresh your workspace and then opening and closing the relevant projects and see if that helps.

Credits
Thanks to Richard Vowles for encouraging me to start a blog, and for announcing it on IllegalArgument.com.