Wednesday, February 18, 2009

Maven Assemblies: Including Runtime Dependencies

I wanted to share a tip I picked up from Maven: The Definitive Guide
Previously, I thought you had to list every runtime dependency you wanted to include in a dependencySet:
   <dependencySets>
<dependencySet>
<includes>
<include>commons-dbcp:commons-dbcp</include>

</includes>
<outputDirectory>mule/lib/user</outputDirectory>
</dependencySet>
</dependencySets>
But all runtime dependencies can be brought into the assembly with an empty dependencySet element (runtime scope implicitly includes compile scope):
   <dependencySet/>
This will put all the runtime dependencies in the root of the assembled artifact, so you can add an outputDirectory:
   <dependencySet>
<outputDirectory>mule/lib/user</outputDirectory>
</dependencySet>
And in the case where you want to exclude something (such as mule-#.tar.gz or isoft-#.tar.gz) you can add exclusions:
   <dependencySet>
<outputDirectory>mule/lib/user</outputDirectory>
<excludes>
<exclude>*:tar.gz</exclude>
</excludes>
</dependencySet>
Doing things this way puts a heavier burden on properly managing your dependencies however (which really is a good thing). If transitive dependencies you may not need are not excluded in the POM’s dependency declaration or the parent’s dependencyManagement, the transitive dependencies will end up in your artifact, leading to potential collisions and jar bloat. An example of an exclusion:
    <dependency>
<groupId>toplink.essentials</groupId>
<artifactId>toplink-essentials</artifactId>
<scope>runtime</scope>
<excludes>
<exclude>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
</exclude>
</excludes>
</dependency>
You can run each of the following to help with your dependency manangement:
mvn dependency:analyze
mvn dependency:resolve
mvn dependency:tree

Friday, February 13, 2009

Spring ref vs. bean: no ID/IDREF binding for IDREF

hen upgrading a project from Mule 1.x to Mule 2.x, I ran into the following error while converting my Mule configuration file:
A Fatal error has occurred while the server was running:
cvc-id.1: There is no ID/IDREF binding for IDREF 'someProxy'.
(org.xml.sax.SAXParseException)
The offending bean:
   <spring:bean id="myImplementationBean" class="org.my.class" scope="prototype">
<spring:property name="myInterface">
<spring:ref local="myProxy"/>
</spring:property>
</spring:bean>
The problem was using local instead of bean as the value of the spring:property:
   <spring:bean id="myImplementationBean" class="org.my.class" scope="prototype">
<spring:property name="myInterface">
<spring:ref bean="myProxy"/>
</spring:property>
</spring:bean>
For a discussion the difference, see Spring-ref-local-vs-ref.

Determining which Process is Using a Port

This post is more of a reminder to myself than anything. To determine which process is using a port with fuser in Linux run:
fuser -n tcp port
Alternatively, you can use netstat:
netstat -nlp | grep port

Wednesday, February 11, 2009

JPA: Attempted to deploy PersistenceUnit while being in the wrong state

For a while I would see the following exception at random times in logs while using JPA in Spring.:

org.springframework.transaction.CannotCreateTransactionException:
Could not open JPA EntityManager for transaction;
nested exception is javax.persistence.PersistenceException:
Exception [TOPLINK-28013] (Oracle TopLink Essentials - 2.1 (Build 60 (11/17/2008))):
oracle.toplink.essentials.exceptions.EntityManagerSetupException
Exception Description: Attempted to deploy PersistenceUnit [harborPU]
while being in the wrong state [Undeployed].
Close all factories for this PersistenceUnit.
Turns out the
PersistenceUnit would be left in the wrong state if the EntityManagerFactory in the JpaTemplate has not been closed. I assumed Spring would take care of this for me, but the behaviour wasn't consistent. In my DAO, I tried adding an explicit call to getJpaTemplate().getEntityManagerFactory().close(). Of course that didn't work because the method where I put the call was within the transaction, leading to:
org.springframework.dao.InvalidDataAccessApiUsageException: 
Attempting to execute an operation on a closed EntityManager.;
nested exception is java.lang.IllegalStateException:
Attempting to execute an operation on a closed EntityManager.
Therefore, I had to call the method from within the class using the DAO that made the call to the method involved in the transaction.

I wonder if this has something to do with my transaction setup:

<bean id="entityManagerFactory" 
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.TopLinkJpaVendorAdapter">
<property name="database" value="MYSQL"/>
<property name="showSql" value="true" />
<!-- set to true if you want the vendor to create the database for you on startup -->
<property name="generateDdl" value="false" />
</bean>
</property>
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
</property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
<property name="dataSource" ref="dataSource"/>
</bean>

<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="get*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>

<aop:config>
<!-- interface to my DAO
<aop:advisor pointcut="execution(* *..MyDaoService.*(..))" advice-ref="txAdvice"/>
</aop:config>
If you have any insight, please leave a comment :).

Monday, February 2, 2009

Mounting a Windows share on Linux

I created a share on Windows desktop at work and wanted to access it from my Ubuntu 8.10 virtual machine served up by VMWare Server but ran into a roadblock:
$ sudo mount -t smbfs -o username=myWindowsLogin,password=myWindowsPassword,uid=prystasj,gid=prystasj,file_mode=000,dir_mode=000 //myWindowsBox/share /share
mount: wrong fs type, bad option, bad superblock on //prystash-j.mycompany.org/share,
missing codepage or helper program, or other error
(for several filesystems (e.g. nfs, cifs) you might
need a /sbin/mount. helper program)
In some cases useful info is found in syslog - try
dmesg | tail or so

$ dmesg | tail
...
[19838.333431] smb_fill_super: missing data argument
...
The answer was to install smbfs.
$ sudo apt-get install smbfs
$ sudo mount -t smbfs -o username=myWindowsLogin,password=myWindowsPassword,uid=prystasj,gid=prystasj,file_mode=000,dir_mode=000 //myWindowsBox/share /share
Unfortunately, as myself or root, I'm not able to write anything to /share from my Linux host, but I can read just fine.
$ sudo ls -ld /share
d--------- 1 prystasj prystasj 0 2009-02-02 15:41 /share
Will have to investigate more later.

Sunday, February 1, 2009

Remote Debugging Mule 2.x on Linux

I was having trouble getting my Mule 2.1.1 instance start in debugging mode, until I found this blog entry: Mule Error: Remote Debugging a Mule Server6. The start of my resulting wrapper.conf, with the normal debug line having been broken out into 4:
# Location of your Mule installation.
wrapper.java.additional.1=-Dmule.home="%MULE_HOME%"
wrapper.java.additional.1.stripquotes=TRUE
wrapper.java.additional.2=-Dmule.base="%MULE_BASE%"
wrapper.java.additional.2.stripquotes=TRUE

# Javaagent for certain load time weavers
wrapper.java.additional.3=-javaagent:/opt/mule-2.1.1/lib/user/spring-agent-2.5.3.jar

# Debug remotely, the application will wait for the external debugger to connect.
# original line:
# wrapper.java.additional.4=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005
wrapper.java.additional.4=-Xdebug
wrapper.java.additional.5=-Xnoagent
wrapper.java.additional.6=-Djava.compiler=NONE
wrapper.java.additional.7=-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005
Then I finally got what I was looking for in my mule.log and was able to attach to port 5005 in Eclipse:
--> Wrapper Started as Daemon
------------------------------------------------------------------------
The JVM is being launched with a debugger enabled and could possibly be
suspended. To avoid unwanted shutdowns, timeouts will be disabled,
removing the ability to detect and restart frozen JVMs.
------------------------------------------------------------------------
Launching a JVM...
Listening for transport dt_socket at address: 5005
Starting the Mule Server...
Wrapper (Version 3.2.3) http://wrapper.tanukisoftware.org
Copyright 1999-2006 Tanuki Software, Inc. All Rights Reserved.

I've tried this on both Ubuntu 8.10 and Linux Mint 6 with Mule 2.1.1.