Calling Java Code from ASP.NET Web Applications
Why Interoperate between ASP.NET and Java?
October 30, 2009
Why would you want to call Java code from your ASP.NET Webapplications? For more information on ASP.NET, see "HTML5 for the ASP.NET Developer" and "ASP.NET MVC Tutorial: Handling Errors and Exceptions." The best way to answer that question is by examining a few real-worldcase studies:
A major Web search portal needed to construct an internal Web site for their sales staff. The vendor-supplied data feed they needed to use on this internal site was only accessible through a Java library supplied by the vendor. The portal company had to use the Java library, but for other reasons they needed to implement on ASP.NET for the internal Web site platform. They had no choice but to solve the Java/.NET interoperability problem.
In another case, a large US savings and loan bank was building a Web application to display digital images of checks that the bank had processed. (In the US, this is known as a Check 21 application, named after the law that allows use of digital images instead of actual paper checks.) The application would be used both internally and by the public. The project s architects had settled on ASP.NET as an implementation platform because of the superior tooling, but the bank s back-end applications were all J2EE-based, and ran on WebSphere application servers. The Check 21 application would need to directly access the data through the back-end systems Enterprise Java Beans (EJBs).
There are many other scenarios that could require ASP.NETcode to call Java. Your company might have invested in a Java library orapplication and need to use it with new .NET development. A merger oracquisition might require .NET and Java applications from the merged companiesto work together. Or you just might want to get existing .NET and Java systemsintegrated to accomplish a business goal. In all these cases, you need to solvethe problem of Java/.NET interoperability.
Approaches to .NET/Java Interoperability
There are two main ways to call Java code from .NET: Webservices and bridging. The approaches are applicable whether the .NETapplication is an ASP.NET Web application, a Windows Forms or WPF-based richdesktop application, a console-based application, or a service.
Much has been written about Web services, so this articlewon t go deep into the details. While there are other definitions, we ll defineWeb services as remote procedure calls that are encoded using SOAP, transmittedusing HTTP, and described to the outside world using WSDL. Web services areimplemented according to established standards, so that any set of platformsthat implement those standards can interoperate. However, standards-based Webservices lead to a least common denominator approach, so that only therelatively small number of data types and other concepts supported by all theplatforms can be used in the communication; many concepts must be left out. Inaddition, the service-oriented approach provided by a Web service typicallyallows access to a very narrow API the service. While it may be possible toaccess an entire object-oriented API through a Web service, it is generallyquite difficult to set up a Web service that offers such a broad API.
The alternative to Web services is a Java/.NET bridge.With a bridge, the .NET code still runs in a CLR (Microsoft .NET CommonLanguage Runtime), and the Java code still runs in a JVM (Java VirtualMachine). Bridges generally take a proxy-based approach: you can create.NET-based proxies for the Java classes that will be accessed from .NET, orvice versa. The .NET code interacts with the proxy classes just as if they werethe underlying Java classes. The proxies, along with the bridge infrastructure,manage the communications between the two sides, including object marshallingand unmarshalling, and object lifecycle management. Depending on the bridge,the Java and .NET sides can run in different processes and communicate over asocket-based connection, or can run in the same process. There are a number ofdifferent Java/.NET bridges available; the example in this article usesJNBridgePro, a .NET/Java bridge from JNBridge (http://www.jnbridge.com), which supportsboth socket-based communication and in-process interoperability using sharedmemory buffers for communication. Figure 1 shows the architecture of JNBridgePro.
Figure 1: Architecture of a.NET/Java bridge.
The choice of whether to use Web services or a bridge toimplement a .NET/Java integration depends on the requirements of theapplication. Web services are standards-based and when they re available theywill usually just work. However, their performance is limited, and they are notwell-suited to calling a rich object-oriented API or passing custom classes orexceptions or implementing callbacks, all of which is easily done with abridge. It also is the case that not every application is Web services-enabledon the .NET and Java sides. Finally, for architectures where the Java code isin a simple library located on the same machine as the ASP.NET server, use of aWeb service, which involves multiple processes and a socket-based connection,is overkill; running the Java in the ASP.NET process, as is available inseveral bridges, is a more appropriate solution.
Calling Java Code from an ASP.NET Web Application
The following example shows how to use a bridge to call aJava library from an ASP.NET Web application. The ASP.NET code supplied belowis C#; the downloadable code also includes the equivalent VB.NET code (see endof article for download details).
To run this example, it is necessary to have Visual Studio2008, a Java Runtime Environment (JRE) 1.4 or later, and a copy of JNBridgePro.Evaluation copies of JNBridgePro can be downloaded from http://www.jnbridge.com.
Let s assume we have an existing Java library thatretrieves names of authors and titles of books from a database. The libraryexposes an API including two classes: Author, encapsulating information aboutauthors, and Book, encapsulating information about books. A simplified versionof the code is as follows:
public class Author{ public String firstName; public String lastName; public Author(String firstName, String lastName) { ... // construct a new Author object } public static Author[] getAuthors() { ... // return an array containing all the available Author objects in the database }}public class Book{ public String title; public String publisher; public String year; public Book(String title, String publisher, String year) { ... // construct a new Book object } public static Book[] getBooks() { ... // return an array containing all the available Book objects in the database } public static Book[] getBooks(String firstName, String lastName) { ... // return an array containing all books in the database by the given author }}
Full code for the Java library is available with thedownloadable code.
We are going to provide an ASP.NET Web-based front-endthat will display all authors in the database, and then, when the user clickson the name of an author, will retrieve and display all books written by aspecified author.
The first step in the process is to generate proxies forthe Author and Book classes. Start by launching JNBProxy, JNBridgePro sGUI-based proxy generator. When the Launch JNBProxy form is displayed, selectCreate new .NET --> Java project, as we are creating a project in which.NET code will be calling Java code. Once this is done, JNBProxy s main form isdisplayed (see Figure 2).
Figure 2: JNBProxy.
We will need to proxy the Java classes Demo2.Author andDemo2.Book, so we will need to configure the Java classpath used by the proxygenerator so that it can locate the desired classes. The classes Demo2.Authorand Demo2.Book are contained in the files Author.class and Book.class,respectively, and they must both be located in a folder Demo2. We must add thefolder containing Demo2 to the classpath. To do so, we use the menu commandProject | Edit Classpath... and locate the necessary folder. When we are done,we will see an Edit Class Path dialog box similar to that shown in Figure 3.
Figure 3: After creating classpath.
The next step is to load the Author and Book Java classes,then generate proxies for those classes. To load the classes, use the menucommand Project | Add Classes from Classpath... and enter the fully qualifiedclass names Demo2.Author and Demo2.Book. It is not necessary to add supportingclasses, as the only supporting classes needed to use Author and Book arearrays and strings, which are automatically converted to native .NET arrays andstrings.
Loading the classes may take a few seconds. Progress willbe shown in the output pane in the bottom of the window, and in the progressbar. When completed, Demo2.Author and Demo2.Book will be displayed in theEnvironment pane on the upper left of the JNBProxy window (see Figure 4).
Figure 4: After loading classes.
We wish to generate proxies for both of these classes, sowhen all the classes have been loaded into the environment, make sure that eachclass in the tree view has a checkmark next to it. Quick ways to do thisinclude clicking on the checkbox next to each package name, or simply byselecting the menu command Edit | Check All in Environment. Once each class hasbeen checked, click the Add button to add each checked class to the list ofproxies to be exposed. These will be shown in the Exposed Proxies pane.
Finally, generate the proxies. Select the Project | Build...menu command, and choose a name and location for the assembly (.dll) file thatwill contain the generated proxies. The proxy generation process may take a fewminutes, and progress and other information will be indicated in the Outputpane. In this example, we will call the generated proxy assemblybookAccess.dll.
Now that the proxies are generated, we will write theASP.NET Web application that uses them and accesses the Java classes throughthem.
First, create a new C# Web Application project. (Make surethat you have Internet Information Server installed and properly configuredbefore you do this. Also note that the downloadable code contains a VB.NETversion of this example, so you will be able to do this same example withVisual Basic.) Open the web.config file in the project. Add the following codeto the section of Web.config:
Immediately after the section, add the following section:
These changes configure the .NET side to communicate withthe Java side using a socket-based approach. The Java side in this case willrun in its own process. It also is possible to configure the project so thatthe Java side runs inside the ASP.NET process and sockets are not needed. Thisapproach will be demonstrated at the end of the section.
Once the configuration file is edited, use the designer tocreate a simple Web form as shown in Figure 5. The two boxes in the Web formare ListBoxes, not ListViews, which are not available in Web forms. Make surethat the AutoPostBack property of the top ListBox is set to true.
Figure 5: Web form for exampleprogram.
Assuming that the top ListBox is named ListBox1, and thebottom ListBox is named ListBox2, add the following event handlers to the Web form scode-behind:
using Demo2;. . .private void ListBox1_Load(object sender, System.EventArgs e){ if (ListBox1.Items.Count > 0) { return; // don't add anything more } // load the authors Author[] authors = Author.getAuthors(); for (int i = 0; i < authors.Length; i++) { ListItem li = new ListItem(); li.Text = authors[i].lastName + ", " + authors[i].firstName; ListBox1.Items.Add(li); }}private void ListBox1_SelectedIndexChanged(object sender, System.EventArgs e){ // clear listBox2 ListBox2.Items.Clear(); // if nothing selected, return ListItem li = ListBox1.SelectedItem; if (li == null) { return; } // last, first names string name = li.Text; int separator = name.IndexOf(","); string lastName = name.Substring(0, separator); string firstName = name.Substring(separator+2); // look up books Book[] titles = Book.getBooks(firstName, lastName); // write out books for (int i = 0; i < titles.Length; i++) { ListItem li2 = new ListItem(); string theBook = titles[i].title + " (" + titles[i].publisher + ", " + titles[i].year + ")"; li2.Text = theBook; ListBox2.Items.Add(li2); }}
Again, note that the proxies for the Java objects of classDemo2.Author and Demo2.Book are used exactly as the original objects would beused in Java. This is where the interop occurs. Every call to a method inAuthor and Books, and every access of a field, is actually an access of theunderlying method or field. If the application is set up properly, the cross-platforminteroperation is transparent.
After entering the code, build the project to obtain theWeb application.
Running the program is simple. First, make sure there isan ODBC data source called BookDemo referencing the supplied Microsoft Accessdatabase books.mdb. Set up your Java environment by copying the filesjnbcore.jar (the JNBridgePro Java-side runtime component) andjnbcore_tcp.properties (the Java-side configuration file specifying binary,socket-based communications) to the folder containing the folder Demo2 (whichcontains the Java class files). Then, open a console window, navigate to thefolder containing Demo2, jnbcore.jar, and jnbcore_tcp.properties, and run thefollowing command:
java -cp ".;jnbcore.jar" com.jnbridge.jnbcore.JNBMain/props jnbcore_tcp.properties
You should see the following output:
JNBCore v4.0.2
Copyright 2008, JNBridge, LLC
creating binary server
This indicates that the Java side is running.
Once the Java side is running, start the Web applicationby launching a browser and entering the URL of the Web application (forexample, http://localhost/Demo2/WebForm1.aspx). The Web form will be displayedwith author names, obtained through the Java class Author, displayed in the toplist box (see Figure 6).
Figure 6: Initial Web form.
Clicking on any of the authors will cause books written bythat author to be displayed (see Figure 7).
Figure 7: Web form after clicking onauthor.
It is possible to run the Java side in the same process asthe .NET side, using a shared-memory communication mechanism. This has severaladvantages: it s much faster than the socket-based mechanism, and it s notnecessary to explicitly start up the Java side it s automatically done beforethe first call to a proxy. To use shared memory, stop Java side (if it s stillrunning), then open the web.config application configuration file. Replace the element with the following:
You will need to edit the jvm , jnbcore , bcel , and classpathvalues to reflect the locations on your machine of jvm.dll (in your Javaruntime environment), jnbcore.jar, bcel-5.1-jnbridge.jar (in your JNBridgeProinstallation), and the folder containing the folder Demo2 containing the filesAuthor.class and Book.class. Once you have made the changes, build the project.Restart ASP.NET by issuing the command iisreset from a command-line prompt,then start the Web application. It will run as before, even though the Javaside has not been explicitly started, because the Java side is now runninginside the .NET process.
Conclusion
This example shows how Java classes can easily be used inan ASP.NET application through use of a Java/.NET bridge. The bridge allows theJava classes to be called directly from the ASP.NET code through proxies; tointeract with a Java object, access the corresponding proxy object in exactlythe same way. Interactions between the .NET and Java code are transparent, anduse of proxies make the Java classes look as though they were written in a .NETlanguage like C# or VB.NET.
Returning to the case studies introduced at the start ofthe article, the Web search portal company decided to use a bridge to directlyaccess the data feed through their vendor s Java API. Constructing a Webservice around the API and accessing that seemed like overkill for the problemat hand. A bridge was more appropriate for direct access of the Java API.
For the savings and loan bank s Check 21 application, thearchitects did consider a Web service, as the back-end WebSphere implementationdid offer the option of Web services. However, they discovered that the Webservice offered insufficient throughput, so they also settled on use of abridge. The new application was up and running within a few weeks, certainly muchmore quickly than if they had decided to re-implement it with Javatechnologies, which was another option.
There are situations where a Web service would be a goodsolution for calling Java from .NET. If performance isn t the most significantissue, or if the connection must pass through firewalls or reach some otherorganization over the Internet, Web services are a reasonable interoperabilityoption.
If you are developing ASP.NET applications, ideally youwould like to base the project exclusively on the .NET platform. However, thereare practical reasons why a pure .NET implementation might not be an option.Knowledge of the various approaches to Java/.NET interoperability, particularlyWeb services and bridging, will often allow you to complete projects morequickly, and without the need to spend time rewriting legacy Java code.
Source codeaccompanying this article is available for download.
Wayne Citrin is theChief Technology Officer at JNBridge, the leading provider of Java and .NETinteroperability tools (http://www.jnbridge.com).Citrin co-founded the company in 2001 and has served as the chief architect ofits flagship product, JNBridgePro. He has been engrossed in Java and .NETinterop issues since .NET s earliest days and is an expert on interoperabilityissues regarding connecting the two development platforms. Previously, he was aleading researcher in programming languages and compilers at the University ofColorado, Boulder. Prior to this position, he was a researcher at IBM s lab inZ rich, Switzerland. Citrin holds a Ph.D. from the University of California,Berkeley, in Computer Science. He has presented at several leading conferencesincluding, JavaOne, Microsoft TechEd, and TechReady. In addition, his work andresearch has been published in numerous academic and trade journals.
About the Author
You May Also Like