Tuesday, November 27, 2012

Assigning a string to shell variable with successive spaces

My friend Sumeeth called me saying that he is trying to assign a string with successive spaces to a shell variable, but the spaces are getting removed.

Linux environment, using bash shell

export test="Hello   World"

echo $test

Hello World <----------extra spaces in middle are removed.  This is because of IFS.  By default it will be set to <space><tab><newline>

So one way of doing this is to change IFS, do the assignment and put the IFS back.

export old_IFS=$IFS
export IFS="\n\t"
export test="Hello   World"
echo $test
Hello   World  <------spaces are retained

Thursday, November 8, 2012

Starting/Stopping hsqldb with maven

Starting hsqldb through maven with exec-maven-plugin is straight forward except for the confusion around arguments support.  Here is version with issue:

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>exec-maven-plugin</artifactId>
  <version>1.2.1</version>
  <executions>
    <execution>
      <goals>
        <goal>java</goal>
      </goals>
    </execution>
  </executions>
  <configuration>
    <mainClass>org.hsqldb.server.Server</mainClass>
    <arguments>
      <argument>--database.0 file:target/data/tutorial</argument>
    </arguments>
  </configuration>
</plugin>

Issue is with the highlighted line.  The value supplied with argument is passed as a whole single string.  What this means is in your java program argument count would be 1.  To start hsqldb we need to send the key and value for db location as seperate arguments.  We could use either args or nest argument as below:

<configuration>
  <mainClass>org.hsqldb.server.Server</mainClass>
  <args>--database.0 file:target/data/tutorial</args>
</configuration>

<configuration>
  <mainClass>org.hsqldb.server.Server</mainClass>
    <arguments>
      <argument>--database.0</argument>
      <argument>file:target/data/tutorial</argument>
    </arguments>

</configuration>

Now that we started the server, how to stop it?
<configuration>
  <mainClass>org.hsqldb.util.DatabaseManager</mainClass>
  <arguments>
    <argument>-driver</argument>
    <argument>org.hsqldb.jdbcDriver</argument>
    <argument>-url</argument>
    <argument>jdbc:hsqldb:file:test</argument>
    <argument>-user</argument>
    <argument>sa</argument>
  </arguments>
</configuration>

Connect using the UI  manager that comes along hsqldb and execute SHUTDOWN as query.

Friday, November 2, 2012

Ant related tasks in Maven

After using Maven dependency from within Ant, this time I had to find a way to call ant task from with Maven.  While trying to do a simple test around JMSMessageID behaviour (read about it on my java blog) with JBoss, I needed to include jbossall-client.jar on the classpath.  Here are couple of ways of doing this and their related issues.

Approach#1
Include jbossall-client as a dependency from JBoss public repository. Co-ordinates are org.jboss.jbossas:jboss-as-client, but this results in Maven downloading huge number of artifacts that are not requried. We would need to selectively include the required or exclude the unnecessary artifacts, which is not an easy job given the huge number.  See here and here for some help on this approach.

Approach#2
I tried adding a dependency with scope as system, providing the absolute path to the jbossall-client.jar.  Using system scope has its own issues, most critical being the dependency not being included on the classpath.  After going through lot of answers on stackoverflow zeroed on two approaches again - creating a local repository or using dependency and jar plugins.  But the problem is jbossall-client.jar

In JBoss 4.0, jbossall-client.jar used to include all the required jars/classes for a standalone client, which is changed since JBoss 5. Now the jar is sleek and refers all the jars through manifest. Issue with this is the jars won't be available if we jbossall-client.jar to some other location as the paths in the manifest are relative.

At this point I gave up and started running my Test directly from cmd by including the jbossall-client.jar in the classpath.  Then I came across two Maven plugins maven-ant-plugin and maven-antrun-plugin.  The former generates build scripts out of pom and the later can run any ant target from within pom.  The antrun plugin is what I tried as I felt the effort to setup maven local repository just to run my test program did not seem worth.  Here is what I came up with:



      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-antrun-plugin</artifactId>
        <version>1.7</version>
        <executions>
          <execution>
            <phase>test</phase>
            <goals>
              <goal>run</goal>
            </goals>
            <configuration>
              <target>
                <property name="runtime_classpath" refid="maven.runtime.classpath" />
                <java classname="com.sample.Tester">
                  <classpath>
                    <pathelement path="${runtime_classpath}" />
                  </classpath>
                    <pathelement location="JBOSS_HOME/client/jbossall-client.jar" />
                </java>
              </target>
            </configuration>
          </execution>
        </executions>
      </plugin>




Note that jbossall-client.jar is included later on the classpath otherwise it will try to bootstrap log4j (slf4j is part of jbossall-client.jar)


Please share if you done this differently.