Architecture & DesignEnterprise Web Services and Model-View-Controller

Enterprise Web Services and Model-View-Controller

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

At the present, most software development teams have adapted various development methodologies, such as design pattern programming or object-oriented code frameworks, to facilitate their project creation. Different communication standards, such as SOAP or Web Services are also becoming commonplace among large and small firms as a way for them to expand their interoperability with other businesses or improve transaction processes.

One of the most widespread and well-known design patterns is the Model-View-Controller. I have described this pattern in detail in previous articles (see the References section), and this article will focus on an underexplored aspect of the MVC design paradigm, which is to separate the presentation layer and make it remote by using a Web service. In other words, remote Web service clients will become a View only and the Model layer and Controller will be contained on the server.

To recap, the MVC paradigm dictates that the model or data layer should be separated from its presentation (view layer) and there should be a controller layer to coordinate transactions to and from the presentation layer and provide data flow control.

MVC became very popular among Web developers, especially Java developers, because it offered an ideal way to develop robust applications in a standardized way in a reasonable amount of time. It also offered an easy way to expand new applications as needed with minimal efforts. In fact, it became so popular that several major frameworks, such as Struts from the Apache group, are based on the MVC.

In my previous article, “Developing Web Services with Borland JBuilder Enterprise and BEA WebLogic Server,” I described how to create a simple Web service from an existing “legacy” code. I will build upon the simple project from that article and add MVC components to show my point. You should be familiar with how to create Web Services using some enterprise or free toolkit, such as Borland JBuilder and BEA WebLogic or Eclipse and Axis. Also, you should be familiar with MVC in general.

Simple Project

Assuming that the following requirements have been created for the project:

  • The user wants to connect to a registry or data store of some kind, for instance LDAP (Light Weight Directory Protocol)
  • Create, edit, and delete data.
  • Store results and view data.

One approach would be to create a client application that directly accesses LDAP or the data store and does all the required actions; for instance, a Graphical User Interface (GUI) in C++ running on Windows. To expand the client base to a different platform or technologies—a Web-based Java Applet or ColdFusion Module, for example—would require rewriting all the client logic, as well as all the LDAP or database connection and data manipulation logic.

A more sensible approach would be to create a server-side client, perhaps running on the same server as LDAP or the database, embed all the connection code and data manipulation logic in it, and expose APIs of this client as a Web service. The client to the LDAP would serve as a Controller and the Model and, at the same time, as a server for other remote clients. This client can be multithreaded to handle multiple concurrent connections from remote clients and scale better when connecting to the data store. This approach would free future clients from knowing how to connect to LDAP or how to do data algorithms. All they would have to know is how to represent the data to the users and submit requests back to the server via a standard protocol.

Server Side: Controller and Model

To demonstrate MVC and Web services in action, a simple project that contains a model and a controller on the server side and exposes view methods via a Web service was created. This project does not actually connect to any LDAP or database; the connection code is beyond the scope of this article, but it can be easily added to the described methods.

The Model is a simple holder “bean” class that holds a single field String namevalue, with setter and getter methods.

public class BeanModel {
   private String namevalue;
   public BeanModel() {
   }
   public String getNamevalue() {
      return namevalue;
   }
   public void setNamevalue(String namevalue) {
      this.namevalue = namevalue;
   }
}

The Controller class, which will be exposed as a Web service, instantiates the Model “bean” class and has methods that the remote client can call to get responses from the server and present them in their Views to the user. These methods also can manipulate data in the Model and then return it to the caller. Here is the code for the Controller with three methods: one method to get namevalue, one to set it to some value, and one that converts it to upper case. These three methods will be exposed as a Web service API. Even though these methods are extremely simple, the architecture can be expanded to cover any enterprise requirement.

public class Bean1 implements Serializable {
   BeanModel bm = new BeanModel();

   public String getName() {
      return bm.getNamevalue();
   }

   public void setName(String name) {
      bm.setNamevalue(name);
   }

   public void upperCaseName() {
      bm.setNamevalue(bm.getNamevalue().toUpperCase());
   }

However, these methods only manipulate the data and present no control over the transaction state or data flow. Bean1 is exposed as a Web service using Borland JBuiderX, but you can use any toolkit you are familiar with. Precompiled stubs and classes (packaged in an EAR file) are loaded into an application server, in this example BEA WebLogic, but any compatible application server also can be used. For a concrete explanation on how to create a Web service and install it on Weblogic, please see “Developing Web Services with Borland JBuilder Enterprise and BEA WebLogic Server.”

The lient calling these methods can execute them in any order and show returned results in any form. I’ll discuss the client in more detail later on, but the calling code can look like this:

String name = "Vlad";
System.out.println("Setting Name to: " + name);
port.setName(name);
port.upperCaseName();

String resultStr = port.getName();
System.out.println("Modified name is: " + resultStr);

With the result:

Setting Name to: Vlad
Modified name is: VLAD

There is a shortcoming in the server code that limits client use of the given APIs. The true MVC power comes in the ability to control the execution state and transaction flow with a controller object telling the client the outcome of the operation and what should be done next. This can range from error handling, with the exception caught on the server propagated to the client and presented to the user; to the execution flow, with client getting responses as to what to which methods to call in the sequence. For instance, a banking transaction can dictate to the client application to display a balance page after a transfer operation.

For this to occur, a little more logic needs to exist on the server. For instance, in an enterprise-scale application a Controller would return a response to the client, indicating what action to perform next or how to handle the result. To simulate this behavior, a new set of methods returning String keys is added to the Controller (prepended with “method#_”). These methods still work with the same Model object, but do more than the first three methods described. In addition to exactly the same data manipulation (get, set, and uppercase), these methods also return a response to the client. The return value is a String “key” that is a name of the next method the client should call, if they choose to. For example, Java clients can use reflection to instantiate a new method and call it.

/*************True MVC Logic ********************/
public String method1_setName(String name) {
   bm.setNamevalue(name);
   return "method2_UpperCaseName";    // key
}

public String method2_upperCaseName() {
   bm.setNamevalue(bm.getNamevalue().toUpperCase());
   return "method3_GetName";
}

public String method3_getName() {
   return bm.getNamevalue();
}

Remote Web Service Client: View

Clients invoking Web service methods can decide what action to perform, based on the response from the server. In this case, a server returns a key that is also a method name. Clients can dynamically invoke the next method based on the result value from the server and continue with their operation execution.

For instance, Java clients can get a Web service access point and set data as before, but the response will tell the client what API to call next. In case of method1_SetName, the call return value is the “method2_UpperCaseName” string, which can be instantiated as a next method to invoke dynamically on the Web service.

The return value from method2_upperCaseName is a“method3_getName” string that is also called dynamically.

//True MVC test
name = "Kofman";
String nextActionKey = port.method1_SetName(name);
System.out.println("Setting new name to Server model: " + name);

Method method = port.getClass().getMethod(nextActionKey, new Class[] {});
String nextKey = (String) method.invoke(port, new Object[] {});

Method method2 = port.getClass().getMethod(nextKey, new Class[] {});
String result = (String) method2.invoke(port, new Object[] {});

System.out.println("Result from Server Model - name is: " + result); 

For a complete listing, please see the accompanying source code. The result is the same as before, but the client did not explicitly call the methods; the calling was guided by the controller on the server.

Setting new name to Server model: Kofman
Result from Server Model - name is: KOFMAN

Of course, this architecture can be expanded and applied to any scenario where MVC Web service architecture can be beneficial. Here is the complete client listing:

package test;

import beanexport.generated.*;
import java.lang.reflect.Method;

public class Test {
   public static void main(String[] args) {
      try {
         String wsdlUrl = "http://localhost:9501/web-services/
                                  Bean1?WSDL";
         Bean1 service = new Bean1_Impl(wsdlUrl);
         Bean1Port port = service.getBean1Port();

         //Simplified Remote View test
         String name = "Vlad";
         System.out.println("Setting Name to: " + name);
         port.setName(name);
         port.upperCaseName();

         String resultStr = port.getName();
         System.out.println("Modified name is: " + resultStr);

         //True MVC test
         name = "Kofman";
         String nextActionKey = port.method1_SetName(name);
         System.out.println("Setting new name to Server model: "
                            + name);
         Method method = port.getClass().getMethod(nextActionKey,
                                                   new Class[] {});
         String nextKey = (String) method.invoke(port, new Object[] {});

         Method method2 = port.getClass().getMethod(nextKey,
                                                    new Class[] {});
         String result = (String) method2.invoke(port, new Object[] {});

         System.out.println("Result from Server Model - name is: "
                            + result);

      }
      catch (Exception e) {
         e.printStackTrace();
      }
   }
}

Conclusion

In this article, I’ve discussed how to expand MVC to include a Web service and relocate the View layer to remote machines. Given that the communication protocol will be standardized via XML schema and can be SOAP over HTTP, the potential for a Client Interfaces is quite large, encompassing other platforms and languages different from whatever language the Controller and Model on the server are written in. Different user interfaces such as desktop GUI, text mode, Web-based pages, or non-interactive autonomous applications all can serve as clients in this type of architecture. If you are designing your application for the Web and choose to use MVC as an underlying framework, it may make sense to add a Web service component early on in your design process. Eventually, offering a remote presentation with standard protocols for Web service-centric clients can greatly increase your customer base.

Source Code

Download the accompanying source code here.

Articles Written by the Author on Similar Topics

Applying MVC to Web-Based Applications with Generic Views

Creating Interactive GUIs with Swing’s MVC Architecture

Creating Dynamic Swing Views with Reflection by Extending MVC

Additional References

Advanced MVC: http://www.ifi.unizh.ch/richter/Classes/oose2/03_mvc/02_mvc_java/02_mvc_java.html#4%20Models%20as%20Proxies

Web Services Developer: http://info.borland.com/techpubs/jbuilder/

Developing Web Services: http://info.borland.com/techpubs/jbuilder/jbuilder2005/websvcs/contents.html

About the Author

Vlad Kofman is a System Architect working on projects under government defense contracts. He has also been involved with enterprise-level projects for major Wall Street firms and the U.S. government. His main interests are object-oriented programming methodologies and design patterns.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories