Archive

Archive for the ‘Java’ Category

Maven snippet – add generated sources to the build

July 21, 2014 Leave a comment

Here’s a maven snippet I found myself looking for many times – adding generated sources to the build.
This tells Maven to include the generated classes as part of the compilation, which ensures any non generated code that depends on them compiles fine, and their corresponding .class files be included in the .jar/.war file.

  ...
  <build>
    <plugins>
      ...
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>build-helper-maven-plugin</artifactId>
        <executions>
          <execution>
            <id>add-source</id>
            <phase>generate-sources</phase>
            <goals>
              <goal>add-source</goal>
            </goals>
            <configuration>
              <sources>
                <source>${project.build.directory}/generated</source>
              </sources>
            </configuration>
          </execution>
        </executions>
      </plugin>
    ...
    </plugins>
  </build>
  ...

In this case (line #153) – we assume that the sources are generated to target/generated.

Some useful reading material regarding this subject:

Advertisements

Demeter is running

August 19, 2013 Leave a comment

I think that one of the widely ignored laws in in object oriented programming is the Law of Demeter (LoD).

Take the following real life scenario:

John needs $5. John goes to Jack, pulls out his wallet an opens it – and takes $5, than puts the wallet back in its palace.

Sounds bad – right? Now see it as a piece of code and think if you ever saw something like this in your source code:

public class Wallet
{
     private int amount;

     public Wallet(int amount)
     {
          this.amount = amount;
     }

     public int deposit(int sum)
     { 
         if (sum < 0) throw new IllegalArgumentException("sum must be non-negative");
         amount += sum;
         return amount;
     }
     public int withdraw(int sum)
     { 
         if (sum < 0) throw new IllegalArgumentException("sum must be non-negative");
         if (sum > amount) throw new InsufficiantFundsException("Insufficiant Funds!");
         amount -= sum;
         return amount;
     }
}

public class Person
{
     private string name;
     private Wallet wallet;

     public Person(String name, int moneyInWallet)
     {
          this.name = name;
          this.wallet = new Wallet(moneyInWallet);
     }

     public boolean requestLoanFrom(Person otherPerson, int amount)
     {
          int moneyFromOtherPerson = otherPerson.getWallet().withdraw(amount);
          this.wallet.deposit(moneyFromOtherPerson);          
          
          return true;
     }
}

public class Main
{
     public static void main(String [] args)
     {
          Person john = new Person("John", 10);
          Person jack = new Person("jack", 10);

          jack.requestLoanFrom(john,5);          
     }
}

The LoD relates to the fact that Jack knows John’s wallet – which it should not.

Now consider this implementation:

public class Person
{
     ...

     public boolean requestLoanFrom(Person otherPerson, int amount)
     {
          if (otherPerson.handleLoanRequest(amount))
          {
              this.wallet.deposit(amount);          
              return true;
          }
          else
          {return false;}                  
     }

     protected boolean handleLoanRequest(int amount)
     {
          // Do some validation ...
          wallet.withdraw(amount);     
          return true;
     }
}

Notice that each person is responsible for their own wallet – as it is in real life*.
*Note: I’m well aware this code is bad from the transaction POV – it is just to clarify the point.

To simplify things, the LoD states that this line of code is bad:

x = a.getSome().getThing();

It basically states that your code should be like:

public class A
{
   private Some some;

   public Thing getSomeThing()
   {
       this.some.getThing();
   }
}

public class Main
{
   public static void main(String ... args)
   {
      x = a.getSomeThing();
   }
}

I believe LoD is a useful guideline when developing Object Oriented software, but becoming too strict with it has a price.
In my experience – when you find it very hard to adhere to the LoD – you should review your design as you might be tight-coupling your system.

ArrayIndexOutOfBoundsException when creating a connection to an Oracle database

May 27, 2013 Leave a comment

More than once I encountered a java.lang.ArrayIndexOutOfBoundsException when creating a connection to an Oracle database using the SID of the database instead of the HOST:PORT:INSTANCE combination.

The stacktrace for this error usually looks like this:

java.lang.ArrayIndexOutOfBoundsException: <some number>
        at oracle.net.nl.NVTokens.parseTokens(Unknown Source)
        at oracle.net.nl.NVFactory.createNVPair(Unknown Source)
        at oracle.net.nl.NLParamParser.addNLPListElement(Unknown Source)
        at oracle.net.nl.NLParamParser.initializeNlpa(Unknown Source)
        at oracle.net.nl.NLParamParser.<init>(Unknown Source)
        at oracle.net.resolver.TNSNamesNamingAdapter.loadFile(Unknown Source)
        at oracle.net.resolver.TNSNamesNamingAdapter.checkAndReload(Unknown Source)
        at oracle.net.resolver.TNSNamesNamingAdapter.resolve(Unknown Source)
        at oracle.net.resolver.NameResolver.resolveName(Unknown Source)
        at oracle.net.resolver.AddrResolution.resolveAndExecute(Unknown Source)
        at oracle.net.ns.NSProtocol.establishConnection(Unknown Source)
        at oracle.net.ns.NSProtocol.connect(Unknown Source)
        at oracle.jdbc.driver.T4CConnection.connect(T4CConnection.java:1037)
        at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:282)
        at oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:468)
        at oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.java:165)
        at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:35)
        at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:839)
        at java.sql.DriverManager.getConnection(DriverManager.java:582)
        at java.sql.DriverManager.getConnection(DriverManager.java:185)

It appears that Oracle’s java client has a bug – this exception occurs if the tnsnames.ora file has misplaced spaces/tabs/new-lines in particular places.

Oracle’s documentation states that the structure of a record in the tnsnames.ora file should be as such:

net_service_name= 
 (DESCRIPTION=
   (ADDRESS=...)
   (ADDRESS=...)
   (CONNECT_DATA=
    (SERVICE_NAME=sales.us.example.com)))

Definition such as the one below are illegal:

net_service_name= 
 (DESCRIPTION=
   (ADDRESS=...)
(ADDRESS=...)
   (CONNECT_DATA=
(SERVICE_NAME=sales.us.example.com)))

Apparently the indentation is crucial – if any of the lines in the block of a single net_service_name start at index 1 – this exception is thrown.
Only once you add indentation to all (can be spaces or tab) – it works. It doesn’t have to look good, but has to have an offset of some sort.

Important note – the only problem is with ‘(‘, indentation rules don’t apply to ‘)’.
E.g. the below example is perfectly fine:

net_service_name= 
     (DESCRIPTION=
       (ADDRESS=...
)
       (ADDRESS=...
)
       (CONNECT_DATA=
        (SERVICE_NAME=sales.us.example.com))
)

And here is the important excerpt from Oracle’s documentation:

Even if you do not choose to indent your files in this way, you must indent a wrapped line by at least one space, or it will be misread as a new parameter
The following layout is acceptable:

(ADDRESS=(COMMUNITY=tcpcom.world)(PROTOCOL=tcp)
   (HOST=max.world)(PORT=1521))

The following layout is not acceptable:

(ADDRESS=(COMMUNITY=tcpcom.world)(PROTOCOL=tcp)
(HOST=max.world)(PORT=1521))

Quick decompile of Java code

April 29, 2013 2 comments

If you need to quickly decompile a java .class file and you only have access to a machine with the JDK installed on it (like production servers) – you can use a tool which is built-in with the JDK.

It is called javap and it can disassemble any .class file. All you need to do is run it from the directory where all of your the .class files exist (the “root”).
It will also work if the class can be found within the CLASSPATH (i.e. the environment variable CLASSPATH) and it can be given a specific classpath via a CLI argument. It can also find the .class file within a JAR.

javap <FQCN> Usage Gets the list of all the public members (variables + methods).
Only gives you method declerations.
Example javap java.lang.String
javap -private <FQCN> Usage Gets the list of all the members (variables + methods).
Only gives you method declerations.
Example javap -private java.lang.String
javap -c <FQCN> Usage Same as javap <FQCN>, but also disassembles the method body.
This does not “decompile” – but you can understand what will happen in simple methods.
Example javap -c java.lang.String
javap -c -private <FQCN> Usage Same as above but does it for all private members as well.
Example javap -c -private java.lang.String

FQCN: Fully Qualified Class Name.

How does it look? Take for example this piece of code:

package com.ron;

import java.lang.*;

public class JavapSample
{
        private String someMember;

        public JavapSample(int someArgument)
        {
                someMember = String.valueOf(someArgument);
        }

        public void doSomething()
        {
                System.out.println(someMember);
        }

        private void doSomethingSecret()
        {
                System.out.println("Secret ...");
        }
}

Here is the output:

public class com.ron.JavapSample extends java.lang.Object{
    public com.ron.JavapSample(int);
    public void doSomething();
}
public class com.ron.JavapSample extends java.lang.Object{
    private java.lang.String someMember;
    public com.ron.JavapSample(int);
    public void doSomething();
    private void doSomethingSecret();
}
public class com.ron.JavapSample extends java.lang.Object{
private java.lang.String someMember;

public com.ron.JavapSample(int);
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   aload_0
   5:   iload_1
   6:   invokestatic    #2; //Method java/lang/String.valueOf:(I)Ljava/lang/String;
   9:   putfield        #3; //Field someMember:Ljava/lang/String;
   12:  return

public void doSomething();
  Code:
   0:   getstatic       #4; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   aload_0
   4:   getfield        #3; //Field someMember:Ljava/lang/String;
   7:   invokevirtual   #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   10:  return

private void doSomethingSecret();
  Code:
   0:   getstatic       #4; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   ldc     #6; //String Secret ...
   5:   invokevirtual   #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   8:   return
}

Where/When to use it – I use it when I need to ensure a certain fix is available within a JAR on a QA/Prod environment. It is not intrusive – and it is rather easy to understand if the fix is there or not.

Note for Java7 users: In java 7 it looks like javap can receive a .class file as an argument instead of the FQCN.

Categories: Java, Tools Tags: , ,

Where did that Class come from?

April 21, 2013 Leave a comment

Too many times I watched the logs trying to understand why I got the NoSuchMethodError. I sometimes get it with other derivatives of IncompatibleClassChangeError (AbstractMethodError, IllegalAccessError, InstantiationError, NoSuchFieldError) but NoSuchMethodError is the most common one.

The reason for this error is simple – the class you want to use is not the one being loaded at run time. This can be another version of the third party that finds its way to the classpath, or some old copy of your class. The problem is usually pin-pointing where it got from.

For that I have a simple solution – which unfortunately requires some code modification.
All you need to do is add these lines to your code (modify slightly) and you will get the result:

String className = classYouWantToFind.getName();
String classFileRelativePath = className.replace('.', '/') +  ".class";
java.net.URL classFileUrl = this.getClass().getClassLoader().getResource(classFileRelativePath);
System.out.println(className + " comes from [" + classFileUrl.toString() + "]");

This code asks the ClassLoader of the currently running object to find the .class representing the class you are looking for. Since the class loader searches for resources in the same order as it does for classes – it should find the correct one.

You can see a live example of this code on IDE One.

Note: You can always get this result by adding the -verbose:class VM argument – but this will get you verbose output of every class in the system.

Categories: Internals, Java Tags: ,

Testing a large variance of inputs using Parameterized JUnit tests

April 17, 2013 4 comments

Often in utility methods (e.g. your usual StringUtils) you find yourself writing the same test over and over again with different inputs.
You can do something like this:

public class TestSomeUtils
{
      @Test
      public void test_function1_input_1()
      {
            test_function1("some-output",  7, 2.6);
      }

      @Test
      public void test_function1_input_2()
      {
            test_function1("another-output",  9, -1.56);
      }

      @Test
      public void test_function1_input_3()
      {
            test_function1("no-output",  0, 768.2341);
      }

      private void test_function1(String expectedOutput, int inputA, double inputB)
      {
            String actualOutput = SomeUtils.function1(inputA, inputB);
            assertEquals(expectedOutput, actualOutput);
      }
}

However – JUnit has a much better way of doing it – org.junit.runners.Parameterized

@RunWith(Parameterized.class)
public class TestSomeUtils
{
      private String expectedOutput;
      private int inputA;
      private double inputB;

      @Parameters
      public static Collection<Object[]> prepareData()
      {
            Collection<Object[]> args = new ArrayList<Object[]>();

            args.add(new Object[]{"some-output",  7, 2.6});
            args.add(new Object[]{"another-output",  9, -1.56});
            args.add(new Object[]{"no-output",  0, 768.2341});

            return args;        
      }

      public TestSomeUtils(String expectedOutput, int inputA, double inputB)
      {
            this.expectedOutput = expectedOutput;
            this.inputA = inputA;
            this.inputB = inputB;
      }

      @Test
      public void testSomething()
      {
            String actualOutput = SomeUtils.function1(inputA, inputB);
            assertEquals(expectedOutput, actualOutput);
      }
}

Explenation:

@RunWith(Parameterized.class) tells the JUnit framework use a non-default test runner, in which case it is the Parameterized runner.
This runner will execute all the tests on all the given inputs. So if you have 3 test methods and nine sets of inputs – you actually get 27 distinct tests.

How does it do it?

  1. It calls the prepareData method since it is annotated with @Parameters.
  2. For each Object[] in the Collection it will instantiate the test class using the Object[] as constructor arguments (Using Reflection).
  3. It will execute all the test methods in the test class

Simple, isn’t it?

I use it mostly for simple utility methods that I want to cover from end to end, but I have also used it to execute other tests as well.

Jar scanning utility – find a class within all jars (Unix/Linux)

March 28, 2013 Leave a comment

Every so often I need to figure out which jar(s) contain a certain class so I can figure out why an application acts the way it does – either since a class is missing in some environment or since the wrong class was loaded into the classpath.

When that happens, I use the following script. I saw it once in a company I worked at, and then again in another company.
I modified it slightly, but the credits do not go to me, they go to the anonymous person who wrote the initial code.

The script is available for download on GitHub.

Or you can simply copy it from here:

#!/bin/tcsh -f

if ( $#argv < 2 ) then
        printf "Scans all the JARs in the specified directory for classes matching the specified string\n"
        printf "Usage: $0 <dir> <class-name-pattern>\n"
        printf "Example: $0 . Exception\n"
        printf 'Example: '$0' $JAVA_HOME/lib "com\/sun\/.*action"\n'
        exit 1
endif

set DIR = "$1"
set CLASS = "$2"

foreach J ( `find $DIR -name "*.jar"` )
        printf "."
        set res=`jar tvf $J | grep "$CLASS" | sed 's/$/;/'`
        set outputsize = `echo $res|wc -c`
        if ( $outputsize > 1 )  then
                printf "\nMatch found in [$J]\n"
                printf  "$res\n" | tr ';' '\n'
        endif
end

printf "\n"
Categories: Java, Shell Scripting, Tools, UNIX Tags: , , , ,
%d bloggers like this: