It is important to invoke the methods of a remote EJB in an efficient manner. This recipe illustrates how to return data from a remote EJB using a coarse-grained approach. This is then contrasted with a fine-grained approach to accessing the elements of an EJB which is less efficient.
The position of a satellite in orbit can be specified using a set of six orbital parameters. For the interested reader, a good discussion of these parameters is found in the Wikipedia article at http://en.wikipedia.org/wiki/Orbital_elements. We will create the class PositionBean
to hold these parameters. We will also use an OrbitalElements
EJB to return an instance of the PositionBean
using a remote interface. A client can directly access the PositionBean
in a fine-grained manner or access the PositionBean
from the OrbitalElements
bean in a coarse-grained manner.
This technique is about how to organize your code. You can return information as a single object or you provide methods to return individual elements one at a time. Either approach is valid. However, the latter approach will not be as efficient.
The approach illustrated here uses an interface to define methods to access elements of an object. The object is returned as a single object and its methods permit access to the information of interest.
Let's begin by creating a Java Web application called ParameterExample
. Add a packt
package with the following EJBs and interfaces:
OrbitalElements
A singleton EJBOrbitalElementsRemote
An interfacePositionBean
A stateless EJBPositionBeanRemote
An interfaceAlso create a second package called servlet
and add a servlet called PositionServlet
.
Beginning with the PositionBeanRemote
interface, this simple interface has only get type methods.
package packt; public interface PositionBeanRemote { public double getArgumentOfPeriapsis(); public double getEccentricity(); public double getInclination(); public double getLongitudeOfTheAscendingNode(); public double getMeanAnomaly(); public double getSemimajorAxis(); }
Next, the PositionBean
implements the remote interface methods and in this example only initializes the eccentricity instance variable. In a more sophisticated version of the application, other fields of the PositionBean
would be initialized.
@Stateless @Remote @Startup public class PositionBean implements PositionBeanRemote{ private double eccentricity; private double semimajorAxis; private double inclination; private double longitudeOfTheAscendingNode; private double argumentOfPeriapsis; private double meanAnomaly; //@PostConstruct public PositionBean() { eccentricity = 1.0; } public double getArgumentOfPeriapsis() { return argumentOfPeriapsis; } public double getEccentricity() { System.out.println("--- Return eccentricity"); return eccentricity; } public double getInclination() { return inclination; } public double getLongitudeOfTheAscendingNode() { return longitudeOfTheAscendingNode; } public double getMeanAnomaly() { return meanAnomaly; } public double getSemimajorAxis() { return semimajorAxis; } }
To illustrate the use of the PositionBean
the PostionServlet
declares an instance of the bean and uses the getEccentricity
method. This technique illustrates a fine-grained approach.
public class PositionServlet extends HttpServlet { @EJB PositionBeanRemote position; protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); try { out.println("<html>"); out.println("<head>"); out.println("<title>Servlet PositionServlet</title>"); out.println("</head>"); out.println("<body>"); out.println("<h3>Eccentricity: " + position.getEccentricity() + "</h3>"); out.println("</body>"); out.println("</html>"); } finally { out.close(); } } }
The OrbitalElements
EJB implements the OrbitalElementsRemote
interface with a single method, getPosition
, returning a PositionBean
. This technique illustrates a coarse-grained approach.
@Remote public interface OrbitalElementsRemote { public PositionBean getPosition(); }
The OrbitalElements
EJB creates an instance of the PositionBean
and then returns the bean. This example did not provide a means of initializing the PositionBean
to unique values or perhaps treating the bean as a singleton. Its actual type and creation will depend on the needs of the application.
@Singleton public class OrbitalElements implements OrbitalElementsRemote { public PositionBean getPosition() { return new PositionBean(); } }
In the PostionServlet
declare a reference to the OrbitalElementsRemote
interface and use the getPosition
method to return an instance of the PositionBean
.
public class PositionServlet extends HttpServlet { @EJB PositionBeanRemote position; @EJB OrbitalElementsRemote orbitalElements; protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); try { out.println("<html>"); out.println("<head>"); out.println("<title>Servlet PositionServlet</title>"); out.println("</head>"); out.println("<body>"); out.println("<h3>Eccentricity: " + position.getEccentricity() + "</h3>"); out.println("<h3>Eccentricity: " + orbitalElements.getPosition().getEccentricity() + "</h3>"); out.println("</body>"); out.println("</html>"); } finally { out.close(); } }
Execute the servlet using the URL shown in the following screenshot:
Notice the creation of the PositionBean
using the new
keyword in the OrbitalElements
EJB. This illustrates an easily made potential problem. The object created is not managed by the EJB container. As a result, the benefits of an EJB such as security and transaction management are not supported. This may not be a problem depending on the intended use of the object. Use dependency injection if the object needs to be managed by the EJB container.
Local beans execute in the same JVM as the client. This type of access is typically faster than using remote access which occurs when the client is in a different JVM. There is less communication overhead required to execute a method and to pass parameters. However, there are times when it is necessary to access an EJB in a remote fashion. Be aware that some servers are able to optimize such access and avoid the overhead costs.
Consider a class with several private instance variables. If individual calls are made to access each variable one at a time, then this requires repeated method invocations. This type of access is referred to as fine-grained access.
In contrast, when the entire object is passed, only a single remote method invocation is needed. This is called coarse-grained access. It will still be necessary to invoke the individual methods, but these are local to the client. Fine-grained access becomes more of a problem when the client resides on a different JVM.
One coarse-grained remote procedure call followed by multiple "local" method calls in the client is more efficient than multiple fine-grained remote procedure calls. If it is necessary to modify the original object, then fine-grained access for the setter type methods is required along with its performance penalties.
When passing or returning an object in a different JVM, the object is passed by value. That is, a copy of the object is passed to the client. Should the client attempt to modify the object, only the copy of the object is modified. The original object is not touched.
When passing an object by value it is a good idea to pass an immutable object so as to make it clear that it cannot be modified. The creation of an immutable object means at minimum the class should not have setter type methods.
13.59.107.152