Hiển thị các bài đăng có nhãn Java (General). Hiển thị tất cả bài đăng
Hiển thị các bài đăng có nhãn Java (General). Hiển thị tất cả bài đăng

Thứ Ba, 15 tháng 4, 2014

Programmatic Access to Sizes of Java Primitive Types

One of the first things many developers new to Java learn about is Java's basic primitive data types, their fixed (platform independent) sizes (measured in bits or bytes in terms of two's complement), and their ranges (all numeric types in Java are signed). There are many good online resources that list these characteristics and some of these resources are the Java Tutorial lesson on Primitive Data Types, The Eight Data Types of Java, Java's Primitive Data Types, and Java Basic Data Types.

Java allows one to programmatically access these characteristics of the basic Java primitive data types. Most of the primitive data types' maximum values and minimum values have been available for some time in Java via the corresponding reference types' MAX_VALUE and MIN_VALUE fields. J2SE 5 introduced a SIZE field for most of the types that provides each type's size in bits (two's complement). JDK 8 has now provided most of these classes with a new field called BYTES that presents the type's size in bytes (two's complement).

DataTypeSizes.java

package dustin.examples.jdk8;

import static java.lang.System.out;
import java.lang.reflect.Field;

/**
* Demonstrate JDK 8's easy programmatic access to size of basic Java datatypes.
*
* @author Dustin
*/
public class DataTypeSizes
{
/**
* Print values of certain fields (assumed to be constant) for provided class.
* The fields that are printed are SIZE, BYTES, MIN_VALUE, and MAX_VALUE.
*
* @param clazz Class which may have static fields SIZE, BYTES, MIN_VALUE,
* and/or MAX_VALUE whose values will be written to standard output.
*/
private static void printDataTypeDetails(final Class clazz)
{
out.println("\nDatatype (Class): " + clazz.getCanonicalName() + ":");
final Field[] fields = clazz.getDeclaredFields();
for (final Field field : fields)
{
final String fieldName = field.getName();
try
{
switch (fieldName)
{
case "SIZE" : // generally introduced with 1.5 (twos complement)
out.println("\tSize (in bits): " + field.get(null));
break;
case "BYTES" : // generally introduced with 1.8 (twos complement)
out.println("\tSize (in bytes): " + field.get(null));
break;
case "MIN_VALUE" :
out.println("\tMinimum Value: " + field.get(null));
break;
case "MAX_VALUE" :
out.println("\tMaximum Value: " + field.get(null));
break;
default :
break;
}
}
catch (IllegalAccessException illegalAccess)
{
out.println("ERROR: Unable to reflect on field " + fieldName);
}
}
}

/**
* Demonstrate JDK 8's ability to easily programmatically access the size of
* basic Java data types.
*
* @param arguments Command-line arguments: none expected.
*/
public static void main(final String[] arguments)
{
printDataTypeDetails(Byte.class);
printDataTypeDetails(Short.class);
printDataTypeDetails(Integer.class);
printDataTypeDetails(Long.class);
printDataTypeDetails(Float.class);
printDataTypeDetails(Double.class);
printDataTypeDetails(Character.class);
printDataTypeDetails(Boolean.class);
}
}

When executed, the code above writes the following results to standard output.

The Output


Datatype (Class): java.lang.Byte:
Minimum Value: -128
Maximum Value: 127
Size (in bits): 8
Size (in bytes): 1

Datatype (Class): java.lang.Short:
Minimum Value: -32768
Maximum Value: 32767
Size (in bits): 16
Size (in bytes): 2

Datatype (Class): java.lang.Integer:
Minimum Value: -2147483648
Maximum Value: 2147483647
Size (in bits): 32
Size (in bytes): 4

Datatype (Class): java.lang.Long:
Minimum Value: -9223372036854775808
Maximum Value: 9223372036854775807
Size (in bits): 64
Size (in bytes): 8

Datatype (Class): java.lang.Float:
Maximum Value: 3.4028235E38
Minimum Value: 1.4E-45
Size (in bits): 32
Size (in bytes): 4

Datatype (Class): java.lang.Double:
Maximum Value: 1.7976931348623157E308
Minimum Value: 4.9E-324
Size (in bits): 64
Size (in bytes): 8

Datatype (Class): java.lang.Character:
Minimum Value:

UPDATE: Note that, as Attila-Mihaly Balazs has pointed out in the comment below, the MIN_VALUE values showed for java.lang.Float and java.lang.Double above are not negative numbers even though these constant values are negative for Byte, Short, Int, and Long. For the floating-point types of Float and Double, the MIN_VALUE constant represents the minimum absolute value that can stored in those types.

Although the characteristics of the Java primitive data types are readily available online, it's nice to be able to programmatically access those details easily when so desired. I like to think about the types' sizes in terms of bytes and JDK 8 now provides the ability to see those sizes directly measured in bytes.

Thứ Ba, 1 tháng 4, 2014

Compiling and Running Java Without an IDE

A recent Java subreddit thread called "Compiling Java Packages without IDE" posed the question, "is [there] a command that compiles a group of java files that are inside a package into a separate folder (let's just call it bin), and how would I go about running the new class files?" The post's author, kylolink, explains that "When I started out using Java I relied on Eclipse to do all the compiling for me and just worried about writing code." I have seen this issue many times and, in fact, it's what prompted my (now 4 years old) blog post GPS Systems and IDEs: Helpful or Harmful? I love the powerful modern Java IDEs and they make my life easier on a daily basis, but there are advantages to knowing how to build and run simple Java examples without them. This post focuses on how to do just that.

In my blog post Learning Java via Simple Tests, I wrote about how I sometimes like to use a simple text editor and command-line tools to write, build, and run simple applications. I have a pretty good idea now how my much "overhead" my favorite Java IDEs require and make an early decision whether the benefits achieved from using the IDE are sufficient to warrant the "overhead." In most real applications, there's no question the IDE "overhead" is well worth it. However, for the simplest of example applications, this is not always the case. The rest of this post shows how to build and run Java code without an IDE for these situations.

The Java Code to be Built and Executed

To make this post's discussion more concrete, I will use some very simple Java classes that are related to each other via composition or inheritance and are in the same named package (not in the unnamed package) called dustin.examples. Two of the classes do not have main functions and the third class, Main.java does have a main function to allow demonstration of running the class without an IDE. The code listings for the three classes are shown next.

Parent.java

package dustin.examples;

public class Parent
{
@Override
public String toString()
{
return "I'm the Parent.";
}
}
Child.java

package dustin.examples;

public class Child extends Parent
{
@Override
public String toString()
{
return "I'm the Child.";
}
}
Main.java

package dustin.examples;

import static java.lang.System.out;

public class Main
{
private final Parent parent = new Parent();
private final Child child = new Child();

public static void main(final String[] arguments)
{
final Main instance = new Main();
out.println(instance.parent);
out.println(instance.child);
}
}

The next screen snapshot shows the directory structure with these class .java source files in place. The screen snapshot shows that the source files are in a directory hierarchy representing the package name (dustin/examples because of package dustin.examples) and that this package-reflecting directory hierarchy is under a subdirectory called src. I have also created classes subdirectory (which is currently empty) to place the compiled .class files because javac will not create that directory when it doesn't exist.

Building with javac and Running with java

No matter which approach one uses to build Java code (Ant, Maven, Gradle, or IDE) normally, I believe it is prudent to at least understand how to build Java code with javac. The Oracle/Sun-provided javac command-line tool's standard options can be seen by running javac -help and additional extension options can be viewed by running javac -help -X. More details on how to apply these options can be found in the tools documentation for javac for Windows or Unix/Linux.

As the javac documentation states, the -sourcepath option can be use to express the directory in which the source files exist. In my directory structure shown in the screen snapshot above, this would mean that, assuming I'm running the javac command from the C:\java\examples\javacAndJava\ directory, I'd need to have something like this in my command: javac -sourcepath src src\dustin\examples\*.java. The next screen snapshot shows the results of this.

Because we did not specify a destination directory for the .class files, they were placed by default in the same directory as the source .java files from which they were compiled. We can use the -d option to rectify this situation. Our command could be run now, for example, as javac -sourcepath src -d classes src\dustin\examples\*.java. As stated earlier, the specified destination directory (classes) must already exist. When it does, the command will place the .class files in the designated directory as shown in the next screen snapshot.

With the Java source files compiled into the appropriate .class files in the specified directory, we can now run the application using the Java application launcher command line tool java. This is simply done by following the instructions shown by java -help or by the java tools page and specifying the location of the .class files with the -classpath (or -cp) option. Using both approaches to specify that the classes directory is where to look for the .class files is demonstrated in the next screen snapshot. The last argument is the fully qualified (entire Java package) name of the class who has a main function to be executed. The commands demonstrated in the next screen snapshot is java -cp classes dustin.examples.Main and java -classpath classes dustin.examples.Main.

Building and Running with Ant

For the simplest Java applications, it is pretty straightforward to use javac and java to build and execute the application respectively as just demonstrated. As the applications get a bit more involved (such as code existing in more than one package/directory or more complex classpath dependencies on third-party libraries and frameworks), this approach can become unwieldy. Apache Ant is the oldest of the "big three" of Java build tools and has been used in thousands of applications and deployments. As I discussed in a previous blog post, a very basic Ant build file is easy to create, especially if one starts with a template like I outlined in that post.

The next code listing is for an Ant build.xml file that can be use to compile the .java files into .class files and then run the dustin.examples.Main class just like was done above with javac and java.

build.xml

<?xml version="1.0" encoding="UTF-8"?>
<project name="BuildingSansIDE" default="run" basedir=".">
<description>Building Simple Java Applications Without An IDE</description>

<target name="compile"
description="Compile the Java code.">
<javac srcdir="src"
destdir="classes"
debug="true"
includeantruntime="false" />
</target>

<target name="run" depends="compile"
description="Run the Java application.">
<java classname="dustin.examples.Main" fork="true">
<classpath>
<pathelement path="classes"/>
</classpath>
</java>
</target>
</project>

I have not used Ant properties and not included common targets I typically include (such as "clean" and "javadoc") to keep this example as simple as possible and to keep it close to the previous example using javac and java. Note also that I've included "debug" set to "true" for the javac Ant task because it's not true in Ant's default but is true with javac's default. Not surprisingly, Ant's javac task and java task closely resemble the command tools javac and java.

Because I used the default name Ant expects for a build file when it's not explicitly specified (build.xml) and because I provided the "run" target as the "default" for that build file and because I included "compile" as a dependency to run the "run" target and because Ant was on my environment's path, all I need to do on the command line to get Ant to compile and run the example is type "ant" in the directory with the build.xml file. This is demonstrated in the next screen snapshot.

Although I demonstrated compiling AND running the simple Java application with Ant, I typically only compile with Ant and run with java (or a script that invokes java if the classpath is heinous).

Building and Running with Maven

Although Ant was the first mainstream Java build tool, Apache Maven eventually gained its own prominence thanks in large part to its adoption of configuration by convention and support for common repositories of libraries. Maven is easiest to use when the code and generated objects conform to its standard directory layout. Unfortunately, my example doesn't follow this directory structure, but Maven does allow us to override the expected default directory structure. The next code listing is for a Maven POM file that overrides the source and target directories and provides other minimally required elements for a Maven build using Maven 3.2.1.

pom.xml

<project>
<modelVersion>4.0.0</modelVersion>
<groupId>dustin.examples</groupId>
<artifactId>CompilingAndRunningWithoutIDE</artifactId>
<version>1</version>

<build>
<defaultGoal>compile</defaultGoal>
<sourceDirectory>src</sourceDirectory>
<outputDirectory>classes</outputDirectory>
<finalName>${project.artifactId}-${project.version}</finalName>
</build>
</project>

Because the above pom.xml file specifies a "defaultGoal" of "compile" and because pom.xml is the default custom POM file that the Maven executable (mvn) looks for and because the Maven installation's bin directory is on my path, I only needed to run "mvn" to compile the .class files as indicated in the next screen snapshot.

I can also run the compiled application with Maven using the command mvn exec:java -Dexec.mainClass=dustin.examples.Main, which is demonstrated in the next screen snapshot.

As is the case with Ant, I would typically not use Maven to run my simple Java application, but would instead use java on the compiled code (or use a script that invokes java directly for long classpaths).

Building and Running with Gradle

Gradle is the youngest, trendiest, and hippest of the three major Java build tools. I am sometimes skeptical of the substance of something that is trendy, but I have found many things to like about Gradle (written in Groovy instead of XML, built-in Ant support, built-in Ivy support, configuration by convention that is easily overridden, Maven repository support, etc.). The next example shows a Gradle build file that can be used to compile and run the simple application that is the primary example code for this post. It is adapted from the example I presented in the blog post Simple Gradle Java Plugin Customization.

build.gradle

apply plugin: 'java'
apply plugin: 'application'

// Redefine where Gradle should expect Java source files (*.java)
sourceSets {
main {
java {
srcDirs 'src'
}
}
}

// Redefine where .class files are written
sourceSets.main.output.classesDir = file("classes")

// Specify main class to be executed
mainClassName = "dustin.examples.Main"

defaultTasks 'compileJava', 'run'

The first two lines of the build.gradle file specify application of the Java plugin and the Application plugin, bringing a bunch of functionality automatically to this build. The definition of "sourceSets" and "sourceSets.main.output.classesDir" allows overriding of Gradle's Java plugin's default directories for Java source code and compiled binary classes respectively. The "mainClassName" allows explicit specification of which class should be run as part of the Application plugin. The "defaultTasks" line specifies the tasks to be run by simply typing "gradle" at the command line: 'compileJava' is a standard task provided by the Java plugin and 'run' is a standard task provided by the Application plugin. Because I named the build file build.gradle and because I specified the default tasks of 'compileJava' and 'run' and because I have the Gradle installation bin directory on my path, all I needed to do to build and run the examples was to type "gradle" and this is demonstrated in the next screen snapshot.

Even the biggest skeptic has to admit that Gradle build is pretty slick for this simple example. It combines brevity from relying on certain conventions and assumptions with a very easy mechanism for overriding select defaults as needed. The fact that it's in Groovy rather than XML is also very appealing!

As is the case with Ant and Maven, I tend to only build with these tools and typically run the compiled .class files directly with java or a script that invokes java. By the way, I typically also archive these .class into a JAR for running, but that's outside the scope of this post.

Conclusion

An IDE is often not necessary for building simple applications and examples and can even be more overhead than it's worth for the simplest examples. In such a case, it's fairly easy to apply javac and java directly to build and run the examples. As the examples become more involved, a build tool such as Ant, Maven, or Gradle becomes more appealing. The fact that many IDEs support these build tools means that a developer could transition to the IDE using the build tool created earlier in the process if it was determined that IDE support was needed as the simple application grew into a full-fledged project.

Thứ Năm, 27 tháng 3, 2014

Abstract Class Versus Interface in the JDK 8 Era

In The new Java 8 Date and Time API: An interview with Stephen Colebourne, Stephen Colebourne tells Hartmut Schlosser, "I think the most important language change isn't lambdas, but static and default methods on interfaces." Colebourne adds, "The addition of default methods removes many of the reasons to use abstract classes." As I read this, I realized that Colebourne is correct and that many situations in which I currently use abstract classes could be replaced with interfaces with JDK 8 default methods. This is pretty significant in the Java world as the difference between abstract classes and interfaces has been one of the issues that vex new Java developers trying to understand the difference. In many ways, differentiating between the two is even more difficult in JDK 8.

There are numerous examples of online forums and blogs discussing the differences between interfaces and abstract classes in Java. These include, but are not limited to, JavaWorld's Abstract classes vs. interfaces, StackOverflow's When do I have to use interfaces instead of abstract classes?, Difference Between Interface and Abstract Class, 10 Abstract Class and Interface Interview Questions Answers in Java, As useful and informative as these once were, many of them are now outdated and may be part of even more confusion for those new to Java who start their Java experience with JDK 8.

As I was thinking about the remaining differences between Java interfaces and abstract classes in a JDK 8 world, I decided to see what the Java Tutorial had to say on this. The tutorial has been updated to reflect JDK 8 and the Abstract Methods and Classes has a section called "Abstract Classes Compared to Interfaces" that has been updated to incorporate JDK 8. This section points out the similarities and differences of JDK 8 interfaces with abstract classes. The differences it highlights are the accessibility of data members and methods: abstract classes allow non-static and non-final fields and allow methods to be public, private, or protected while interfaces' fields are inherently public, static, and final, and all interface methods are inherently public.

The Java Tutorial goes on to list bullets for when an abstract class should be considered and for when an interface should be considered. Unsurprisingly, these are derived from the previously mentioned differences and have primarily to do with whether you need fields and methods to be private, protected, non-static, or not final (favor abstract class) or whether you need the ability to focus on typing without regard to implementation (favor interface).

Because Java allows a class to implement multiple interfaces but extend only one class, the interface might be considered advantageous when a particular implementation needs to be associated with multiple types. Thanks to the JDK 8's default methods, these interfaces can even provide default behavior for implementations.

A natural question might be, "How does Java handle a class that implements two interfaces, both of which describe a default method with the same signature?" The answer is that this is a compilation error. This is shown in the next screen snapshot which shows NetBeans 8 reporting the error when my class implemented two interfaces that each defined a default method with the same signature [String speak()].

As the screen snapshot above indicates, a compiler error is shown that states, "class ... inherits unrelated defaults for ... from types ... and ..." (where the class name, defaults method name, and two interface names are whatever are specified in the message). Peter Verhas has written a detailed post ("Java 8 default methods: what can and can not do?") looking at some corner cases (gotchas) related to multiply implemented interfaces with default method names with the same signature.

Conclusion

JDK 8 brings arguably the abstract class's greatest advantage over the interface to the interface. The implication of this is that a large number of abstract classes used today can likely be replaced by interfaces with default methods and a large number of future constructs that would have been abstract classes will now instead be interfaces with default methods.

Thứ Hai, 10 tháng 2, 2014

Serializing Java Objects with Non-Serializable Attributes

There are multiple reasons one might want to use custom serialization instead of relying on Java's default serialization. One of the most common reasons is for performance improvements, but another reason for writing custom serialization is when the default serialization mechanism is unsupported. Specifically, as will be demonstrated in this post, custom serialization can be used to allow a larger object to be serialized even when attributes of that object are not themselves directly serializable.

The next code listing shows a simple class for serializing a given class to a file of the provided name and for deserializing an object from that same file. I will be using it in this post to demonstrate serialization.

SerializationDemonstrator.java

package dustin.examples.serialization;

import static java.lang.System.out;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/**
* Simple serialization/deserialization demonstrator.
*
* @author Dustin
*/
public class SerializationDemonstrator
{
/**
* Serialize the provided object to the file of the provided name.
* @param objectToSerialize Object that is to be serialized to file; it is
* best that this object have an individually overridden toString()
* implementation as that is used by this method for writing our status.
* @param fileName Name of file to which object is to be serialized.
* @throws IllegalArgumentException Thrown if either provided parameter is null.
*/
public static <T> void serialize(final T objectToSerialize, final String fileName)
{
if (fileName == null)
{
throw new IllegalArgumentException(
"Name of file to which to serialize object to cannot be null.");
}
if (objectToSerialize == null)
{
throw new IllegalArgumentException("Object to be serialized cannot be null.");
}
try (FileOutputStream fos = new FileOutputStream(fileName);
ObjectOutputStream oos = new ObjectOutputStream(fos))
{
oos.writeObject(objectToSerialize);
out.println("Serialization of Object " + objectToSerialize + " completed.");
}
catch (IOException ioException)
{
ioException.printStackTrace();
}
}

/**
* Provides an object deserialized from the file indicated by the provided
* file name.
*
* @param <T> Type of object to be deserialized.
* @param fileToDeserialize Name of file from which object is to be deserialized.
* @param classBeingDeserialized Class definition of object to be deserialized
* from the file of the provided name/path; it is recommended that this
* class define its own toString() implementation as that will be used in
* this method's status output.
* @return Object deserialized from provided filename as an instance of the
* provided class; may be null if something goes wrong with deserialization.
* @throws IllegalArgumentException Thrown if either provided parameter is null.
*/
public static <T> T deserialize(final String fileToDeserialize, final Class<T> classBeingDeserialized)
{
if (fileToDeserialize == null)
{
throw new IllegalArgumentException("Cannot deserialize from a null filename.");
}
if (classBeingDeserialized == null)
{
throw new IllegalArgumentException("Type of class to be deserialized cannot be null.");
}
T objectOut = null;
try (FileInputStream fis = new FileInputStream(fileToDeserialize);
ObjectInputStream ois = new ObjectInputStream(fis))
{
objectOut = (T) ois.readObject();
out.println("Deserialization of Object " + objectOut + " is completed.");
}
catch (IOException | ClassNotFoundException exception)
{
exception.printStackTrace();
}
return objectOut;
}
}

The next code listing illustrates use of the SerializationDemonstrator class to serialize and deserialize a standard Java string (which is Serializable). A screen snapshot follows the code listing and shows the output (in NetBeans) of running that String through the serialize and deserialize methods of the SerializationDemonstrator class.

Running SerializationDemonstrator Methods on String

SerializationDemonstrator.serialize("Inspired by Actual Events", "string.dat");
final String stringOut = SerializationDemonstrator.deserialize("string.dat", String.class);

The next two code listings are for the class Person.java and a class that it has as an attribute type (CityState.java). Although Person implements Serializable, the CityAndState class does not.

Person.java

package dustin.examples.serialization;

import java.io.Serializable;

/**
* Person class.
*
* @author Dustin
*/
public class Person implements Serializable
{
private String lastName;
private String firstName;
private CityState cityAndState;

public Person(
final String newLastName, final String newFirstName,
final CityState newCityAndState)
{
this.lastName = newLastName;
this.firstName = newFirstName;
this.cityAndState = newCityAndState;
}

public String getFirstName()
{
return this.firstName;
}

public String getLastName()
{
return this.lastName;
}

@Override
public String toString()
{
return this.firstName + " " + this.lastName + " of " + this.cityAndState;
}
}
CityAndState.java

package dustin.examples.serialization;

/**
* Simple class storing city and state names that is NOT Serializable.
*
* @author Dustin
*/
public class CityState
{
private final String cityName;
private final String stateName;

public CityState(final String newCityName, final String newStateName)
{
this.cityName = newCityName;
this.stateName = newStateName;
}

public String getCityName()
{
return this.cityName;
}

public String getStateName()
{
return this.stateName;
}

@Override
public String toString()
{
return this.cityName + ", " + this.stateName;
}
}

The next code listing demonstrates running SerializationDemonstrator on the serializable Person class with a non-serializable CityState. The code listing is followed by a screen snapshot of the output in NetBeans.

Running SerializationDemonstrator Methods on Serializable Person with Non-Serializable CityState

final Person personIn = new Person("Flintstone", "Fred", new CityState("Bedrock", "Cobblestone"));
SerializationDemonstrator.serialize(personIn, "person.dat");

final Person personOut = SerializationDemonstrator.deserialize("person.dat", Person.class);

In this case, the CityState class is my own class and I could make it Serializable. However, supposing that this class was part of a third-party framework or library and I was not able to change the class itself, I can change Person to use custom serialization and deserialization and work with CityState properly. This is shown in the next code listing for the class SerializablePerson that is adapted from Person.

SerializablePerson.java

package dustin.examples.serialization;

import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;

/**
* Person class.
*
* @author Dustin
*/
public class SerializablePerson implements Serializable
{
private String lastName;
private String firstName;
private CityState cityAndState;

public SerializablePerson(
final String newLastName, final String newFirstName,
final CityState newCityAndState)
{
this.lastName = newLastName;
this.firstName = newFirstName;
this.cityAndState = newCityAndState;
}

public String getFirstName()
{
return this.firstName;
}

public String getLastName()
{
return this.lastName;
}

@Override
public String toString()
{
return this.firstName + " " + this.lastName + " of " + this.cityAndState;
}

/**
* Serialize this instance.
*
* @param out Target to which this instance is written.
* @throws IOException Thrown if exception occurs during serialization.
*/
private void writeObject(final ObjectOutputStream out) throws IOException
{
out.writeUTF(this.lastName);
out.writeUTF(this.firstName);
out.writeUTF(this.cityAndState.getCityName());
out.writeUTF(this.cityAndState.getStateName());
}

/**
* Deserialize this instance from input stream.
*
* @param in Input Stream from which this instance is to be deserialized.
* @throws IOException Thrown if error occurs in deserialization.
* @throws ClassNotFoundException Thrown if expected class is not found.
*/
private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException
{
this.lastName = in.readUTF();
this.firstName = in.readUTF();
this.cityAndState = new CityState(in.readUTF(), in.readUTF());
}

private void readObjectNoData() throws ObjectStreamException
{
throw new InvalidObjectException("Stream data required");
}
}

The above code listing shows that SerializablePerson has custom writeObject and readObject methods to support custom serialization/deserialization that handle its attribute of unserializable type CityState appropriately. A snippet of code for running this class through the SerializationDemonstrator and the successful output of doing so are shown next.

Running SerializationDemonstrator on SerializablePerson

final SerializablePerson personIn = new SerializablePerson("Flintstone", "Fred", new CityState("Bedrock", "Cobblestone"));
SerializationDemonstrator.serialize(personIn, "person1.dat");

final SerializablePerson personOut = SerializationDemonstrator.deserialize("person1.dat", SerializablePerson.class);

The approach depicted above will allow non-serializable types to be used as attributes of serializable classes without the need to make those fields transient. However, if the CityState instance shown earlier needs to be used in multiple serializable classes, it might be better to decorate the CityState class with a serializable decorator and then used that serialized decorator class in classes needing to be serialized. The next code listing shows SerializableCityState which decorates CityState with a serialized version.

SerializableCityState

package dustin.examples.serialization;

import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;

/**
* Simple class storing city and state names that IS Serializable. This class
* decorates the non-Serializable CityState class and adds Serializability.
*
* @author Dustin
*/
public class SerializableCityState implements Serializable
{
private CityState cityState;

public SerializableCityState(final String newCityName, final String newStateName)
{
this.cityState = new CityState(newCityName, newStateName);
}

public String getCityName()
{
return this.cityState.getCityName();
}

public String getStateName()
{
return this.cityState.getStateName();
}

@Override
public String toString()
{
return this.cityState.toString();
}

/**
* Serialize this instance.
*
* @param out Target to which this instance is written.
* @throws IOException Thrown if exception occurs during serialization.
*/
private void writeObject(final ObjectOutputStream out) throws IOException
{
out.writeUTF(this.cityState.getCityName());
out.writeUTF(this.cityState.getStateName());
}

/**
* Deserialize this instance from input stream.
*
* @param in Input Stream from which this instance is to be deserialized.
* @throws IOException Thrown if error occurs in deserialization.
* @throws ClassNotFoundException Thrown if expected class is not found.
*/
private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException
{
this.cityState = new CityState(in.readUTF(), in.readUTF());
}

private void readObjectNoData() throws ObjectStreamException
{
throw new InvalidObjectException("Stream data required");
}
}

This serializable decorator can be used in the Person class directly and that enclosing Person can use default serialization because its fields are all serializable. This is shown in the next code listing for Person2 adapted from Person.

Person2.java

package dustin.examples.serialization;

import java.io.Serializable;

/**
* Person class.
*
* @author Dustin
*/
public class Person2 implements Serializable
{
private final String lastName;
private final String firstName;
private final SerializableCityState cityAndState;

public Person2(
final String newLastName, final String newFirstName,
final SerializableCityState newCityAndState)
{
this.lastName = newLastName;
this.firstName = newFirstName;
this.cityAndState = newCityAndState;
}

public String getFirstName()
{
return this.firstName;
}

public String getLastName()
{
return this.lastName;
}

@Override
public String toString()
{
return this.firstName + " " + this.lastName + " of " + this.cityAndState;
}
}

This code can be executed as shown in the next code listing, which is followed by its output as seen in the NetBeans output window.

Running SerializationDemonstrator Against Person2/SerializableCityState

final Person2 personIn = new Person2("Flintstone", "Fred", new SerializableCityState("Bedrock", "Cobblestone"));
SerializationDemonstrator.serialize(personIn, "person2.dat");

final Person2 personOut = SerializationDemonstrator.deserialize("person2.dat", Person2.class);

Custom serialization can be used to allow a class with attributes of nonserializable types to be serialized without making those attributes of nonserializable type transient. This is a useful technique when serializable classes need to use attributes of types that are not serializable and that cannot be changed.

Thứ Hai, 3 tháng 2, 2014

ObjectStreamClass: Peeking at a Java Object's Serialization

ObjectStreamClass can be a useful class to analyze the serialization characteristics of a serialized class loaded in the JVM. This post looks at some of the information this class provides about a loaded serialized class.

ObjectStreamClass provides two static methods for lookup of a class: lookup(class) and lookupAny(Class). The first, lookup(Class), will only return an instance of ObjectStreamClass when the provided class is serializable and returns null if the provided class is not serializable. The second, lookupAny(Class) returns an instance of ObjectStreamClass for the provided class regardless of whether it's serializable or not.

Once an instance of ObjectStreamClass is provided via the static "lookup" methods, that instance can be queried for class name, for serial version UID, and for serializable fields.

To demonstrate use of ObjectStreamClass, I first list the code listings for two simple classes that will be part of the demonstration. One class, Person, is Serializable, but has a transient field. The other class, UnserializablePerson, is nearly identical, but it is not Serializable.

Person.java

package dustin.examples.serialization;

import java.io.Serializable;

/**
* Person class intended for demonstration of ObjectStreamClass.
*
* @author Dustin
*/
public class Person implements Serializable
{
private final String lastName;
private final String firstName;
transient private final String fullName;

public Person(final String newLastName, final String newFirstName)
{
this.lastName = newLastName;
this.firstName = newFirstName;
this.fullName = this.firstName + " " + this.lastName;
}

public String getFirstName()
{
return this.firstName;
}

public String getLastName()
{
return this.lastName;
}

public String getFullName()
{
return this.fullName;
}

@Override
public String toString()
{
return this.fullName;
}
}
UnserializablePerson.java

package dustin.examples.serialization;

/**
* Person class intended for demonstration of ObjectStreamClass.
*
* @author Dustin
*/
public class UnserializablePerson
{
private final String lastName;
private final String firstName;
private final String fullName;

public UnserializablePerson(final String newLastName, final String newFirstName)
{
this.lastName = newLastName;
this.firstName = newFirstName;
this.fullName = this.firstName + " " + this.lastName;
}

public String getFirstName()
{
return this.firstName;
}

public String getLastName()
{
return this.lastName;
}

public String getFullName()
{
return this.fullName;
}

@Override
public String toString()
{
return this.fullName;
}
}

With two classes in place to run use in conjunction with ObjectStreamClass, it's now time to look at a simple demonstration application that shows use of ObjectStreamClass.

ObjectStreamClassDemo.java

package dustin.examples.serialization;

import static java.lang.System.out;

import java.io.ObjectStreamClass;
import java.io.ObjectStreamField;

/**
* Demonstrates use of ObjectStreamDemo.
*
* @author Dustin
*/
public class ObjectStreamClassDemo
{
/**
* Displays class name, serial version UID, and serializable fields as
* indicated by the provided instance of ObjectStreamClass.
*
* @param serializedClass
*/
public static void displaySerializedClassInformation(
final ObjectStreamClass serializedClass)
{
final String serializedClassName = serializedClass.getName();
out.println("Class Name: " + serializedClassName);
final long serializedVersionUid = serializedClass.getSerialVersionUID();
out.println("serialversionuid: " + serializedVersionUid);
final ObjectStreamField[] fields = serializedClass.getFields();
out.println("Serialized Fields:");
for (final ObjectStreamField field : fields)
{
out.println("\t" + field.getTypeString() + " " + field.getName());
}
}

/**
* Main function that demonstrates use of ObjectStreamDemo.
*
* @param arguments Command line arguments; none expected.
*/
public static void main(String[] arguments)
{
// Example 1: ObjectStreamClass.lookup(Class) on a Serializable class
out.println("\n=== ObjectStreamClass.lookup(Serializable) ===");
final ObjectStreamClass serializedClass = ObjectStreamClass.lookup(Person.class);
displaySerializedClassInformation(serializedClass);

// Example 2: ObjectStreamClass.lookup(Class) on a class that is not
// Serializable (which will result in a NullPointerException
// when trying to access null returned from 'lookup'
out.println("\n=== ObjectStreamClass.lookup(Unserializable) ===");
try
{
final ObjectStreamClass unserializedClass =
ObjectStreamClass.lookup(UnserializablePerson.class);
displaySerializedClassInformation(unserializedClass);
}
catch (NullPointerException npe)
{
out.println("NullPointerException: Unable to lookup unserializable class with ObjectStreamClass.lookup.");
}

// Example 3: ObjectStreamClass.lookupAny(Class) works without the
// NullPointerException, but only provides name of the class as
// Serial Version UID and serialized fields do not apply in the
// case of a class that is not serializable.
out.println("\n=== ObjectStreamClass.lookupAny(Unserializable) ===");
final ObjectStreamClass unserializedClass =
ObjectStreamClass.lookupAny(UnserializablePerson.class);
displaySerializedClassInformation(unserializedClass);
}
}

The comments in the source code above indicate what is being demonstrated. The output from running this class is shown in the next screen snapshot.

When the output shown above is correlated with the code before it, we can make several observations related to ObjectStreamClass. These include the fact that the transient field of a serializable class is not returned as one of the serializable fields. We also see that ObjectStreamClass.lookup(Class) method returns null if the class provided to it is not serializable. ObjectStreamClass.lookupAny(Class) returns an instance of ObjectStreamClass for classes that are not serializable, but only the class's name is available in that case.

The code above showed a Serial Version UID for Person.java of 1940442894442614965. When serialver is run on the command line, the same Serial Version UID is generated and displayed.

What's nice about the ability to programatically calculate the same Serial Version UID as would be calculated by the serialver tool that comes with the Oracle JDK is that one could explicitly add the same Serial Version UID to generated code as would be implicitly added anyway. Any JVM-friendly script or tool (such as one written in Groovy) that needs to know the implicit Serial Version UID of a class could use ObjectStreamClass to obtain that Serial Version UID.

Thứ Hai, 20 tháng 1, 2014

Something to Consider as Java Tops the Programming Charts

The following is a contributed article from Dennis Chu of Coverity:


Something to Consider as Java Tops the Programming Charts

By Dennis Chu, Senior Product Manager, Coverity

For development teams, it may be obvious: Java is one of the top programming languages today. Approximately 9 million developers are currently working in Java; it’s said to be running on three billion devices and the language continues to evolve almost as quickly as the changing technology landscape. But, as the story goes, the rise to the top isn’t always easy.

While Java continues to grow in popularity, it has also been linked to a number of vulnerabilities over the years - due in large part to hackers capitalizing on its widespread use. So much so that Apple moved to pull Java entirely from its Mac OS X and its products at the end of 2012.

Further, during the summer of 2013, flaws in Java were linked to growing security threats for some Android device users who owned the much-hyped digital currency Bitcoin. The vulnerability enabled hackers to tap into the digital wallets of these Bitcoin owners, exposing a serious risk for both the new monetary system and the Android operating system.

One of the most recent blows for Java came from its link to HealthCare.gov, the website that continues to make headlines as developers work to fix the programming errors that caused the site to come to a crawl - only about 5 percent of the expected 500,000 health insurance plan enrollments were able to occur in the first month of the site’s launch. HealthCare.gov was developed with Java on top of Tomcat, and while the causes of its errors are many and complex, coding and architecture design flaws were no doubt part of the problem.

Despite the shortcomings exposed over the years, Java has a large number of effective testing and development tools. But even so, given the persistence of issues, it’s become clear that these tools are not being leveraged properly. This is presumably due to poor development testing discipline or weak processes in place within organizations.

After reviewing a number of open source Java projects via our Coverity Scan service – which helps the open source development community evaluate and improve the quality and security of their software – we found similar levels of quality and security issues for Java relative to other languages, such as C and C++. So it turns out that just because Java is one of the most widely used computer languages, it doesn’t guarantee higher quality software.

Some advice for developers coding in Java, or any other computer programming language for that matter: be vigilant. Make an emphasis to select the right tools that will provide the right framework and process to allow your organization to test early and often. This will enable your organization to avoid potential nightmares down the road – for example after it’s been released to customers, when it’s too late.

Using the right technologies and best practices are still the best safeguards to ensure high-quality software. Fixing a flaw during the development process will cost only a small fraction of what it will cost to fix a defect after the product has been released – and that’s not including the damage to your brand and reputation.

On the road ahead, no matter what language tops the charts, it’s important to view testing as a critical investment rather than an unintended expense.


The article above was contributed by Dennis Chu of Coverity. I have published this contributed article because I think it brings up some interesting points of discussion. No payment or remuneration was received for publishing this article.

Thứ Hai, 23 tháng 12, 2013

Determining Presence of Characters or Integers in String with Guava CharMatcher and Apache Commons Lang StringUtils

A recent Reddit post asked the question, "Is there a predefined method for checking if a variable value contains a particular character or integer?" That question-based title was also asked a different way, "A method or quick way for checking if a variable contains any numbers say or ('x',2,'B') like a list?" I am not aware of any single method call within the standard SDK libraries to do this (other than using a carefully designed regular expression), but in this post I answer those questions using Guava's CharMatcher and Apache Common Lang's StringUtils class.

Java's String class does have a contains method that can be used to determine if a single character is contained in that String or if a certain explicitly specified sequence of characters is contained in that String. However, I'm not aware of any way in a single executable statement (not counting regular expressions) to ask Java if a given String contains any of a specified set of characters without needing to contain all of them or contain them in the specified order. Both Guava and Apache Commons Lang do provide mechanisms for just this thing.

Apache Commons Lang (version 3.1 used in this post) provides overloaded StringUtils.containsAny methods that easily accomplish this request. Both overloaded versions expect the first parameter passed to them to be the String (or more precisely, the CharSequence) to be tested to see if it contains a given letter or integer. The first overloaded version, StringUtils.containsAny(CharSequence, char...) accepts zero or more char elements to be tested to see if any of them are in the String represented by the first argument. The second overloaded version, StringUtils.containsAny(CharSequence, CharSequence) expects the second argument to contain all the potential characters to be searched for in the first argument as a single sequence of characters.

The following code listing demonstrates using this Apache Commons Lang approach to determine if a given string contains certain characters. All three statements will pass their assertions because "Inspired by Actual Events" does include 'd' and 'A', but not 'Q'. Because it is only necessary for any one of the provided characters to be present to return true, the first two assertions of true pass. The third assertion passes because the string does NOT contain the only provided letter and so the negative is asserted.

Determining String Contains A Character with StringUtils

private static void demoStringContainingLetterInStringUtils()
{
assert StringUtils.containsAny("Inspired by Actual Events", 'd', 'A'); // true: both contained
assert StringUtils.containsAny("Inspired by Actual Events", 'd', 'Q'); // true: one contained
assert !StringUtils.containsAny("Inspired by Actual Events", 'Q'); // true: none contained (!)
}

Guava's CharMatcher can also be used in a similar manner as demonstrated in the next code listing.

Determining String Contains A Character with CharMatcher

private static void demoStringContainingLetterInGuava()
{
assert CharMatcher.anyOf("Inspired by Actual Events").matchesAnyOf(new String(new char[]{'d', 'A'}));
assert CharMatcher.anyOf("Inspired by Actual Events").matchesAnyOf(new String (new char[] {'d', 'Q'}));
assert !CharMatcher.anyOf("Inspired by Actual Events").matchesAnyOf(new String(new char[]{'Q'}));
}

What if we specifically want to make sure at least one character in a given String/CharSequence is a numeric (integer), but we cannot be guaranteed that the entire string is numerics? The same approach as used above with Apache Commons Lang's StringUtils can be applied here with the only change being that the provided letters to be matched are the numeric digits 0 through 9. This is shown in the next screen snapshot.

Determining String Contains a Numeral with StringUtils

private static void demoStringContainingNumericDigitInStringUtils()
{
assert !StringUtils.containsAny("Inspired by Actual Events", "0123456789");
assert StringUtils.containsAny("Inspired by Actual Events 2013", "0123456789");
}

Guava's CharMatcher has a really slick way of expressing this question of whether a provided sequence of characters includes at least one numeral. This is shown in the next code listing.

Determining String Contains a Numeral with CharMatcher

private static void demoStringContainingNumericDigitInGuava()
{
assert !CharMatcher.DIGIT.matchesAnyOf("Inspired by Actual Events");
assert CharMatcher.DIGIT.matchesAnyOf("Inspired by Actual Events 2013");
}

CharMatcher.DIGIT provides a concise and expressive approach to specifying that we want to match a digit. Fortunately, CharMatcher provides numerous other public fields similar to DIGIT for convenience in determining if strings contain other types of characters.

For completeness, I have included the single class containing all of the above examples in the next code listing. This class's main() function can be run with the -enableassertions (or -ea) flag set on the Java launcher and will complete without any AssertionErrors.

StringContainsDemonstrator.java

package dustin.examples.strings;

import com.google.common.base.CharMatcher;
import static java.lang.System.out;

import org.apache.commons.lang3.StringUtils;

/**
* Demonstrate Apache Commons Lang StringUtils and Guava's CharMatcher. This
* class exists to demonstrate Apache Commons Lang StringUtils and Guava's
* CharMatcher support for determining if a particular character or set of
* characters or integers is contained within a given
*
* This class's tests depend on asserts being enabled, so specify the JVM option
* -enableassertions (-ea) when running this example.
*
* @author Dustin
*/
public class StringContainsDemonstrator
{
private static final String CANDIDATE_STRING = "Inspired by Actual Events";
private static final String CANDIDATE_STRING_WITH_NUMERAL = CANDIDATE_STRING + " 2013";
private static final char FIRST_CHARACTER = 'd';
private static final char SECOND_CHARACTER = 'A';
private static final String CHARACTERS = new String(new char[]{FIRST_CHARACTER, SECOND_CHARACTER});
private static final char NOT_CONTAINED_CHARACTER = 'Q';
private static final String NOT_CONTAINED_CHARACTERS = new String(new char[]{NOT_CONTAINED_CHARACTER});
private static final String MIXED_CONTAINED_CHARACTERS = new String (new char[] {FIRST_CHARACTER, NOT_CONTAINED_CHARACTER});
private static final String NUMERIC_CHARACTER_SET = "0123456789";

private static void demoStringContainingLetterInGuava()
{
assert CharMatcher.anyOf(CANDIDATE_STRING).matchesAnyOf(CHARACTERS);
assert CharMatcher.anyOf(CANDIDATE_STRING).matchesAnyOf(MIXED_CONTAINED_CHARACTERS);
assert !CharMatcher.anyOf(CANDIDATE_STRING).matchesAnyOf(NOT_CONTAINED_CHARACTERS);
}

private static void demoStringContainingNumericDigitInGuava()
{
assert !CharMatcher.DIGIT.matchesAnyOf(CANDIDATE_STRING);
assert CharMatcher.DIGIT.matchesAnyOf(CANDIDATE_STRING_WITH_NUMERAL);
}

private static void demoStringContainingLetterInStringUtils()
{
assert StringUtils.containsAny(CANDIDATE_STRING, FIRST_CHARACTER, SECOND_CHARACTER);
assert StringUtils.containsAny(CANDIDATE_STRING, FIRST_CHARACTER, NOT_CONTAINED_CHARACTER);
assert !StringUtils.containsAny(CANDIDATE_STRING, NOT_CONTAINED_CHARACTER);
}

private static void demoStringContainingNumericDigitInStringUtils()
{
assert !StringUtils.containsAny(CANDIDATE_STRING, NUMERIC_CHARACTER_SET);
assert StringUtils.containsAny(CANDIDATE_STRING_WITH_NUMERAL, NUMERIC_CHARACTER_SET);
}

/**
* Indicate whether assertions are enabled.
*
* @return {@code true} if assertions are enabled or {@code false} if
* assertions are not enabled (are disabled).
*/
private static boolean areAssertionsEnabled()
{
boolean enabled = false;
assert enabled = true;
return enabled;
}

/**
* Main function for running methods to demonstrate Apache Commons Lang
* StringUtils and Guava's CharMatcher support for determining if a particular
* character or set of characters or integers is contained within a given
* String.
*
* @param args the command line arguments Command line arguments; none expected.
*/
public static void main(String[] args)
{
if (!areAssertionsEnabled())
{
out.println("This class cannot demonstrate anything without assertions enabled.");
out.println("\tPlease re-run with assertions enabled (-ea).");
System.exit(-1);
}

out.println("Beginning demonstrations...");
demoStringContainingLetterInGuava();
demoStringContainingLetterInStringUtils();
demoStringContainingNumericDigitInGuava();
demoStringContainingNumericDigitInStringUtils();
out.println("...Demonstrations Ended");
}
}

Guava and Apache Commons Lang are very popular with Java developers because of the methods they provide beyond what the SDK provides that Java developers commonly need. In this post, I looked at how Guava's CharMatcher and Apache Commons Lang's StringUtils can be used to concisely but expressively test to determine if any of a set of specified characters exists within a provided string.

Orika: Mapping JAXB Objects to Business/Domain Objects

This post looks at mapping JAXB objects to business domain objects with Orika. Earlier this month, I covered the same mapping use case using reflection-based Dozer. In this post, I'll assume the same example classes need to be mapped, but they will be mapped using Orika instead of Dozer.

Dozer and Orika are intended to solve the same type of problem: the automatic mapping of two "data" objects that do not share a common inheritance but represent the same same of data fields. Dozer uses reflection to accomplish this while Orika uses reflection and bytecode manipulation to accomplish it. Orika's slogan is, "simpler, lighter and faster Java bean mapping."

Orika has an Apache License, Version 2, and can be downloaded at https://github.com/orika-mapper/orika/archive/master.zip (sources) or at http://search.maven.org/#search|ga|1|orika (binaries). Orika has dependencies on Javassist (for bytecode manipulation), SLF4J, and paranamer (to access method/constructor parameter names at runtime). Two of these three dependencies (JavaAssist and paranamer but not SLF4J) are bundled in orika-core-1.4.4-deps-included.jar. If the dependencies are already available, the slimmer orika-core-1.4.4.jar can be used instead. As the names of these JARs suggest, I'm using Orika 1.4.4 for my examples in this post.

In my post Dozer: Mapping JAXB Objects to Business/Domain Objects, I discussed reasons that using instances of JAXB-generatated classes as business or domain objects is often not desirable. I then showed "traditional" ways of mapping between JAXB-generated classes and custom data classes so that data could be passed throughout an application in the business domain data objects. For this post, I will be using the same approach, but with Orika doing the mapping rather than doing custom mapping or using Dozer for the mapping. For convenience, I include the cost listings here for the JAXB-generated classes com.blogspot.marxsoftware.AddressType and com.blogspot.marxsoftware.PersonType as well as the renamed custom data classes dustin.examples.orikademo.Address and dustin.examples.orikademo.Person.

JAXB-generated AddressType.java

//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2013.12.03 at 11:44:32 PM MST
//


package com.blogspot.marxsoftware;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;


/**
* <p>Java class for AddressType complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType name="AddressType">
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <attribute name="streetAddress1" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
* <attribute name="streetAddress2" type="{http://www.w3.org/2001/XMLSchema}string" />
* <attribute name="city" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
* <attribute name="state" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
* <attribute name="zipcode" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "AddressType")
public class AddressType {

@XmlAttribute(name = "streetAddress1", required = true)
protected String streetAddress1;
@XmlAttribute(name = "streetAddress2")
protected String streetAddress2;
@XmlAttribute(name = "city", required = true)
protected String city;
@XmlAttribute(name = "state", required = true)
protected String state;
@XmlAttribute(name = "zipcode", required = true)
protected String zipcode;

/**
* Gets the value of the streetAddress1 property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getStreetAddress1() {
return streetAddress1;
}

/**
* Sets the value of the streetAddress1 property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setStreetAddress1(String value) {
this.streetAddress1 = value;
}

/**
* Gets the value of the streetAddress2 property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getStreetAddress2() {
return streetAddress2;
}

/**
* Sets the value of the streetAddress2 property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setStreetAddress2(String value) {
this.streetAddress2 = value;
}

/**
* Gets the value of the city property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getCity() {
return city;
}

/**
* Sets the value of the city property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setCity(String value) {
this.city = value;
}

/**
* Gets the value of the state property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getState() {
return state;
}

/**
* Sets the value of the state property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setState(String value) {
this.state = value;
}

/**
* Gets the value of the zipcode property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getZipcode() {
return zipcode;
}

/**
* Sets the value of the zipcode property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setZipcode(String value) {
this.zipcode = value;
}

}
JAXB-generated PersonType.java

//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2013.12.03 at 11:44:32 PM MST
//


package com.blogspot.marxsoftware;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;


/**
* <p>Java class for PersonType complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType name="PersonType">
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="MailingAddress" type="{http://marxsoftware.blogspot.com/}AddressType"/>
* <element name="ResidentialAddress" type="{http://marxsoftware.blogspot.com/}AddressType" minOccurs="0"/>
* </sequence>
* <attribute name="firstName" type="{http://www.w3.org/2001/XMLSchema}string" />
* <attribute name="lastName" type="{http://www.w3.org/2001/XMLSchema}string" />
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "PersonType", propOrder = {
"mailingAddress",
"residentialAddress"
})
public class PersonType {

@XmlElement(name = "MailingAddress", required = true)
protected AddressType mailingAddress;
@XmlElement(name = "ResidentialAddress")
protected AddressType residentialAddress;
@XmlAttribute(name = "firstName")
protected String firstName;
@XmlAttribute(name = "lastName")
protected String lastName;

/**
* Gets the value of the mailingAddress property.
*
* @return
* possible object is
* {@link AddressType }
*
*/
public AddressType getMailingAddress() {
return mailingAddress;
}

/**
* Sets the value of the mailingAddress property.
*
* @param value
* allowed object is
* {@link AddressType }
*
*/
public void setMailingAddress(AddressType value) {
this.mailingAddress = value;
}

/**
* Gets the value of the residentialAddress property.
*
* @return
* possible object is
* {@link AddressType }
*
*/
public AddressType getResidentialAddress() {
return residentialAddress;
}

/**
* Sets the value of the residentialAddress property.
*
* @param value
* allowed object is
* {@link AddressType }
*
*/
public void setResidentialAddress(AddressType value) {
this.residentialAddress = value;
}

/**
* Gets the value of the firstName property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getFirstName() {
return firstName;
}

/**
* Sets the value of the firstName property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setFirstName(String value) {
this.firstName = value;
}

/**
* Gets the value of the lastName property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getLastName() {
return lastName;
}

/**
* Sets the value of the lastName property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setLastName(String value) {
this.lastName = value;
}

}
Domain/Business Class Address.java

package dustin.examples.orikademo;

import java.util.Objects;

/**
* Address class.
*
* @author Dustin
*/
public class Address
{
private String streetAddress1;
private String streetAddress2;
private String municipality;
private String state;
private String zipCode;

public Address() {}

public Address(
final String newStreetAddress1,
final String newStreetAddress2,
final String newMunicipality,
final String newState,
final String newZipCode)
{
this.streetAddress1 = newStreetAddress1;
this.streetAddress2 = newStreetAddress2;
this.municipality = newMunicipality;
this.state = newState;
this.zipCode = newZipCode;
}

public String getStreetAddress1()
{
return this.streetAddress1;
}

public void setStreetAddress1(String streetAddress1)
{
this.streetAddress1 = streetAddress1;
}

public String getStreetAddress2()
{
return this.streetAddress2;
}

public void setStreetAddress2(String streetAddress2)
{
this.streetAddress2 = streetAddress2;
}

public String getMunicipality()
{
return this.municipality;
}

public void setMunicipality(String municipality)
{
this.municipality = municipality;
}

public String getState() {
return this.state;
}

public void setState(String state)
{
this.state = state;
}

public String getZipCode()
{
return this.zipCode;
}

public void setZipCode(String zipCode)
{
this.zipCode = zipCode;
}

@Override
public int hashCode()
{
return Objects.hash(
this.streetAddress1, this.streetAddress2, this.municipality,
this.state, this.zipCode);
}

@Override
public boolean equals(Object obj)
{
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Address other = (Address) obj;
if (!Objects.equals(this.streetAddress1, other.streetAddress1))
{
return false;
}
if (!Objects.equals(this.streetAddress2, other.streetAddress2))
{
return false;
}
if (!Objects.equals(this.municipality, other.municipality))
{
return false;
}
if (!Objects.equals(this.state, other.state))
{
return false;
}
if (!Objects.equals(this.zipCode, other.zipCode))
{
return false;
}
return true;
}

@Override
public String toString()
{
return "Address{" + "streetAddress1=" + streetAddress1 + ", streetAddress2="
+ streetAddress2 + ", municipality=" + municipality + ", state=" + state
+ ", zipCode=" + zipCode + '}';
}

}
Domain/Business Class Person.java

package dustin.examples.orikademo;

import java.util.Objects;

/**
* Person class.
*
* @author Dustin
*/
public class Person
{
private String lastName;
private String firstName;
private Address mailingAddress;
private Address residentialAddress;

public Person() {}

public Person(
final String newLastName,
final String newFirstName,
final Address newResidentialAddress,
final Address newMailingAddress)
{
this.lastName = newLastName;
this.firstName = newFirstName;
this.residentialAddress = newResidentialAddress;
this.mailingAddress = newMailingAddress;
}

public String getLastName()
{
return this.lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public String getFirstName()
{
return this.firstName;
}

public void setFirstName(String firstName)
{
this.firstName = firstName;
}

public Address getMailingAddress()
{
return this.mailingAddress;
}

public void setMailingAddress(Address mailingAddress)
{
this.mailingAddress = mailingAddress;
}

public Address getResidentialAddress()
{
return this.residentialAddress;
}

public void setResidentialAddress(Address residentialAddress)
{
this.residentialAddress = residentialAddress;
}

@Override
public int hashCode()
{
int hash = 3;
hash = 19 * hash + Objects.hashCode(this.lastName);
hash = 19 * hash + Objects.hashCode(this.firstName);
hash = 19 * hash + Objects.hashCode(this.mailingAddress);
hash = 19 * hash + Objects.hashCode(this.residentialAddress);
return hash;
}

@Override
public boolean equals(Object obj)
{
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
final Person other = (Person) obj;
if (!Objects.equals(this.lastName, other.lastName))
{
return false;
}
if (!Objects.equals(this.firstName, other.firstName))
{
return false;
}
if (!Objects.equals(this.mailingAddress, other.mailingAddress))
{
return false;
}
if (!Objects.equals(this.residentialAddress, other.residentialAddress))
{
return false;
}
return true;
}

@Override
public String toString() {
return "Person{" + "lastName=" + lastName + ", firstName=" + firstName
+ ", mailingAddress=" + mailingAddress + ", residentialAddress="
+ residentialAddress + '}';
}

}

As was the case with Dozer, the classes being mapped need to have no-arguments constructors and "set" and "get" methods to support conversion in both directions without any special additional configuration. Also, as was the case with Dozer, Orika maps same-named fields automatically and makes it easy to configure the mapping of the exceptions (fields whose names don't match). The next code listing, for a class I call OrikaPersonConverter, demonstrates the instantiation and configuration of an Orika MapperFactory to map most fields by default and to map the fields with different names than each other ("municipality" and "city") through explicit mapping configuration. Once the MapperFactory is configured, copying from one object to another is easy and both directions are depicted in the methods copyPersonTypeFromPerson and copyPersonFromPersonType.

OrikaPersonConverter

package dustin.examples.orikademo;

import com.blogspot.marxsoftware.AddressType;
import com.blogspot.marxsoftware.PersonType;
import ma.glasnost.orika.MapperFacade;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;

/**
* Convert between instances of {@link com.blogspot.marxsoftware.PersonType}
* and {@link dustin.examples.orikademo.Person}.
*
* @author Dustin
*/
public class OrikaPersonConverter
{
/** Orika Mapper Facade. */
private final static MapperFacade mapper;

static
{
final MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
mapperFactory.classMap(Address.class, AddressType.class)
.field("municipality", "city")
.byDefault()
.register();
mapper = mapperFactory.getMapperFacade();
}

/** No-arguments constructor. */
public OrikaPersonConverter() {}

/**
* Provide an instance of {@link com.blogspot.marxsoftware.PersonType}
* that corresponds with provided {@link dustin.examples.orikademo.Person} as
* mapped by Dozer Mapper.
*
* @param person Instance of {@link dustin.examples.orikademo.Person} from which
* {@link com.blogspot.marxsoftware.PersonType} will be extracted.
* @return Instance of {@link com.blogspot.marxsoftware.PersonType} that
* is based on provided {@link dustin.examples.orikademo.Person} instance.
*/
public PersonType copyPersonTypeFromPerson(final Person person)
{
PersonType personType = mapper.map(person, PersonType.class);
return personType;
}

/**
* Provide an instance of {@link dustin.examples.orikademo.Person} that corresponds
* with the provided {@link com.blogspot.marxsoftware.PersonType} as
* mapped by Dozer Mapper.
*
* @param personType Instance of {@link com.blogspot.marxsoftware.PersonType}
* from which {@link dustin.examples.orikademo.Person} will be extracted.
* @return Instance of {@link dustin.examples.orikademo.Person} that is based on the
* provided {@link com.blogspot.marxsoftware.PersonType}.
*/
public Person copyPersonFromPersonType(final PersonType personType)
{
Person person = mapper.map(personType, Person.class);
return person;
}
}

As is the case with Dozer, the mapping between two classes is bidirectional and so only needs to be made once and will apply in copying from either object to the other.

Conclusion

Like Dozer, Orika offers much more customizability and flexibility than demonstrated in this post. However, for relatively simple mappings (which are very common with applications using JAXB-generated objects), Orika is very easy to use out of the box. A good resource for learning more about Orika is the Orika User Guide.