Wednesday, October 23, 2013

Java Decompiling and Eclipse


Java Decompiling and Eclipse


One of the more frustrating issues are when you debug code in eclipse and want to debug a third party jar but do not have the source.


If the jar is open source and you are using maven you can try to use
mvn install –DdownloadSources=true.
This does not always work, since not all jar’s supply the source files.
In addition there are third part jar’s or sun jar’s that do not have source files. For this we have decompile utilities. The most famous one is jad (http://en.wikipedia.org/wiki/JAD_(JAva_Decompiler)).
So just go to your eclipse market and write jad. Once you have installed the plugin, next time you need to look at the code you will see:





Monday, October 14, 2013

Android – Israel Timezone


Android – Israel Timezone

For all those Israelis that have an android but have the wrong time/time zone since Israel keeps on changing the date of day light savings, this procedure is for you.

Download updated tzdata 


Android adb

Make sure you have the android adb (http://developer.android.com/sdk/index.html)

Connection to your device

To test your connection type in the dos prompt: adb devices.
You should get a list like

Copy the tzdata file to the same folder as the adb.

Run the following commands

adb root
adb remount
adb push tzdata /system/usr/share/zoneinfo/
adb shell chmod 644 /system/usr/share/zoneinfo/tzdata
adb reboot

You should now have the correct time and time zone.



Monday, October 7, 2013

Create a Java CLI application with Maven

Create a Java CLI application with Maven

Creating a CLI application is part of our daily routine. In java it is strait forward; all you need to do is to add a class with the main function:
public static void main(String[] args) {
}
This is nice for debugging from eclipse, but if you need to release this jar with the cli working, you will face the following issues:
1.       You need to add the main class to you manifest file and compile it in the jar.
2.       You need to create a folder with all the jar’s dependencies needed to run this cli.

Main Class

maven-jar-plugin

The first issue can be solved by using the maven-jar-plugin:
<plugin>
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-jar-plugin</artifactId>
       <configuration>
              <archive>
                     <manifest>
                           <addClasspath>true</addClasspath>
                           <mainClass>com.package.Main</mainClass>
                     </manifest>
              </archive>
              <finalName>jarname-cli</finalName>
       </configuration>
</plugin>

This plugin will create a jar file by the name of jarname-cli.jar, will a manifest file with the following entry:
Main-Class: com.package.Main
This will allow us to run from the command line:
java -jar jarname-cli %1 %2.

Jar Dependencies

Though if your jar has dependencies to other jars you will receive the following error when running the command line:
Exception in thread "main" java.lang.NoClassDefFoundError:
This is because we still need to package all the dependency jars into the same folder.
To solve this you need two more plugins.

maven-dependency-plugin (http://maven.apache.org/plugins/maven-dependency-plugin/)

The first plugin will calculate all the dependencies and copy them to a directory (cli):
<plugin>
       <artifactId>maven-dependency-plugin</artifactId>
       <executions>
              <execution>
                     <phase>install</phase>
                     <goals>
                           <goal>copy-dependencies</goal>
                     </goals>
                     <configuration>
       <outputDirectory>${project.build.directory}/../cli/</outputDirectory>
                     </configuration>
              </execution>
       </executions>
</plugin>

This plugin will copy all dependencies even though you don’t need all of them (it will include testing and jars not necessarily in use). You can start to manage you dependencies with the exclude, but this way you will constantly need to check that new jars are not added. The other option is to tell the plugin only the jars you want added:
                     <configuration>
                           <includeScope>runtime</includeScope>
                           <includeArtifactIds>commons-cli,spring-core,commons-logging,freemarker</includeArtifactIds>
                           <outputDirectory>${project.build.directory}/../cli/</outputDirectory>
                     </configuration>

This way any new dependencies will not be copied to the directory.
Of course if there are dependencies that you need for the execution of your cli, you will need to add them. You can use either the includeArtifactIds, or includeGroupIds whichever is easier.
This plugin is nice since it will get all the dependencies, but what it does not do is copy current jar to your cli directory. For this you need the ant plugin to copy the current jar

maven-antrun-plugin (http://maven.apache.org/plugins/maven-antrun-plugin/)

<plugin>
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-antrun-plugin</artifactId>
       <executions>
              <execution>
                     <id>Copy Main Jar To Cli Directory</id>
                     <phase>install</phase>
                     <configuration>
                           <tasks>
                                  <copy todir="${project.build.directory}/../cli/">
                                         <fileset dir="${project.build.directory}/" includes="*.jar"
                                                excludes="*sources*.jar,*javadoc*.jar" />
                                  </copy>
                           </tasks>
                     </configuration>
                     <goals>
                           <goal>run</goal>
                     </goals>
              </execution>
       </executions>
</plugin>

The action is very simple, it is a copy action from ant, that will copy the jar from the target directory.

maven-clean-plugin (http://maven.apache.org/plugins/maven-clean-plugin/)

Since your maven project will create the dir and all the jars needed, you need to add the clean plugin to remove the dir when running clean in maven.
<plugin>
       <artifactId>maven-clean-plugin</artifactId>
       <configuration>
              <filesets>
                     <fileset>
                           <directory>${project.build.directory}/../cli</directory>
                     </fileset>
              </filesets>
       </configuration>
</plugin>

This solution is good for most cases. But sometimes you need more flexibility. Occasionally you might want not to have a directory with all jar’s but you might want to pack them all in one jar (thought licensing must be considered). Also sometimes you might want to add more files or resources to the jar, or maybe create a zip file instead of the jar file. For this you have the assembly plugin. The dependency plugin is actually a subset of the assembly plugin, so you can do all the above and more.

maven-assembly-plugin (http://maven.apache.org/plugins/maven-assembly-plugin/)

We will not go into the whole plugin since you can do a lot with it (for a full set of options see http://maven.apache.org/plugins/maven-assembly-plugin/assembly.html).
                     <plugin>
                           <artifactId>maven-assembly-plugin</artifactId>
                           <configuration>
                                  <finalName>wsf_${version}</finalName>
                                  <appendAssemblyId>false</appendAssemblyId>
                                  <descriptors>
                                         <descriptor>src/main/resources/assembly.xml</descriptor>
                                  </descriptors>
                                  <outputDirectory>${project.build.directory}/../assembly/</outputDirectory>
                           </configuration>
                           <executions>
                                  <execution>
                                         <id>make-assembly</id>
                                         <!-- this is used for inheritance merges -->
                                         <phase>package</phase>
                                         <!-- bind to the packaging phase -->
                                         <goals>
                                                <goal>single</goal>
                                         </goals>
                                  </execution>
                           </executions>
                     </plugin>

As you can see we can do both creating a manifest file with the mainclass, and adding other files. You can enable enhanced features by assigning an assembly.xml and do for example:

<assembly>
        <id>bundle</id>
        <formats>
               <format>jar</format>
        </formats>
        <includeBaseDirectory>false</includeBaseDirectory>
        <dependencySets>
               <dependencySet>
                       <outputDirectory>/</outputDirectory>
                       <useProjectArtifact>true</useProjectArtifact>
                       <unpack>true</unpack>
                       <scope>runtime</scope>
                       <includes>
                               <include>*:commons-cli:*</include>
                               <include>*:spring-core:*</include>
                               <include>*:commons-logging:*</include>
                               <include>*:freemarker:*</include>
                       </includes>
               </dependencySet>
        </dependencySets>
</assembly>


Here you can notice that we used the option <unpack>true</unpack>. This will unpack all jar’s and then repack them all in one jar. This way you can bundle you cli into one jar only.