| Contents | Index |
| On this page… |
|---|
Integrating MATLAB Code on the Web Using Java Servlets Optimizing Performance of Servlets That Call Your MATLAB Web Code |
Web processing take place on some combination of a client, running a Web browser (such as Microsoft®Internet Explorer® or Mozilla® Firefox®) and a Web server. HTTP (Hypertext Transfer Protocol) is a simple, synchronous protocol—a client connecting to a server, sending a single command, then waiting for a response from the server.
In the most basic scenario, the URL specifies the exact document to be read. A browser using HTTP retrieves the document for display. Most Web applications, however, deal extensively with dynamic, interactive content.
Typically, Web processing is made up of the following workflow:
The user enters a URL request, either manually or via a search engine, in the browser.
The browser parses the URL into two parts: one specifying the server and one specifying a document on the server to be retrieved.
For example, the URL http://www.mathworks.com/product-list.html indicates the product-list HTML document on the MathWorks server.
A browser using HTTP retrieves the document from the server. After the data is downloaded into the browser, it is parsed and rendered. The document may refer to other documents (via hyperlinked URLs) which are similarly processed until the full Web page is rendered.
A Java servlet is an object that resides on the server. When a servlet is first placed on a Web server, it is assigned patterns of URLs which it can process.
The servlet has a method on it, called doGet. doGet is invoked when a client issues the get command for any document matching the pattern assigned to a particular servlet. The get command is one of the most common in the HTTP protocol: it initiates the reading of a document.
One of the simplest ways to integrate MATLAB code in a Web context is to write a Java servlet, and in its doGet method, make calls against an object built by MATLAB Builder JA.
The doGet command is passed two objects: one that represents the request and one that represents the response. doGet must analyze the request object for what is needed and use the response object to send back the document it creates to the browser:
Integrate your MATLAB code as follows:
Override the default doGet method provided by the servlet class. For example, class MyServlet extends HttpServlet (part of the Java Servlets API). In the doGet method of MyServlet, you make calls to a deployed component.
The Magic Square Example illustrates how to instantiate the MagicDemoJavaApp component inside doGet (taking care to call the dispose method to release native resources).
Write code to respond to the client request. At minimum, you must at least set the content type (HTML, for example).
Write your data to a virtual file that is either being buffered or being sent directly to the client via socket.
The stream output commands in your servlet include the output from calling the MATLAB function on your component. For example, you might use the MWArray toString method to convert your MWArrays to strings or another type appropriate to your application.
Much of the code in this chapter is based on building a Java component using the Magic Square example in the MATLAB Builder JA User's Guide.
Before attempting the examples in this chapter, it is advisable to familiarize yourself with The Magic Square Example in the Getting Started chapter of the MATLAB Builder JA User's Guide.
Under some circumstances, you can achieve desired end result faster and more seamlessly by using JavaServer Pages (JSP). JSP is a server side Java technology that allows software developers to create dynamically generated web pages, with HTML, XML, or other document types, in response to a Web client request to a Java Web Application container (server).
For an example of how to use JSP pages to dynamically render WebFigures, see Creating a WebFigure on a JSP Page and Creating an End-to-End Web Application in this Example Guide, and Quick Start: Implementing a Custom WebFigure in the User's Guide.
import com.mathworks.toolbox.javabuilder.MWException;
import com.mathworks.toolbox.javabuilder.MWArray;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import java.io.IOException;
import java.io.PrintStream;
import magicsquare.magic;
/**
* A simple servlet to call MATLAB code.
*/
public class MyServlet extends HttpServlet
{
@Override
protected void doGet(final HttpServletRequest request,
final HttpServletResponse response)
throws ServletException, IOException
{
try {
final magic m = new magic();
try {
final Object[] results = m.makesqr(1, (int)(Math.random()
* 7 + 3));
try {
final MWArray firstResult = (MWArray)results[0];
final double[][] square = (double[][])firstResult.toArray();
response.setContentType("text/html");
final PrintStream page =
new PrintStream(response.getOutputStream());
page.println("<html>");
page.println("<head>");
page.println(" <title>Magic Square Web App</title>");
page.println("</head>");
page.println("<body>");
page.println("A magic square of size " + square.length);
page.println("<table border='1' cellpadding='4'>");
for (double[] row : square) {
page.println("<tr>");
for (double column : row) {
page.println("<td>" + column + "</td>");
}
page.println("</tr>");
}
page.println("</table>");
page.println("</body>");
page.println("</html>");
} finally {
MWArray.disposeArray(results);
}
} finally {
m.dispose();
}
} catch (MWException e) {
throw new ServletException(e);
}
}
}doGet is invoked every time a get command is received on the server. Thus, every time a get command is received,MagicDemo is instantiated along with its dispose method.
This can quickly impact performance, as it takes time to create an MCR instance. You can, however, take measures to improve the performance of your code.
Moving the ownership of the component from the doGet method into the servlet, so it doesn't have to be created and destroyed repeatedly, is a start.
HTTPServlet has a set of methods called init and destroy. The servlet automatically calls these methods when the servlet is created and destroyed.
To take advantage of these methods, you match the scope of MagicDemoJavaApp to the scope of the servlet. This renders the lifetime of the deployed component and its MCR instance as the same as the lifetime of the servlet. From the first time a user requests a document that matches the pattern assigned to the servlet, until the time the servlet is terminated by an administrator, the servlet remains available.
Add a property on MyServlet of type magic and instantiate.
Overload the init method (where you create your servlet).
Overload the destroy method (where you issue dispose).
Verify your doGet method in your servlet is reentrant—meaning that it can be entered simultaneously on multiple threads and processed in a thread-safe manner.
Note A Web server that uses servlets to process requests can be termed a servlet container. The servlet container manages every object scoped to its class. In this case, the container manages the lifetime of servlets by calling init and destroy for you. You specify to the container how you want init and destroy to be executed. |
public class MyServlet extends HttpServlet
{
private magic m;
@Override
public void init(ServletConfig servletConfig) throws ServletException {
try {
m = new magic();
} catch (MWException e) {
throw new ServletException(e);
}
}
@Override
protected void doGet(final HttpServletRequest request,
final HttpServletResponse response)
throws ServletException, IOException
{
try {
final Object[] results = m.makesqr(1, (int)(Math.random() * 7 + 3));
try {
final MWArray firstResult = (MWArray)results[0];
final double[][] square = (double[][])firstResult.toArray();
response.setContentType("text/html");
final PrintStream page =
new PrintStream(response.getOutputStream());
page.println("<html>");
page.println("<head>");
page.println(" <title>Magic Square Web App</title>");
page.println("</head>");
page.println("<body>");
page.println("A magic square of size " + square.length);
page.println("<table border='1' cellpadding='4'>");
for (double[] row : square) {
page.println("<tr>");
for (double column : row) {
page.println("<td>" + column + "</td>");
}
page.println("</tr>");
}
page.println("</table>");
page.println("</body>");
page.println("</html>");
} finally {
MWArray.disposeArray(results);
}
} catch (MWException e) {
throw new ServletException(e);
}
}
@Override
public void destroy() {
m.dispose();
}
}When working with servlets, you must be extremely aware of the role scoping plays in placement of your data.
A scope is a binding of variable to value. In the same scope, a certain name always refers to a particular binding value.
Every method call generates its own scope. Local variables belong to the scope of the method invocation.
There are several degrees of scope provided by the Java language:
Static scope — Bound to the class itself
Instance scope — Bound to an instance of the class
Method scope — Bound to local variables tied to a specific method invocation
When you refer to a variable, the default behavior of the Java compiler is to first interpret that variable in terms of its most local scope. For example, in MyOtherServlet.java, note how variables are determined within the scopes designated by each set of curly braces.
In this example, notice that state which is particular to an individual request is scoped to the doGet method itself, rather than the servlet.
To ensure processing is thread-safe, avoid storing data related to state variables as instance variables on the class itself. Defining too many instance fields in the class allows state variables to be shared by all threads that call doGet on the same servlet instance. Instead, scope at the method level, using method parameters, rather than at the class level. This scoping at the method level also ensures your application scales easily as more servers are added.
As discussed in Optimizing Performance of Servlets That Call Your MATLAB Web Code, MyServlet takes a request and generates an HTML document calling MagicDemoJavaApp. This call generates a formatted response. However, you may want a different formatted response or you may want to call MagicDemoJavaApp with another method to achieve a different result. To do this, you write myOtherServlet.
Begin by using the code from MyServlet as a template for myOtherServlet. This time, however, you install myOtherServlet in the servlet container by mapping it to another set of URLs.
Clients periodically do GETs on various URL patterns mapped to each servlet. While this works well, you can make the process more efficient—note that you are duplicating work by using two copies of MagicDemoJavaApp.
Because each of the servlets gets their init method called separately, each of these methods initializes a separate MCR instance.
public class MyOtherServlet extends HttpServlet
{
private magic m;
@Override
public void init(ServletConfig servletConfig) throws ServletException {
try {
m = new magic();
} catch (MWException e) {
throw new ServletException(e);
}
}
@Override
protected void doGet(final HttpServletRequest request,
final HttpServletResponse response)
throws ServletException, IOException
{
try {
final Object[] results = m.makesqr(1, (int)(Math.random()
* 10 + 11));
try {
final MWArray firstResult = (MWArray)results[0];
response.setContentType("text/html");
{
final double[][] square = (double[][])firstResult.toArray();
{
final PrintStream page =
new PrintStream(response.getOutputStream());
page.println("<html>");
page.println("<head>");
page.println("
<title>Magic Square Web App (Other)</title>");
page.println("</head>");
page.println("<body>");
page.println("A magic square of size " + square.length);
page.println("<table border='1' cellpadding='4'>");
{
for (double[] row : square) {
page.println("<tr>");
for (double column : row) {
page.println("<td>" + column + "</td>");
}
page.println("</tr>");
}
}
page.println("</table>");
page.println("</body>");
page.println("</html>");
}
}
} finally {
MWArray.disposeArray(results);
}
} catch (MWException e) {
throw new ServletException(e);
}
}
@Override
public void destroy() {
m.dispose();
}
}Context scopes provided by the servlet container can supply convenient solutions to performance problems such as those described in Context Scoping with Servlets.
Scopes including multiple servlets are called servlet contexts. Using a servlet context, you make the component a shared resource and improve performance substantially.
Obtain the servlet context by calling getServletContext .
After you obtain the servlet context, get an attribute (in this case, variables bound to the servlet context) on the context.
The following logic (shown in bold type) added to each servlet (MyServlet.java and MyServletContextListener.java), creates a shared MagicDemoInstance:
MyServletContextListener.java.
import magicsquare.magic;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContext;
import com.mathworks.toolbox.javabuilder.MWException;
public class MyServletContextListener implements ServletContextListener {
static final String SHARED_MAGIC_INSTANCE = "SharedMagicInstance";
public void contextInitialized(final ServletContextEvent event) {
final ServletContext context = event.getServletContext();
try {
final magic m = new magic();
context.setAttribute(SHARED_MAGIC_INSTANCE, m);
} catch (MWException e) {
context.log("Error creating magicsquare.magic", e);
}
}
public void contextDestroyed(final ServletContextEvent event) {
final ServletContext context = event.getServletContext();
final magic m = (magic)context.getAttribute(SHARED_MAGIC_INSTANCE);
m.dispose();
}
}Code Excerpt from MyServlet.java.
@Override
protected void doGet(final HttpServletRequest request,
final HttpServletResponse response)
throws ServletException, IOException
{
final HttpSession session = request.getSession();
final ServletContext context = session.getServletContext();
final magic m =
(magic)context.getAttribute
(MyServletContextListener.SHARED_MAGIC_INSTANCE);A Java session is defined as a lasting connection between a user (or user agent) and a peer, typically a server, usually involving the exchange of many packets between the user's computer and the server.
The servlet container provides a scope that corresponds to a session between a particular client and a server. Since HTTP is a very lightweight protocol and carries no notion of persistence, it follows that session scoping is particularly useful in retaining data or state particular to a client. If you have state that needs to persist across requests, the proper context is the Session.
Single instances of a servlet may be used for many clients throughout its lifetime. Thus, init and destroy have no knowledge of the session context. However, HTTP request and response objects do, since request and response happen within the context of a session between a client and server.
You usually get the HTTPSession object from the request.
Session has an API with similar methods to servlet context—setAttribute, getAttribute, removeAtrribute, and so on. They bind variables that last for the relationship between a specific client with browser and server.
Sessions usually have time-outs, so they automatically clean up in case the client doesn't explicitly log off. This is configurable on the HTTPSession object itself or somewhere in the servlet API.
The following logic (shown in bold type) added to both MyHttpSessionListener.java and MyServer.java creates your MATLAB component at the session scope.
import magicsquare.magic;
import javax.servlet.http.HttpSessionListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import com.mathworks.toolbox.javabuilder.MWException;
public class MyHttpSessionListener implements HttpSessionListener {
static final String SHARED_MAGIC_INSTANCE = "SharedMagicInstance";
public void sessionCreated(final HttpSessionEvent event) {
final HttpSession session = event.getSession();
try {
final magic m = new magic();
session.setAttribute(SHARED_MAGIC_INSTANCE, m);
} catch (MWException e) {
session.getServletContext().log
("Error creating magicsquare.magic", e);
}
}
public void sessionDestroyed(final HttpSessionEvent event) {
final HttpSession context = event.getSession();
final magic m = (magic)context.getAttribute(SHARED_MAGIC_INSTANCE);
m.dispose();
}
} @Override
protected void doGet(final HttpServletRequest request,
final HttpServletResponse response)
throws ServletException, IOException
{
final HttpSession session = request.getSession();
final magic m =
(magic)session.getAttribute
(MyHttpSessionListener.SHARED_MAGIC_INSTANCE);For the most detailed coverage of the Java language on the Web, refer to Oracle's Web Site at http://www.oracle.com/us/technologies/java/index.htm.
![]() | Why Learn About Java Web Concepts and Terminology? | Lifecycle of a Deployed MATLAB Web Application | ![]() |

Learn how to build standalone executables and C/C++ shared libraries from MATLAB code.
| © 1984-2012- The MathWorks, Inc. - Site Help - Patents - Trademarks - Privacy Policy - Preventing Piracy - RSS |