Recent Posts

RSS Feeds

Alfresco on OS X - ImageMagic and OpenOffice

Alfreso is a fantastic ECM solution that has some amazing features and some great momentum. It has been more than a year since I've used Alfresco and man have they gotten some cool stuff done.

I spent the last couple of days getting certified to teach a couple of Aflresco's classes. I used my mac (running leopard) and I figured I'd post a bit about what I did to get all the features up and running. Alfresco is able to use OpenOffice and Image Magick to do some cool stuff like transform any word doc to PDF or and GIF to PNG etc. Problem is the Alfresco site is short on detail about how to make all that goodness work on the mac.

Being the stubborn guy that I am I would not leave well enough alone and run it on some other OS. It took me a couple of hours but I got everything working. Here are the details...

Grab Open Office from here. I got the aqua interface cause I don't really care about the UI anyway. Install by copying it to your Applications folder. I renamed the app to OpenOffice.app (got rid of spaces) although I'm not sure that is necessary it ended up that way after all the experimentation and I've not had a chance to go back and check if it would work with a space (seemed at the time like something that Alfresco was using was not properly escaping spaces).

Now that you have the OO install done its time to teach Alfresco about it. In your alfresco install (the one that includes tomcat) there is an extensions folder (tomcat/shared/classes/alfresco/extension). Go there and add a folder called 'bootstrap'. Then in there create an XML file called openoffice-startup-context.xml. I've included mine here so you don't have to set it up from scratch. Basically this file tells Alfresco how to startup openoffice in headless mode so that it can be used to do doc transforms.

Install Image Magick with mac ports via a command line that looks basically like this sudo port install ImageMagick. If you are stubborn and you don't want to use Mac Ports the Image Magick community has a binary distro for you here. I used the mac ports build instead of the binary distro so your millage might vary if you use the binary.

That is it, now when you restart Alfresco it will be able to do the document conversion and image conversion. If you are looking for an ECM take a look, its really cool stuff.

Permalink     No Comments

Maven - Choose Your Pain (Re: mostly hate)

So I generally feel that using maven or ant or make or shell scripts, building is a pain in the neck and what ever way you choose you will have pain. You get used to the pain of one kind or another and sort of grow to like that sort of pain and you forget that you ever lived without it. And at times you even start to defend the kind of pain that you like as pleasure. I'm having one of those moments after reading this.

Agreed maven has bugs, agreed maven has some doc problems, but...

Point 1 - the maven release plugin has its faults to be sure but more or less it works as advertised and if you are following the 'typical' path of using your SCM then the plugin even does a very nice job of keeping tags and such for you.

Point 2 - you can specify the path to the parent pom if you don't have it in the default location (e.g. ../pom.xml) in your parent descriptor (look for relativePath).

Point 3 - Agreed this is really irritating (esp the silent failures) but I've not had much trouble with Checkstyle or PMD on my 'very big' multi-module project. More detail would probably turn up some links to fix whatever issues are being experienced.

Point 4 - We use the assembly plugin with great success on Crank. Geronimo uses it as well. I could not tell what the actual problem was from the description given but I'll bet again there are ways to do that.

The 4 specific pain points I think are relatively easy to work through. The other 50+ things who knows. On my team we were tempted to write a custom plugin but we were able to make things work without it and were much better off in the long run IMO. Not that writing a custom plugin is bad, but in most of the cases on IT projects that I've seen folks writing a plugin its because they want to do something counter to the way maven expects. Such a plugin will be nothing but pain long term.

All that said, I feel his pain. I've been using maven for 2+ years and its only the last few months that I feel competent to make a big project really work. I'm not sure if that is completely a lack of docs or problems with maven. But I've gotten used to the pain of maven and I've really started to dislike the pain that I received from Ant (perhaps 2.0 will be worth a look when its done).

Permalink     5 Comments

Java on Leopard - enough complaining

So while reviewing the release notes for Java on Leopard I noticed a couple of interesting bits. First they included junit 4.1 and maven 2.0.6 in the mix, which is great (except that maven 2.06 had some serious bugs with transitive dependencies). mvn is now on your path so you don't have to download to get maven on your leopard box. Second they really cleaned up the awt/swt issues in this release so we can use stuff like Batik in Eclipse now. They also made the default rendering pipeline the Sun pipeline. Over all a ton of good work. JDK 6 and hopefully the full open source stack of 7 will be happening soon enough.

So for Leopard apple did a ton of java work as well as deeply integrating ruby, over all i think we got a sweet package. And I am ignoring all the complaining.

Yes the lack of official information is irritating to me too...

Permalink     3 Comments

Software Summit 2007 - Learn IT and Skiing

Hope to see you there. I'll be talking about Spring vs Guice and Continuous Integration. Its going to be fun and a great spot to learn tons of good stuff. I'm really looking forward to Dion's gears talk.

Make sure to save some energy for Friday afternoon as A-Basin is open!

Permalink     1 Comment

What was I thinking...

I don't know why it irked me so badly. I was looking at my javablogs email and saw that and thought oh wow I was just going on about this I wonder what the post is about. I read it and posted a comment. Now I'm thinking I have too much real work to do to get sucked into this debate again...

Open mouth, insert foot...

Did I mention that I'm really looking forward to CSS? :)

Permalink     No Comments

Interface 21 and economically rational developers...

Matt hit the nail on the head. Ben has a great point. This is exactly the same stuff that JBoss does/did. Rod is much less 'lawyery' (as Matt said and I've experienced, Rod has not come after me or anyone I've heard of with Cease and Desist letters) about it but that is only because the VC's just got their hooks into him. He will in time be forced to start enforcing Interface 21's trademarks just like JBoss must. And that is as it should be, please understand that I'm not hammering Rod, Interface 21 or even JBoss. (As much as I apparently like to do that, the only reason I've ever hammered on JBoss in the past is because they are something that everyone knows. Makes it much easier to discuss a concrete instance rather than some abstract notion).

So anyway we should try to be economically rational and tie our hard work and knowledge acquisition to truly open solutions instead of just being wowed by getting the source for free. Having the source is great, having freedom is even better.

In my opinion as the open source market matures folks like us (developers and consultants) will start to understand this kind of thing more and more. And as new opensource things come to the market we will be more aware of the fact that joining the Spring community enriches chiefly Interface 21 in the same way that joining the JBoss community chiefly enriches RedHat. Now of course as people involved in these communities we are able to make a living, but its only because we are playing the game by Interface 21's (or JBoss') rule book. If we want to do something with JBoss outside that rule book we are smacked down. In truly open communities like Eclipse or Apache you do get ownership when you join the community, true ownership, not just the source code.

And as I've said a bunch of times in the past that is what makes open source cool for me, I get ownership and freedom to do what I can, or am able, to enrich myself. If I'm good at it I help myself and the community. I help myself cause I get to bill, I help the community because I'm helping someone better understand what the community has built. Thus more people are using the software, more people are able to contribute and the ecosystem grows. The same thing has been happening since the beginning of IT, but its always been the companies that made the community.

We are in an age where big companies are not required for a piece of software to become widely used. Don't believe me? Take a look at appfuse. From Matt's passion to grok java web development came something that more than a couple of people have found useful. And there are many other examples of this kind of thing.

Back to Interface 21 and Spring. You can't justify VC and 10x - 20x revenue buy outs on the DHH philosophy. I tend to be with Matt on this (and alot other things too) that I prefer the DHH model of things, I prefer open communities, truly open, where the community decides direction not a single company or single person. Sure the folks that founded the community should be held in high regard and looked to for direction. But for the committers list to be restricted to one and only one company, that is a recipe for Cease and Desist letters.

All I'm saying is that we should be 'economically rational' and put our weight behind communities that will not come back to squash us.

Permalink     8 Comments

Beware, the lawyers are coming

good for tool vendors, perhaps, bad for programmers for sure[Read More]

Permalink     No Comments

Objective C - book in progress

So I've just about finished up the first chapter of my ObjC book. Its been a ton of fun so far.

I posted some thoughts about it here on my objc blog for those that are interested or anyone that might have thoughts about picking up ObjC coming from Java, .NET, C++ etc.

Permalink     No Comments

Software Summit Slides Away...

I finally got my slides off to CSS. Hope to see you there!

Permalink     No Comments

Software Summit 2007

The time is almost upon us to get into the Keystone mode. The Software Summit starts in just a few weeks. I'm really stoked about the content this year and I hope I get to see you there.

One of my favorite things about the conference (besids the content) is the location. Keystone is absolutely beautiful and some years there is early season skiing. Its been really wet this year all summer. Wet summer does not necessarlly point to snow winter but it can't hurt. Its going to be fun!

Permalink     No Comments

i'm a pc, i'm a mac...

By way of macbytes, chuckle...

Permalink     No Comments

Open source shark jumping?

I read a pointer to this on /. the other day and mentally filed it to go back and see what the fuss was all about. I finally had time tonight. Bottom line, Mr. Gould does not get it. Clearly the IBM press release is about making it so Lotus Notes folks are not stuck with Windows. Their client works in a more open environment. It's all about getting rid of Windows for IBM.

I think the point that he might have made that I wold belive is that Open is becoming more and more diluted as its used to market more and more unrelated stuff. Maybe I should rethink my position on Trade Marks ;-) Maybe I'll shell out the ~$375 it costs to purchase the trade mark on 'Open' and then send IBM a C&D letter.

Permalink     No Comments

Spring, DBUnit and OpenJPA

In an attempt to be economically rational I have been spending some quality time with OpenJPA. My initial impression is that its got great potential. I know Kodo had a loyal following of folks that thought the world of the software and since OpenJPA is Kodo opensourced it stands to reason that its a fairly mature bit of code. What I have discovered in my research thus far is that its cool but poorly documented. The Kodo docs are just different enough to make me crazy and Google has only a few hits that show you how to do stuff. So its early but promising.

Towards realizing that promising end I am going to start blogging bits about OpenJPA in the hope that it helps others get their heads wrapped around it and how it works. I intended to do this with all the other open JPA implementations as well (Cayenne for sure and TopLink as well assuming its not 'owned' by any single company).

So on with the show...

This example takes you through using the following bits together;

  • TestNG which I like tons better than JUnit 4.x or 3.8.x
  • DBUnit
  • Spring - autowire tests to the beans in the context
  • Maven - build the stuff and run the tests
  • OpenJPA - formerly known as Kodo, ORM tool

Some time back I wrote up how to use DbUnit to test your hibernate mappings using a rather simplified financial tracking model (can that really be almost 3 years ago???) It is somewhat like the model Yahoo uses. But the model is of course not that sophistated but its purpose in life is not to unseat Yahoo from the height of fininancial management but rather to illustrate JPA modeling and the testing of the models. So with that bit of background lets take a look at the model;

Model

I used the model unmodified (same JPA annotations) with OpenJPA and then applied the same basic approach to testing the app with DbUnit as I did before. As I tried to prove last time, having these types of tests in place is hugely useful to instill confidence in your mappings.

On to the code... The first thing is the Spring integration. The base class makes some assumptions (your test context is defined in testAppCtx.xml for example) and autowires your test to the beans defined in your context. So I can have a test for the FooService that uses and instance of that service that is injected by Spring simply by having a set method. For example, here is the bean defintion for one of the DAO's tested in this example code;

<bean id="userDao" class="net.dudney.jpaund.dao.jpa.BaseDaoJpa">
  <property name="type" value="net.dudney.jpaund.domain.SiteUser" />
</bean>

Then I have Spring inject that DAO into my test class with a simple property like this;

private BaseDao userDao = null;
...
public BaseDao getUserDao() {
  return userDao;
}

public void setUserDao(BaseDao userDao) {
  this.userDao = userDao;
}
...

Now that my test has a pointer to the DAO I want to test I need some data to test it with, the data is captured in the form of XML for DBUnit and looks like this;

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
  <site_user id="1" version="0" username="benvolio" password="where"/>
  <site_user id="2" version="0" username="tybalt" password="forart"/>
  <site_user id="3" version="0" username="mercutio" password="thou"/>
...
</dataset>

and placed into a file in the src/test/resources folder to be picked up by maven and placed into the test classpath. My test simply returns the path to the file in an overridden method like this;

@Override
public String getDataSetXml() {
  return "net/dudney/jpaund/domain/data.xml";
}

The abstract DbUnitTestBase base class takes care of loading the data for you. The data is loaded before any tests are run from each class courtsey of the @BeforeClass annotation. TestNG will run the method that loads data before any other methods in your test class are run. So you can put data to test your DAO or Service in the database once and then use it in each test. If you modify the data in a way that needs to be undone you can reinitialize the database with your data by calling loadSeedData.

Something I learned also during this expierement is that the OpenJPA Maven2 Plugin is not ready for prime time. Dispite my last post on that topic I would stear clear of the M2 plugin and stick with the ant run plugin as suggest on the OpenJPA home page here.

Finally here is the code.

Good luck and I hope this is helpful in testing your JPA stuff...

Permalink     3 Comments

OpenJPA Class Enhancement with Maven

While attempting to put my time and energy where my mouth is I figured I'd take the time to make OpenJPA work in an example I've been doing of getting Spring/JPA/DbUnit to all play nicely together. I've got the example almost ready to post but not quite. Part of what has held me up is a couple of issues I was having getting the tests to work as I expected.

I was consistently getting the following errors:

testSingleParameterQuery(net.dudney.jpaund.dao.jpa.BaseDaoJpaTest)  Time elapsed: 0.11 sec  <<< FAILURE!
<4|true|0.9.6-incubating> org.apache.openjpa.persistence.ArgumentException: Could not locate metadata for the class using alias "Portfolio". Registered alias mappings: "{Portfolio=null}"
	at org.apache.openjpa.meta.MetaDataRepository.getMetaData(MetaDataRepository.java:343)
	at org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.getClassMetaData(JPQLExpressionBuilder.java:164)
	at org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.resolveClassMetaData(JPQLExpressionBuilder.java:142)
	at org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.getCandidateMetaData(JPQLExpressionBuilder.java:211)
	at org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.getCandidateMetaData(JPQLExpressionBuilder.java:181)
	at org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.getCandidateType(JPQLExpressionBuilder.java:174)
	at org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.access$500(JPQLExpressionBuilder.java:61)
	at org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder$ParsedJPQL.populate(JPQLExpressionBuilder.java:1657)
	at org.apache.openjpa.kernel.jpql.JPQLParser.populate(JPQLParser.java:52)
	at org.apache.openjpa.kernel.ExpressionStoreQuery.populateFromCompilation(ExpressionStoreQuery.java:145)
	at org.apache.openjpa.kernel.QueryImpl.newCompilation(QueryImpl.java:642)
	at org.apache.openjpa.kernel.QueryImpl.compilationFromCache(QueryImpl.java:623)
	at org.apache.openjpa.kernel.QueryImpl.compileForCompilation(QueryImpl.java:589)
	at org.apache.openjpa.kernel.QueryImpl.compileForExecutor(QueryImpl.java:651)
	at org.apache.openjpa.kernel.QueryImpl.getOperation(QueryImpl.java:1464)
	at org.apache.openjpa.kernel.DelegatingQuery.getOperation(DelegatingQuery.java:120)
	at org.apache.openjpa.persistence.QueryImpl.execute(QueryImpl.java:202)
	at org.apache.openjpa.persistence.QueryImpl.getResultList(QueryImpl.java:251)
	at net.dudney.jpaund.dao.jpa.BaseDaoJpa.find(BaseDaoJpa.java:97)
	at net.dudney.jpaund.dao.jpa.BaseDaoJpa.find(BaseDaoJpa.java:74)
	at net.dudney.jpaund.dao.jpa.BaseDaoJpa.find(BaseDaoJpa.java:109)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:585)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:281)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:199)
	at $Proxy9.find(Unknown Source)
	at net.dudney.jpaund.dao.jpa.BaseDaoJpaTest.testSingleParameterQuery(BaseDaoJpaTest.java:172)

testSaveOrUpdateObjectNewObject(net.dudney.jpaund.dao.jpa.BaseDaoJpaTest)  Time elapsed: 0.233 sec  <<< FAILURE!
org.springframework.dao.InvalidDataAccessApiUsageException: The type "class net.dudney.jpaund.domain.VersionedObject" has not been enhanced.; nested exception is <4|true|0.9.6-incubating> org.apache.openjpa.persistence.ArgumentException: The type "class net.dudney.jpaund.domain.VersionedObject" has not been enhanced.
Caused by: <4|true|0.9.6-incubating> org.apache.openjpa.persistence.ArgumentException: The type "class net.dudney.jpaund.domain.VersionedObject" has not been enhanced.
	at org.apache.openjpa.meta.ClassMetaData.resolveMeta(ClassMetaData.java:1590)
	at org.apache.openjpa.meta.ClassMetaData.resolve(ClassMetaData.java:1564)
	at org.apache.openjpa.meta.MetaDataRepository.processBuffer(MetaDataRepository.java:654)
	at org.apache.openjpa.meta.MetaDataRepository.resolveMeta(MetaDataRepository.java:554)
	at org.apache.openjpa.meta.MetaDataRepository.resolve(MetaDataRepository.java:479)
	at org.apache.openjpa.meta.MetaDataRepository.getMetaData(MetaDataRepository.java:283)
	at org.apache.openjpa.meta.MetaDataRepository.resolveMeta(MetaDataRepository.java:519)
	at org.apache.openjpa.meta.MetaDataRepository.resolve(MetaDataRepository.java:479)
	at org.apache.openjpa.meta.MetaDataRepository.getMetaData(MetaDataRepository.java:283)
	at org.apache.openjpa.meta.MetaDataRepository.resolveMeta(MetaDataRepository.java:519)
	at org.apache.openjpa.meta.MetaDataRepository.resolve(MetaDataRepository.java:479)
	at org.apache.openjpa.meta.MetaDataRepository.getMetaData(MetaDataRepository.java:283)
	at org.apache.openjpa.kernel.AttachManager.attach(AttachManager.java:233)
	at org.apache.openjpa.kernel.AttachManager.attach(AttachManager.java:97)
	at org.apache.openjpa.kernel.BrokerImpl.attach(BrokerImpl.java:3124)
	at org.apache.openjpa.kernel.DelegatingBroker.attach(DelegatingBroker.java:1120)
	at org.apache.openjpa.persistence.EntityManagerImpl.merge(EntityManagerImpl.java:591)
	at org.springframework.orm.jpa.JpaTemplate$6.doInJpa(JpaTemplate.java:272)
	at org.springframework.orm.jpa.JpaTemplate.execute(JpaTemplate.java:191)
	at org.springframework.orm.jpa.JpaTemplate.merge(JpaTemplate.java:270)
	at net.dudney.jpaund.dao.jpa.BaseDaoJpa.update(BaseDaoJpa.java:118)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:585)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:281)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:187)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:154)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:176)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:210)
	at $Proxy9.update(Unknown Source)
	at net.dudney.jpaund.dao.jpa.BaseDaoJpaTest.testSaveOrUpdateObjectNewObject(BaseDaoJpaTest.java:121)

Which of course lead me to look into how one enhances for OpenJPA with Maven. Which lead me here. Unfortuanately that leaves off the important bit that you have to attach the plugin to a phase (I expected it was attached to process-classes by default, but as you know we should never as-u-me anything:). So anyway after another 20 minutes of googling around to here and here. It finaly dawned on me that my classes were not actually enhanced. So I updated my pom to look like this;

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>openjpa-maven-plugin</artifactId>
  <executions>
    <execution>
      <id>JPA Enhance</id>
      <phase>process-classes</phase>
      <goals>
        <goal>enhance</goal>
      </goals>
    </execution>
  </executions>
  <configuration>
    <toolProperties>
      <property>
        <name>addDefaultConstructor</name>
        <value>true</value>
      </property>
      <property>
        <name>enforcePropertyRestrictions</name>
        <value>true</value>
      </property>
    </toolProperties>
  </configuration>
</plugin>

And bada-boom bada-bing it started working like a champ.

I post this so that others that might be struggeling with the same frustration might find a quicker solution.

Permalink     4 Comments

Economically Rational?

By way of /. I read this. The article is interesting but the really interesting part for the current discussion is in section 4.1 where it states.

Consequently, it makes little sense for the economically 
rational software developer to invest time in commercial open source. 
The value these developers create is tied to the product and the 
owning company. Unless the product is in wide use or the developer
wants to work only for this one company, it makes more sense to 
invest time in a community open source project.

Projects in wide use can still make sense to get involved in, but it makes more sense as a developer (economically) to get involved in community owned projects.

Permalink     1 Comment