Wednesday, December 31, 2014

Printing content of Java list

This is a very, very simple reference on how to print the contents of a Java List.  The idea is simple. I have a List and I want to loop over it and print whatever is stored in it. But do you really need to code a loop to do this?  Nope.  But I always forget how to correctly do it.  So here it is:

List< String > strings = new LinkedList< String >();
strings.add("one");
strings.add("two");
strings.add("three");

System.out.printf(
 "List< String >.toString()\n%s\n\n"
 ,strings.toString());
System.out.printf(
 "List< String >.toArray().toString()\n%s\n\n"
 ,strings.toArray().toString());
System.out.printf(
 "Arrays.toString(List< String >.toArray())\n%s\n\n"
 ,Arrays.toString(strings.toArray()));

The output looks like this:
List< String >.toString()
[one, two, three]

List< String >.toArray().toString()
[Ljava.lang.Object;@1ea87e7b

Arrays.toString(List< String >.toArray())
[one, two, three] 

Enjoy!


Monday, November 24, 2014

Beans Validation java.lang.ClassNotFoundException: com.sun.el.ExpressionFactoryImpl

If you are using the Beans Validation framework (JSR 349), you may encounter this obscure exception when doing your validation.

java.lang.ExceptionInInitializerError
Caused by: javax.el.ELException: Provider com.sun.el.ExpressionFactoryImpl not found
Caused by: java.lang.ClassNotFoundException: com.sun.el.ExpressionFactoryImpl

This exception is caused by a missing key lookup in the ValidationMessages.properties file.  Make sure you have the the key in the properties file.

Enjoy!

Monday, November 17, 2014

DOS equivalent of Unix/Linux alias

The Unix/Linux alias command is great. But now you are stuck in a DOS environment. What do you do?  Use doskey!

The doskey command can be used in a DOS environment to simulate the kinds of things which alias does.  Here is an example from my alias.bat file:

doskey cdhome=cd c:\Users\michael

doskey tw=cd C:\Users\michael\workspace\ferris-tweial\ferris-tweial\ferris-tweial-app\target\unziped\ferris-tweial-app-1.0.0.0-SNAPSHOT

doskey twr=c:\Applications\java\jdk1.7.0_11\bin\java.exe -jar ferris-tweial-app-1.0.0.0-SNAPSHOT.jar 

As you can see, doskey is very similar to alias.  When on a DOS prompt, all you need to do is type tw or twr and that command will be executed. Of course make your own doskey values.

All of my doskey commands are in an alias.bat file.  This means anytime you open a new DOS prompt you need to execute alias.bat to load all the doskey command. Unacceptable! Instead, create a shortcut for either your desktop or toolbar and you edit the shortcut to execute the alias.bat file for you.  The shortcut will look something like this.

cmd.exe /K "c:\Users\Michael\alias.bat"

That's it.

Enjoy!


Thursday, November 13, 2014

Remember PreparedStatement?

Simple example using PreparedStatement

Miss the good ole' days when interacting with the database was simple, easy to understand SQL statements and a few lines of code?

Select
public static void main(String[] args) throws Exception {
    String driver = "org.apache.derby.jdbc.EmbeddedDriver";
    
    String dbLocation 
        = String.format("./db/Sample");
    
    String connectionUrl =
        String.format("jdbc:derby:%s;create=true;user=sample;password=elpmas",dbLocation);
    
    Class.forName(driver);
    Connection conn = DriverManager.getConnection(connectionUrl);
    StringBuilder sp = new StringBuilder();
    sp.append("select \n");
    sp.append("    integer_value \n");
    sp.append("  , decimal_value \n");
    sp.append("  , varchar_value \n");
    sp.append("  , timestamp_value \n");
    sp.append("from example \n");
    PreparedStatement stmt = conn.prepareStatement(sp.toString());
    
    ResultSet rs = stmt.executeQuery();
    System.out.printf("ResultSet\n");
    while (rs.next()) {
     int i = rs.getInt(1);
     BigDecimal bd = rs.getBigDecimal(2);
     String s = rs.getString(3);
     Timestamp ts = rs.getTimestamp(4);
     
     System.out.printf("%d\t%f\t%s\t%s\n",i,bd,s, ts.toString());
    }

    conn.commit();
    conn.close();        
    System.out.printf("Goodbye\n");
}

Insert
public static void main(String[] args) throws Exception {
    String driver = "org.apache.derby.jdbc.EmbeddedDriver";
    
    String dbLocation 
        = String.format("./db/Sample");
    
    String connectionUrl =
        String.format("jdbc:derby:%s;create=true;user=sample;password=elpmas",dbLocation);
    
    Class.forName(driver);
    Connection conn = DriverManager.getConnection(connectionUrl);
    StringBuilder sp = new StringBuilder();
    sp.append("insert into example ( \n");
    sp.append("    integer_value \n");
    sp.append("  , decimal_value \n");
    sp.append("  , varchar_value \n");
    sp.append("  , timestamp_value \n");
    sp.append(" ) values ( \n");
    sp.append("    ? \n");
    sp.append("  , ? \n");
    sp.append("  , ? \n");
    sp.append("  , ? \n");
    sp.append(" ) \n");
    PreparedStatement stmt = conn.prepareStatement(sp.toString());
    stmt.setInt(1, 19);
    stmt.setBigDecimal(2, new BigDecimal("100.45"));
    stmt.setString(3, "Hello");        
    stmt.setTimestamp(4, new Timestamp(System.currentTimeMillis()));
    
    int cnt = stmt.executeUpdate();
    
    System.out.printf("count = %d\n", cnt);

    conn.commit();
    conn.close();        
    System.out.printf("Goodbye\n");
}

Enjoy!

Saturday, November 8, 2014

SSL JNDI Realm for Tomcat Catalina

Using JNDI as an authentication realm for Tomcat is quite common. What's also quite common is communication with the server needs to happen over SSL. In production, certificates are not a problem. In non-production (and especially development) environments, expired, self-signed, and untrusted SSL certificates are the norm. This project is an JNDI Realm for Tomcat Catalina which is designed to accept any SSL certificate, basically bypassing all security provided by certificates. So only use in development environments.


end

Friday, November 7, 2014

Servlet Info WebApp

Ferris Servlet Info WebApp is a simple servlet which dumps a bunch of info about the request, session, init-params, and server machine to the page for troubleshooting purposes.  It also includes an AJAX call back to the server which can be started and stopped with the "Start" and "Stop" buttons and how many seconds between AJAX calls is determined by the number in the input text box.  When the AJAX response is received, the data on the page is replaced by whatever the server sent back.  This WebApp is especially helpful troubleshooting clustered environments.

Clone the Mavenized project from GitHub (https://github.com/mjremijan/ferris-servletinfo). 

Here is what the information on the page looks like (IP address information has been blacked out)



Saturday, October 25, 2014

Mocking return values of static methods..config for Maven, JUnit, PowerMock, EasyMock, and Mockito

Abstract
I recently was working on code improvement and refactoring driven by unit testing when I came across the need to mock a Java static public method.  This is something I had never done before, but given the emphasis on testing these days, how hard could it be?  Well it took a number of hours to get working. Why so long? All examples I found showed the code but that is only 1/2 of what you need.  The other half, which is even more important, are the Maven dependencies. The purpose of this article is to show a simple code example of mocking a Java public static method and the Maven dependencies you need to get it all working.

System Requirements
The code was developed and run using the following system setup. If yours is different, it may work but no guarantees.
  • JDK 1.7.0_65
  • NetBeans 8.0.1
  • Maven 3.0.5 (bundled with NetBeans)
The rest of the software dependencies can be found in this article.

Maven POM dependencies
Listing 1 shows the Maven POM dependencies needed to run he unit test listed below.  From my research, these are the only dependencies you need.  NOTE that there is NO JUnit dependency and there is NO Mockito direct dependency. These are pulled in as transitive dependencies.  If you do have them as direct dependencies, most likely you'll get at version mismatch and the unit tests will fail to run. 

Listing 1: Maven POM dependencies
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>1.5.6</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-easymock</artifactId>
    <version>1.5.6</version>
    <scope>test</scope>
</dependency>       
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito</artifactId>
    <version>1.5.6</version>
    <scope>test</scope>
</dependency>        
<dependency>
    <groupId>org.easymock</groupId>
    <artifactId>easymock</artifactId>
    <version>3.2</version>
    <scope>test</scope>
</dependency>

Class with a static method
Listing 2 shows the Java source code for a very simple class with a static method.  The goal is to mock this method.  Although this method is harmless and would not cause any problems in a unit test, most uses of static methods follow the builder design pattern and hence are responsible for constructing complex objects. In more real-world examples, the mock of the static method is needed to avoid the construction of the real object and instead return another mock object provided by the unit test. 

Listing 2: Java HelloStatic class
/**
 * @author Michael Remijan mjremijan@yahoo.com @mjremijan
 */
public class HelloStatic {
    public static String getHello() {
        return "Hello";
    }
}

Class using a static method
Listing 3 shows the Java source code for a very simple class which uses a static method.  Again the goal is to mock the static method call to return what we want. 

Listing 3: Java GreetingInstance class
/**
 * @author Michael Remijan mjremijan@yahoo.com @mjremijan
 */
public class GreetingInstance {    
    public String getGreeting(String name) {
        return String.format(
            "%s, %s"
          , HelloStatic.getHello(), name);
    }
} 

Mock the static method in a unit test
Listing 4 shows the Java source code for a very simple unit test which accomplishes the goal of mocking the static method so the unit test can control what the static method returns for asserting purposes. 

When mocking a static method, you are going to be using a combination of PowerMock, EasyMock, and JUnit.  Your unit test class may have other test methods testing other things with Mockito, so there is a lot of technology going on here.  For sanity's sake, avoid using static imports! Static imports are a great convenience, but when mixing so many different technologies it get very hard to keep straight which methods are coming from which classes.

Listing 4: Java GreetingInstanceTest class
/**
 * @author Michael Remijan mjremijan@yahoo.com @mjremijan
 */
@RunWith(PowerMockRunner.class) 
@PrepareForTest(HelloStatic.class)
public class GreetingInstanceTest {
    
    @Test
    public void echo() 
    {
        String shrubbery = "Shrubbery";
        String expected = "Shrubbery, Rita Red";
        String actual = null;
        
        PowerMock.mockStatic(HelloStatic.class);
        EasyMock.expect(HelloStatic.getHello()).andReturn(shrubbery);
        PowerMock.replay(HelloStatic.class);
        {
            actual = new GreetingInstance().getGreeting("Rita Red");
        }       
        PowerMock.verify(HelloStatic.class);
        Assert.assertEquals(expected, actual);
    }    
} 

Let's take a look at this code in a bit more detail.

#4 @RunWith
We need to run the test with the PowerMockRunner, not the normal JUnit runner.

#5 @PrepareForTest
We need to prepare the class with the static methods before running the unit test

#15 PowerMock.mockStatic(. . .)
Use PowerMock to mock the static methods.

#16 EasyMock.expect(. . .)
Use EasyMock to change what the static method returns.

#17 PowerMock.replay(. . .)
This changes the PowerMock mode to replay, which is the mode PowerMock needs to be in in order to run tests.

#19 actual = . . .
Run you test!  The static method should be mocked and return what you set it to return on line #16.

#21 PowerMock.verify(. . .)
This changes the PowerMock mode to verify, which is the mode PowerMock needs to be in in order to verify tests.

#22 Assert.equals(. . .)
Make sure the actual matches the expected where the expected is constructed by mocking the static method to return a different value.

Conclusion
That's it.  Quick, easy, and to the point.

References
johan.ha...@gmail.com. (2010 February 4). MockStatic. Retrieved October 2014, from https://code.google.com/p/powermock/wiki/MockStatic

sachin grover. (2013, June 25). PowerMock:: [java.lang.IllegalStateException: no last call on a mock available]. Retrieved October 2014, from http://stackoverflow.com/questions/17293780/powermock-java-lang-illegalstateexception-no-last-call-on-a-mock-available

end

Tuesday, September 16, 2014

2014 JavaOne Sessions in Day and Time order

I noticed when you click the "Get More Results" link at the bottom at the bottom of the session page you will get sessions for that day however they will be out of order (assuming order time). If you try to sort the list by time again you loose the extra results.  So here is a spreadsheet of all the 2014 JavaOne sessions. Each day has its own tab.  Sessions are sorted by time.

2014JavaOneSessions.xlsx

end

Wednesday, September 3, 2014

Which is faster? Remote EJBs versus Other EE Technologies

Abstract
Following good multi-tier architecture, most applications will have at least two tiers.  With two tiers the presentation- and business-code reside on the first tier and the second tier is typically the database. Sometimes, applications go with more than two tiers. When this happens, figure 1 (Multitier architecture, 2001) shows how the presentation- and business-tiers are separated and stand on their own. 

Figure 1: Multitier architecture 
"Overview of a three-tier application vectorVersion" by Bartledan (talk), based on a file by User:Foofy. Original uploader was Bartledan at en.wikipedia - Transferred from en.wikipedia; transfer was stated to be made by User:Sliwers.(Original text : I created this work based on en:File:Overview_of_a_three-tier_application.png). Licensed under Public domain via Wikimedia Commons.

Once you move to this three (or more) tier architecture you must ask yourself, how will the presentation- and business-tiers communicate with each other?  Java EE has a number of options including:
  1. Remote EJB
    • Return serialized object
  2. Servlet
    • Return serialized object
  3. JAX-RS (REST Service)
    • Return JSON/Text
  4. JAX-WS (Web Service)
    • Return SOAP/XML
All of these technologies have their strengths and weaknesses, but typically the most common question is "Which is fastest?"  After all, by adding another tier you are also adding significant communication overhead getting data displayed to your users. Minimizing this overhead is usually the highest priority.

Having recently finished co-authoring EJB 3 In Action Second Edition and Presenting at JavaOne on EJB Best Practices, I am biased toward EJB technology. Naturally I assume it is the fastest technology for communicating between presentation- and business-tiers.  The purpose of this article is present my results of a experiment I designed which put these four technologies up against each other to see which one would win the race.  If you are just interested in the results, jump down to the Results section.

Authors

The experiment and results described in this article are the result of work from two people.

Michael Remijan
Java EE Architect, developer, researcher, evangelist. Author, writer, instructor.
LinkedIn, Twitter, Tumbler

Timothy Taylor
Java developer, architect.
LinkedIn

System Requirements
The code was developed and run using the following system setup. If yours is different, it may work but no guarantees.

Development Environment
  • JDK 1.7.0_65
  • NetBeans 8.0
  • Maven 3.0.5 (bundled with NetBeans)
  • Glassfish 4.0
The software dependencies can be found in the project's pom.xml

Presentation-tier Server
  • Dell Inspiron 15 7000 Series
  • Windows 8.1
  • Intel(R) Core(TM) i7-4500U CPU @ 1.80GHz 
  • 16.0 GB RAM
  • 64-bit
  • Intel(R) Wireless-N 7260
Business-tier Server
  • MSI Computer Corp GT70 0ND-444US
  • Windows 8.1 Pro with Media Center
  • Intel(R) Core(TM) i7-3630QM CPU @ 2.40GHz
  • 12.0 GB RAM
  • 64-Bit 
  • Intel(R) Centrino(R) Wireless-N 2230
Network
  • Netgear Genie R6300v2
  • Channel: Auto
  • Mode: Up to 450 Mbps
  • Security: WPA2-PSK [AES]
  • 5GHz a/n/ac
Download Project
The project is on GitHub.
Project Structure
Let's start with an understanding of the projects in GitHub.

The top-level directory is /ejbrace.  This is a Maven parent POM project which references the modules underneath it.

The modules inside of /ejbrace are as follows:
  1. /ejbrace-business-ear
  2. /ejbrace-ejb
  3. /ejbrace-model
  4. /ejbrace-presentation-ear
  5. /ejbrace-service
  6. /ejbrace-web
The modules can be logically divided into the following.

Shared Code
  1. /ejbrace-model
    •  This is a basic shared library of the beans in your business model.

    Presentation-tier
    1. /ejbrace-web 
      • A Maven WAR project 
      • This is the WebApp used to perform the experiment

    2. /ejbrace-presentation-ear  
      • Maven EAR project
      • EAR is deployed on the presentation-tier.
      • EAR contains:
        • The WAR from /ejbrace-web
    Business-tier
    1.  /ejbrace-ejb
      • Maven EJB-JAR project
      • These are the remote EJBs for the experiment
    2.  /ejbrace-service
      • Maven WAR project
      • JAX-RS for the experiment
      • JAX-WS for the experiment  
      • Servlet for the experiment
    3.  /ejbrace-business-ear
      • Maven EAR project
      • EAR is deployed on the business-tier
      • EAR contains:
        • EJB-JAR from /ejbrace-ear
        • WAR from /ejbrace-service
    All the projects are Mavenized and all the dependencies are pulled from the Maven central repository so building everything should be very easy.  Running mvn on the /ejbrace Maven parent POM will take care of everything.  There are a few configurations which need to be made before running the applications. We will look at those configurations next.
    Configuration
    Before running the applications, there are a few source code and server configurations which need to be made. So let's take a look at them.

    Source Code
    The following files and classes in the /ejbrace-war project have hard-coded URL values and server names.  You you need to update these values for your environment before building and deploying the EAR to your presentation-tier.
    • org.ferris.ejbrace.web.servlet.CallToJaxRs
    • org.ferris.ejbrace.web.servlet.CallToJaxWs
    • org.ferris.ejbrace.web.servlet.CallToServlet
    • /WEB-INF/glassfish-web
    Once you have these URL values and server names updated, you can build the project.  Next let's take a look at configuring GlassFish on the presentation-tier so the /ejbrace-war WAR can actually run.

    Presentation-tier

    For the experiment, the servlets in the /ejbrace-war project repeatedly call the services deployed on the business-tier and maintain statistics of performance. The number for "repeatedly" is determined by a JNDI Custom Resource.  This resource is configured by the GlassFish administration console. Figure 2 shows how to to create the numberOfCalls JNDI Custom Resource. I wrote a previous blog on using JNDI Custom Resources which goes into more detail.

    Figure 2: The numberOfCalls JNDI Custom Resource


    The numberOfCalls JNDI Custom Resource is created with the information shown in figure 2 which consists of:
    • A: Go to "Resources/JNDI/Custom Resources" to add a new one
    • B: JNDI Name is numberOfCalls
    • C: Resource Type is java.lang.Integer
    • D: FactoryClass will default to org.glassfish.resources.custom.factory.PrimitivesAndStringFactory which is fine.
    • E: There should only be one property, with Name value
    • F: The value is any integer you want it to be.
    In figure 2, the numeric value is set to 2000 (F).  This means the servlet on the presentation-tier will call the service on the business-tier 2000 times in a row.  Statistics are collected for each call. When all 2000 calls are done, averages will be calculated and the results will be displayed.  We'll talk more about this in the Experiment section.

    Having numberOfCalls as a JNDI Custom Resource is nice because the value can be changed on the fly without having to rebuild and redeploy the code. Now that we've covered configuring the code and the presentation-tier, let's look at the final configuration of GlassFish on the business-tier.

    Business-tier
    Configuring GlassFish on the business-tier may be optional for you.  I found it was necessary for me because of some quirks in my home network. You may need to configure of the ORB IIOP listener on the business-tier.  IIOP is the commnication protocol for remote EJBs.  Figure 3 shows this optional configuration.

    Figure 3: ORB IIOP Listener

    • A: /Configuration/default-config/ORB/IIOP Listeners/orb-listener-1
    • B: Network Address is the IP address of the business-tier server.
    Again, this my not be necessary in your environment but it was in mine. The default Network Address value (B) is 0.0.0.0.  When it's 0.0.0.0, GlassFish somehow determines what IP address the ORB IIOP listener will listen on.  I discovered that for my home network, GlassFish determined a different IP address than what was actually assigned to my business-tier machine.  For example, the IP address of my business-tier machine was 192.168.1.4 (as determined by running ipconfig.exe) but GlassFish somehow determined the ORB IIOP listener should be listening on 192.168.1.14. As a result, remote EJB call from the presentation-tier would hang forever trying too communicate with the business-tier.  I solved this "hang forever" problem y specifically setting the Network Address value (B) of the ORB IIOP listener on the business-tier to the IP address assigned to the business-tier machine by my router.

    Now that we've looked at configuration of the code and configuration of both GlassFish instances, let's look at deployment next.

    Deployment
    Deployment should be pretty easy.  Just drop the EAR files and your done. . .well almost.  Let's take a look.

    Presentation-tier
    On the presentation-tier you deploy the EAR file generated by the /ejbrace-presentation-ear project. Using the GlassFish administration console, just select the EAR and deploy. No values need to be changed. The application.xml file will set the context root for the WAR. Once deployed, you will have the following on the presentation-tier.
    1. http://localhost:8080/ejbrace
      • /ejbrace-war WAR project  

    Business-tier
    On the business-tier you deploy the EAR file generated by the /ejbrace-business-ear project. Deploying to the business-tier is almost as easy as the presentation-tier, except for one small difference. When you use the GlassFish administration console to deploy you MUST remember to change the application name to ejbrace-business as shown in figure 4.

    Figure 4: Application name for /ejbrace-business-ear EAR file

    • A: Maven builds an EAR file named using artifact-id and version
    • B: Application name must be ejbrace-business
    You need to set the application name to ejbrace-business (B) because when GlassFish binds the EJBs to JNDI, it will do so using the following the portable JNDI naming standard.

    java:<namespace>/[app-name]/<module-name>/<bean-name>[!fully-qualified-interface-name]
    The value for [app-name] must be ejbrace-business because that is what the presentation-tier is expecting. I have not yet found a way to deploy an EAR with EJBs where the display name in the GlassFish administration console is the Maven file name (so you can easily see versions) but the application name is what I want it to be.  If you know how to do this, please answer this question.

    Once deployed, you will have the following on the business-tier.
    1. java:global/ejbrace-business/ejb/AccountServiceEjb!org.ferris.ejbrace.ejb.AccountService
      • /ejbrace-ejb EJB-JAR project
    2.  http://[business-server-name]:8080/ejbrace-service/AccountServiceServlet
      • Servlet returning Serialized object
      • /ejbrace-service WAR project
    3. http://[business-server-name]:8080/ejbrace-service/AccountServiceJaxWsService
      • JAX-WS returning SOAP/XML
      • /ejbrace-service WAR project
    4. http://[business-server-name]:8080/ejbrace-service/resources/AccountServiceJaxRs/Get
      • JAX-RS returning JSON/Text
      • /ejbrace-service WAR project
     Now that everything is deployed, let's run the experiment.

    Experiment
    The experiment is very simple.  

    First, the /ejbrace-model project builds a LinkedList<Account> object.  The list contains 55 Account objects.  All of the data in the Account objects are Strings and the values of all the Strings are generated by UUID. For this experiment the data itself isn't important just as long as all the data in the 55 Account objects are unique. The  LinkedList<Account> object is also static for the experiment. There is a bit of overhead to build the object model the first time but after that it quickly comes directly from memory.

    Second, the business-tier returns the LinkedList<Account> object using the following technologies: 
    1. The /ejbrace-ejb project contains a Remote EJB (AccountServiceEjb) which returns a serialized object over IIOP.
    2. The /ejbrace-service project contains a Servlet (AccountServiceServlet) which serializes the object to the HttpServletResponse OutputStream.
    3. The /ejbrace-service project contains a JAX-RS (AccountServiceJaxRs) which returns the object by @Produces(MediaType.APPLICATION_JSON).
    4. The /ejbrace-service project contains a JAX-WS (AccountServiceJaxWs) which returns the object by SOAP/XML.
    Third, the presentation-tier is a simple WebApp capable of calling each of the 4 business-tier services.  The numberOfCalls JNDI value tells the presentation-tier how many times to make the call to the business-tier during the experiment.  So let's take a look at the steps to run the experiments.

    Step 1: Set numberOfCalls value to 1
    Login to the GlassFish administration console on the presentation-tier.  Set the value for numberOfCalls to 1.

    The reason to set numberOfCalls to 1 is because we want to run all the tests at least one time so we get all of the code in memory and ready to run as fast as possible.

    Step 2: Browse to the WebApp on the presentation-tier
    Open a browser to the WebApp on the presentation-tier.  If you are running GlassFish with all its defaults, the WebApp is:
    http://[presentation-tier-server]:8080/ejbrace
    The welcome page for the WebApp is shown in figure 5.  It has hyperlinks for performing each experiment.

    Figure 5: Welcome page to run all the experiments


    Let's take a look at each experiment in more detail.

    Get account by remote EJB (Default transaction) 
    This experiment calls a Remote EJB method which has no @TransactionAttribute on it so it uses the application's servers default transaction.

    Get account by remote EJB (Transaction Never)
    This experiment calls a Remote EJB method which has @TransactionAttribute(TransactionAttributeType.NEVER) on it.

    Get account by remote EJB (Transaction Supports)
    This experiment calls a Remote EJB method which has @TransactionAttribute(TransactionAttributeType.SUPPORTS) on it.

    Get account by remote Servlet
    This experiment calls the Servlet at:
    http://[business-server-name]:8080/ejbrace-service/AccountServiceJaxWsService
    It uses Apache HttpClientBuilder to make the call.

    Get account by remote RESTful Web Service
    This experiment calls the JAX-RS RESTful Web Service at:
    http://[business-server-name]:8080/ejbrace-service/resources/AccountServiceJaxRs/Get.
    It uses the the JAX-RS Client to make the call.

    Get account by remote SOAP Web Service
    This experiment calls the JAX-WS SOAP Web Service at:
    http://[business-server-name]:8080/ejbrace-service/AccountServiceJaxWsService
    It uses an AccountServiceJaxWsService object generated by the WSDL to make the call.

    Get account by LOCAL EJB
    Just for fun, this calls a local version of the Remote EJB.

    Step 3: Prepare each experiment
    Click through each of the hyperlinks and run each experiment.  Because numberOfCalls is set to 1, each experiment should be very quick. This gets everything into memory.  When you are done you are ready to run the experiments and get real results.

    Step 4: Set numberOfCalls value to 2000
    Go back to the GlassFish administration console on the presentation-tier.  Set the value for numberOfCalls to 2000.  You can use whatever number you want but I ran all my experiments making 2000 calls.

    Step 5: Run each experiment
    Click through each of the hyperlinks and run each experiment.  Because numberOfCalls is set to 2000, each experiment will now take a while.  Of course which is the fastest?  We'll find out!

    Results
    When an experiment completes its 2000 loops, the results are displayed as in figure 6.

    Figure 6: Results of an experiment

    • A: Statistics of the experiment. For this run the business-tier service was called 2000 times and it took a total of 156,655ms to make all 2000 calls
    • B: List<Account> of size 55 was returned by the business-tier service.
    • C: Print of the first Account from the List<Account>. 
    I copied the results (A) into Excel and re-ran the experiment.  I ran each experiment 10 times and used Excel to average all 10 runs and draw some pretty graphs.
    Download Excel Results
    A summary of the results of all the experiments shown in Graph 1.

    Graph 1: Graph of all runs of all the experiments

    From this graph, we can rank the results.  From fastest to slowest we have:
    1. Servlet
    2. JAX-RS
    3. Remote EJB
    4. JAX-WS

    So of the 4 technologies on the business-tier - according to this experiment - it looks like a plain old Servlet returning a serialized object is the fastest!

    Conclusion
    So the results of the experiment show a Servlet returning a serialized object is the fastest whencompared with a Remote EJB returning a serialized object, JAX-RS returning JSON/Text, and JAX-WS returning SOAP/XML.

    Does this mean we should be updating all our projects and using nothing but Servlets returning serialized objects from now on?  Well, no not so much.  Each technology exists for a reason and they all have their uses and are appropriate solutions for the roles they play. But if speed is your goal, then it looks like your business-tier should be basic Servlets returning Serialized objects.

    Caveat
    Any experiment like this will naturally result a lot of what-if conversation. What if the tiers were Linux instead of Windows? What if you used JBoss instead of GlassFish. What if it was a wired network not wireless? I'm sure you can think of more. If so please download the source code, set up your own experiment, and let me know the results. 

    References
    Jendrock, Cervera- Navarro, Evans, Haase, Markito. (2014, May). Java EE 7 Tutorial. Retrieved August 2014, from http://docs.oracle.com/javaee/7/tutorial/doc/javaeetutorial7.pdf

    dwuysan. (2012, December 6). Starting with JAX-RS: Configuring javax.ws.rs.ApplicationPath. Retrieved July 2014, from http://dwuysan.wordpress.com/2012/12/06/starting-with-jax-rs-configuring-javax-ws-rs-applicationpath/

    Kops, Micha. (2013, December 30). JAX-RS 2.0 REST Client Features by Example. Retrieved August 2014, from http://www.hascode.com/2013/12/jax-rs-2-0-rest-client-features-by-example/

    Marthin. (2013, August 31). deploy REST services on glassfish 4. Retrieved August 2014, from http://stackoverflow.com/questions/18548983/deploy-rest-services-on-glassfish-4

    Multitier architecture. (2001, September 25). In Wikipedia. Retrieved September 3, 2014, from http://en.wikipedia.org/w/index.php?title=Multitier_architecture&oldid=621927321


    end