Develop
à la J2EE by using .NET with the SnippetStore Project (Chapter II) by Julien Brunet (j.brunet@cross-systems.com) |
||
Chapter 2/3
Printed : 26 pages
Version 1.2-RAW
[WARNING] This is a fast rewrite of the rough Translation from the Google service. Please apologize the numerous mistakes, someone is actually reviewing this automated translation.
This chapter explains the building of the SnippetStore framework starting from the sources available on SourceForge (download information at the bottom of this chapter). It is also here that you will find the implementation details of the different J2EE APIs by using those from NET.
- If you arrived here by error, you can start again in chapter 1.
- If you wish to see with work the running of Java PetStore using this framework, you can go in chapter 3. However you'll have first to follow the labs of this chapter to build the required binaries before proceed.
Lab 1. Preparing the SnippetStore environment - Download the SnippetStore.zip [1] package on SourceForge, and unzip it to C:\SnippetStore - Download and install the JDK 1.2.2 [2], J2EE 1.2.1 [3], Jad [4], NAnt [5], MSDE [6] and ASP.NET Web Matrix [7] - Open a Command Prompt in C:\SnippetStore - Edit setenv.cmd and fix the accurate directories (JAVA_HOME, JÈE_HOME, NAntDir, JadDir) - Execute setenv.cmd in this CommandPrompt - Keep this Command Prompt opened during all the labs
Lab 2. Downloading and installing Java PetStore - Download the Java PetStore .zip file on the Sun website [8] - Unzip it to C:\SnippetStore\samples\jps1.1.2
Note: You must be registered on the Sun website to download Java PetStore.
In the following document and the associated source codes, we will briskly mix .NET and Java/J# code . For more clearness, the following convention will be applied to the source files:
Language | Origin | Files | Namespaces convention |
---|---|---|---|
Java | Java | .java | lowercase (javax.servlet.jsp) |
J# | .NET | .jsl | Pascal (SourceForge.SnippetStore.Xml) |
C# | .NET | .cs | Pascal (SourceForge.SnippetStore.Xml) |
This natural convention has the double advantage of being respectful of the standards of each framework, and of enabling you to identify in a glance the origin of the source code which you study.
As when working in the kitchen, it is always the preparation of the
ingredients which is most significant... and longest!
The objective of this stage at the very least tiresome is to recompile the
j2ee.jar package in J#.NET. However it is very far from being simple... (remember
the history of Apollo 13 where 50 engineers must find how to connect a round
ventilation shaft in a square recuperator...) Courage, the next steps will
be easier.
The modification of the J2EE source code being prohibited, it is thus excluded to distribute commercial software based on this SDK for NET. Too bad! All that starts very badly, but one should not be discouraged for as much. You point out that J# is not intended for complete Java support, but simply to bring its developers has to make the transition towards NET by using syntax from the language. One can hope that with the end of the lawsuits in progress, Microsoft goes a little further in the support of more recents JDK. On this subject, Brian Keller, Product Manager of J#, lance a call for contribution [9] to improve the language, profit.
Breaking News : Microsoft just released Supplemental UI Library for Visual J# .NET v1.1 [10]. I did'nt have time to look at it but it seems that this package reduces by little the variation with the JDK 1.2
In order to circumvent the failures of J #, i created some substitution classes in the LAME namespace (Let Another Missing Entrypoint :-) Other classes saw their code modified to use these substitutes. The following modifications there are thus found:
Assembly | Action | Class | Comments |
---|---|---|---|
j2se.dll | Substitute | LAME.Character | An additional constructor appeared in J2SE |
Substitute | LAME.ClassLoader | The J# ClassLoader always returns null! | |
Substitute | LAME.ResourceBundle | Who knows the relationship between RessourceBundle, .properties files .NET resources ? | |
Substitute | LAME.Vector2Collection | An additional conversion operator appeared in J2SE | |
Substitute | LAME.Enumeration2Iterator | Same | |
j2ee.dll | Dégradé | javax.rmi.PortableRemoteObject | In order not to peek the whole CORBA! |
Dégradé | javax.mail.internet.MimeUtility | Same | |
Changé | javax.servlet.http.HttpServlet | To refer LAME.ResourceBundle | |
Changed | com.sun.activation.registries.MailcapTokenizer | To refer LAME.Character | |
Substitute | LAME.MailcapTokenizer | A new char/int conversion operator appeared in J2EE |
Don't keep it for thruth: If there are so few changes, it is because the J2EE fingerprint was reduced to its bare minimum to make Java PetStore running. The curious ones will be able to study the j2ee-3 target from the NAnt script.
Trying to preserve the PortableRemoteObject class during the "removal" amount taking along all the house, the roof and the foundations... it is to better saw the feet of the settee rather than to cut down a wall, is'nt it ?
Where are the J2EE sources ?
Nowhere! As much the JDK library is delivered with its sources, as much J2EE SDK is like the .NET Framework: We have only the final bytecode in the j2ee.jar file which it will be needed to decompile. The thing is commonplace with a tool like Jad for example.
PS: In order not to upset anybody, throw a glance with Annakrino [11] for NET: -)
Lab 3. Converting the J2EE SDK for .NET Remark: NAnt must be configured to use the .NET Framework 1.1 - Edit NAnt.exe.config - (line 25) Change to <nantSettings defaultframework="net-1.1"> - (line 120) Change to <startup> <requiredRuntime version="v1.1.4322"/> <supportedRuntime version="v1.1.4322"/> </startup> C:\SnippetStore> nant snk C:\SnippetStore> nant j2se-1 j2se-2 C:\SnippetStore> nant j2ee-1 j2ee-2 j2ee-3
Job's done! Our J2EE SDK is very incomplete, but sufficient to run Java PetStore.
Hardest is made. We now will implement the J2EE layers one by one.
J2EE provides standard the DOM and SAX interfaces of the W3C. Surprising, the instanciation factory is defined in a separated package, JAXP (Api Java for Xml Processing). This factory makes it possible J2EE developers to choose the implementation to be used, among those available on the market.
JAXP is included in the zip of PetStore, this is why I asked you to download it from the very start of this chapter.
The .NET Framework provides a complete implementation of DOM and SAX parsers. However, no interface, only classes ! Impossible thus to consider the use of a different implementation without changing your source code.
To convert jaxp.jar into NET, it is very simple: The .NET Framework SDK 1.1 provides a new tool, "JbImp.exe" (Microsoft (R) Java-language bytecode to MSIL converter). This tool directly converts the java bytecode into MSIL NET (without passing by an intermediate phase of source code).
So only the JDK of J # was up to date and completely implemented, the conversion of the J2EE SDK would have been also simple. Alas, the "gap" is so significant that JbImp stops with internal errors...
Lab 4. Converting de JAXP
C:\SnippetStore> nant jaxp
There the serious things are coming: It is a challenge of implementing an interface (Java) while delegating on an aggregate class (.NET). The principle is well-known from Delphi programmers, who have even a keyword of the language for that!
Fortunately, both J2EE and NET APIs are based on the W3C specification, the correspondence of classes is thus very easy to establish.
The wrappers approach is very naive: When a Java method returns an interface, we reinstanciate without thinking the corresponding wrapper, even if one already exists. This method has the merit to be powerful, because the speed of construction of the wrapper is higher than calculation than it would be necessary to establish to determine the existence of an existing wrapper.
In NET, the garbage collector has an mark-and-sweep algorithm, i.e. it allocates memory in a linear way and regularly compacts it like a defragmentation tool. The instanciation of an object in .NET is thus one of the fastest operations of Framework. Many articles explain the subject in details.
Lab 5. implementating JAXP over .NET C:\SnippetStore> nant SnippetStore.Xml
The JDBC API (Java DataBase Connectivity) is not part of J2EE but of the JDK. It is made up mainly of Java interfaces dedicated to data access. It is thus enough, as for JAXP, to implement these interfaces to get a new provider.
Did you know? J# provides out of standard a generic implementation on ODBC (inherited Visual J++ 6.0). It is located in the com.ms.jdbc.odbc namespace of the vjslib.dll assembly
The ADO.NET API (Active Data Objects .NET) also consists of interfaces (IDbConnection, IDbCommand...). Multiples providers are available from start, some reaching generic middlewares (OleDb, Odbc), others specialized (SqlClient, OracleClient, MySql...) like JDBC thin-drivers.
The design of ADO.NET is very elegant, except on a point: There does not exist out of standard of instanciation factory, which means that unless to write it by yourself (the thing is relatively commonplace), you must explicitly handle the classes of a provider X or Y.
Using ODBC... well, why not, but the challenge is weak. I thus propose you that we reimplement ourself the JDBC interfaces on a ADO.NET basis. The mapping is more complex, but a good knowledge of each framework quickly makes it possible to determine the relationships. The pattern remains the same one: the implementation of the J2EE interfaces by the wrappers aggregates the ADO.NET interfaces, which refer themselves to an implementation (OleDb by default)
Caution! A small anecdote on the bridge (noted during Java PetStore testrun) :
- in Java, we can retrieve multiple ResultSets using calls to executeQuery() on the same Statement
- in .NET, there can be only one active DataReader at a time by calling ExecuteReader() on the same DbCommand.
The wrapper thus makes a follow-up of the last DataReader generated by its internal DbCommand and closes it before providing another one.
Lab 6. Implementing JDBC over .NET C:\SnippetStore> nant SnippetStore.Data
The JNDI API (Java Naming Directory Interfaces) is a major element of J2EE, because it gives him the essence of its flexibility. Let us say to simplify that this interface describes a system of distributable directory on which one can refer and obtain as well Java objects as entries LDAP.
Within J2EE applications such as Java PetStore, it is up to the container to configure the JNDI directory and to register objects and values described in XML manifests (which we saw in chapter 1). Then the applications have to query the directory with the JNDI APIs to retrieve these objects and to use them inside the application. Here is an extract of the Java PetStore code which helps understanding the interest of using a directory inside factories:
This code makes it possible to recover a DAO object (Data Access Object) that manages accounts, via the InitialContext JNDI class. The advantage of using a factory making a lookup on the directory is that the container can bind a different implementation without this factory to be impacted by it. In Java PetStore, three implementations of DAO are provided: Cloudscape, Sybase and Oracle.
PS: This code sample demonstrates what i see as the misdeeds of the checked exceptions of Java: The exceptions are choked to be replaced by more general exceptions (AccountDAOSysException). We will get back on this thorn-bush problem at the end of the chapter.
The System.Directory API of NET is a wrapper on the Windows client for Active Directory (Active Directory being the enterprise directory on which all the Microsoft infrastructure is based). Unfortunately, the referencing of objects offered by JNDI misses completely NET!
It is thus clear that System.Directory is not adapted at all to emulate JNDI since it lacks its principal function to him, and yet very simple in the case of Java PetStore: to maintain a list objects referred by identifiers chains single.
To implement JNDI, I thus made with simplest: A hashtable! Admittedly, it is very far from managing all the smoothnesses of context and providers suggested by JNDI, but that is enough for the bind/lookup functions of Java PetStore.
Besides this do-it-yourself, the use of this JNDI implementation is the same one as in J2EE: When the Web container starts (will see we it further), it mounts a local JNDI and publishes there the objects and values of the manifests which has been loaded.
Fourth and penultimate part of J2EE to be implemented in the SnippetPetStore framework, EJBs (Enterprise Java Beans). For this part as for the following one (the Web container), work to be carried out is much more delicate: As much JAXP, JDBC and JNDI are parts of code with wrapper once and for all, as much the interfaces and classes of this API are extended by J2EE developer on the one hand, by the application server on the other hand (as we will see it, the main part of the EJB system is based on dynamic code generation)
For all these reasons, we will have to define principles of wrappers, and to automate their writing for each EJB via the toolkit. So that the thing is comprehensible, it is necessary to go down a little more deeply in the object models of the two platforms.
EJBs are at the core of J2EE, since they have to handle the transactionnal, load balancing and component distribution services.
The EJB Specification distinguishes 3 types of components:
Moreover, among the EJB entities, we distinguishes the way in which persistence is handled:
From a strictly technical point of view, it is about a particular design pattern intended to facilitate the "weaving" of the aspects (transaction management, network calls, Juste-in-time activation ...) by the J2EE container. The following diagram illustrates some of these aspects:
The EJB Design Pattern being difficult to summarize, let us look at together the code of the EJB "Account" of Java PetStore. In a EJB development, it is required to write 2 interfaces and 1 class for each EJB component :
All that is, from a strict object point of view, very disappointing (not to say straightforwardly hideous)! We could have thought that the EJB implementation implements at first the interface of the same EJB and that the "technical" interfaces (EntityBean/SessionBean) are possibly woven around... and well not, it is the opposite! Fortunately, the majority of the J2EE development environments ensure the consistency checks which the model object does not provide...
As if it were not complicated already enough, it is also necessary to describe in the EJB manifest associations between the three elements and their methods. Note finally the indication of the transactional methods (<trans-attribute>)
Two questions are remaining:
Let us be honnest, even if theorically Serviced Components of NET looks like the J2EE EJBs, their technical perimeter is far from being comparable. Serviced Components represent, for now, a "reasonably elegant" integration of the COM+ services (Common Object Model) which existed well before .NET on the Windows platform. The latter have as to handle the transactionnal, load-balancing and component distribution services.
In .NET, Serviced Components do not hide their J2EE inspiration since they are located in the "System.EnterpriseServices" namespace. It is to however be unaware of that, historically, EJBs appeared after COM+ components (MTS, at this time)!
Compared to EJBs, ServicedComponents do not cover the following aspects:
The following diagram illustrates the base ServicedComponent class to be derived, with one of its aspects:
Yes, you read well: The base class is imposed, which will not facilitate weaving by the toolkit!
On the transactional side, the declaration is much more elegant: .NET makes use of attributes to declare the transactional components, directly in the code. Other aspects are also described in this manner: Juste-in-time activation, Pooling, Statistics...
Oui, vous avez bien lu : La classe de base est imposée, ce qui ne va pas faciliter le tissage par la toolkit!
This long summary of the compared functionalities of EJBs and ServicedComponent clarifies the notable differences between the two platforms. The API EJB is rich and flexible, but its model object is unnecessarily complex. The .NET Platform is much simpler a priori, but have also more limitations. Pragmatic, some will say: -)
The EJB/ServicedComponent bridge proceeds overall by weaving between the classes/interfaces and the EJB manifest, as follows:
The suggested conversion is simple, being limited to bare essential is thus required by Java PetStore. The CMP Model is not handled (Container Managed Persistence), since the application uses only BMP model (it manages itself its persistence).
As a consolation, the SnippetStore toolkit not proposes one but two modes of weaving, with the choice:
If you use the serviced weaving, you will have the pleasant one surprised to see your COM+ components being registered automatically with the execution of Java PetStore, functionality integrated of the NET Framework.
NB: The choice of the weaving model is defined in the NAnt script, through the "serviced" property. This setting does not affect the compilation of the lab below but the code generation in chapter 3.
Lab 7. Implementing EJB over .NET C:\SnippetStore> nant SnippetStore.EJB
Tired? Disappointed? I understand you, this EJB/COM+ wrapper is probably very distant from your hopes... but be reasonable: nobody said that the thing was easy. For the Web container, on the other hand, it will be simpler; by a fortunate coincidence, .NET and J2EE have much more pronounced resemblances, in the content as in the form.
As previously, we will study in the broad outline the specifications of each platform, to deduce the adequate method of interposition thereafter from it.
At the contrary of the EJBs, the Web container in J2EE was precursory. For a long time It kept a length besides in advance on its competitor of the time, ASP 3.0 from Microsoft. Considering that the principal role of a Web container is to generate dynamic Web pages, we distinguishes for that the three following bricks among the J2EE APIs :
The three bricks (Servlets, JSP, TagLibs) are not mutually exclusive: Java
PetStore, following the J2EE best pratice, combines these three techniques
within an MVC model (Model View Controller).
We distinguishes 3 bricks to generate dynamic pages under .NET
Attention, any resemblance to concepts already seen would be only sheer coincidence: -)
The correspondences between J2EE and .NET concepts appear immediately, however you will have noted some differences in both approach. The divergence comes primarily in the processing mode from JSP and ASPx pages, and we can on this subject to a parallel dared a little with parsers XML:
- The J2EE taglibs decide of the flow generation the way SAX parsers does ("event-based" calls on the opening and closing tags)
- .NET WebControls are assembled in a composite model, the way DOM parsers does (call on the root element which reiterates on its subelements)
This remark being made, we can for the remainder establish a interposition
diagram. The mapping being more complicated than for JAXP and JDBC, the
illustration below were simplified:
Technically, the SnippetStore conversion toolkit includes three parts :
1. | 2. | 3. |
Honestly, the JSP->ASP.NET converter is very insufficient, but it has at least the merit to facilitate the migration. The following problems are not solved in particular (they were discovered during the migration Java PetStore) :
- The scope of a < %... % > block covers the entire JSP page, whereas it is limited to the block in ASP.NET. If a variable is declared in a JSP block and is used in another, it is necessary to transform the first block into < script runat="server ">... </script > section.
- WebControls do not support an initialization of their properties using code expressions, but only constants. Everytime an expression has to be used within taglibs, it is necessary to give a single identifier to the Tag/WebControl (ID attribute) and to move initialization in the Page_Load() event of the ASP.NET page.
- Certain overlaps of TagLibs are not correctly analyzed by parser ASP.NET.
- Finally (the worst for the end), the problem of the checked exceptions,
which deserves a paragraph... that here :
One of the notable divergences between Java and .NET is about the concept of checked exceptions:
- In Java, exceptions are checked. That means that a method must explicitly declare on its signature the exceptions types which it can raise, via the throws keyword (not to be confused with throw).
- In .NET, exceptions are not checked. Any method can raise any exception, without that being explicitly described in its signature. This definition is imposed by the CLS (Common Language Specification), the in theory common contract for all .NET languages.
- J#, hybrid between the two worlds, is a .NET language which supports checked exceptions of Java. How is this possible? The compiler requires the presence of the throws keyword, in agreement with the Java standard, and discreetly generates a .NET metadata attribute (com.ms.vjsharp.cor.JavaThrownExceptions, undocumented). It is enough for it then to read again this attribute by reflexion to simulate at compilation time the concept of checked exceptions.
The problem of J# is at the CodeDom level. However this last is used by ASP.NET! Indeed, the CodeDom API, which makes it possible in .NET to generate code by handling objects symbolizing of the code (class, method), follows the CLS strictly... Impossible thus to indicate the throws clause required by the Java compiler.
We
can imagine the hard choice the J# team had to make... there has is not indeed
"a good" answer, according to the use which one wants to make of the language...
note the honourable effort but nevertheless ridiculous of the J# implementation
of CodeDom which sticks "to guess" the throws clause by detecting the presence
of a throw statement in the body of a CodeDom method (that does not go to all
the blows).
The only regrettable thing, it is to be able to say to the compiler which one
wants to be unaware of the checked exceptions in the CodeDom generation or
ASP.NET pages, via an attribute of the page directive, i.e.
"checkedexceptions=false" for example. In the absence of this functionality, you
will have to replace all ASP.NET expressions <%=... %> by a <script
runat=server > try {... } catch (Exception E) { }; block. This limit applies to
the JSP->ASP.NET converter
Lab 8. Implementing Servlets/JSP/TagLibs en .NET C:\SnippetStore> nant SnippetStore.Web
Yes, you deserved it well! Thus this chapter 2 is completed, very length I grant it to you.
As a reward, I propose to you to close the subject with chapter 3, much simpler, since it is only about practical work: the conversion of Java PetStore under .NET !
Author : Julien Brunet
Copyright © June 2003
Download the sources and binaries
SnippetStore official website : http://snippetstore.sourceforge.net/
[1] SnippetStore.zip (sources) : Snippetstore (zip File)
Resources
[2] J2SE SDK 1.2.2 -
http://java.sun.com/products/jdk/1.2/download.html
[3] J2EE SDK 1.2.1 -
http://java.sun.com/j2ee/1.2/download.html#sdk
[4] Jad -
http://kpdus.tripod.com/jad.html
[5] NAnt - http://nant.sourceforge.net/
[6] MSDE -
http://www.asp.net/msde/default.aspx?tabindex=0&tabid=1
[7] ASP.NET Web Matrix -
http://www.asp.net/webmatrix/default.aspx?tabIndex=4&tabId=46
[8] Java Pet Store -
http://java.sun.com/blueprints/code/index.html#java_pet_store_demo
[9] Brian Keller's Call for contribution -
http://msdn.microsoft.com/vjsharp/productinfo/survey/default.aspx
[10] Supplemental UI Library for Visual J# .NET v1.1 -
http://msdn.microsoft.com/vjsharp/supui/
[11] Anakrinno -
http://www.saurik.com/net/exemplar/
Lesser-GPL Licence
All files are provided under Lesser-GPL license.