By Brett McLaughlin
Price: $34.95 USD
£24.95 GBP
Cover | Table of Contents | Colophon
<?xml version="1.0"?>
<songs>
<song>
<title>The Finishing Touch</title>
<artist type="Band">Sound Doctrine</artist>
</song>
<song>
<title>Change Your World</title>
<artist type="Solo">Eric Clapton</artist>
<artist type="Solo">Babyface</artist>
</song>
<song>
<title>The Chasing Song</title>
<artist type="Band">Andy Peterson</artist>
</song>
</songs>
<?xml version="1.0"?>
<ejb-jar>
<entity>
<description>This is the Account EJB which represents
the information which is kept for each Customer</description>
<display-name>TheAccount</display-name>
<ejb-name>TheAccount</ejb-name>
<home>com.sun.j2ee.blueprints.customer.account.ejb.AccountHome</home>
<remote>com.sun.j2ee.blueprints.customer.account.ejb.Account</remote>
<ejb-class>com.sun.j2ee.blueprints.customer.account.ejb.AccountEJB</ejb-class>
<persistence-type>Bean</persistence-type>
<prim-key-class>java.lang.String</prim-key-class>
<reentrant>False</reentrant>
<env-entry>
<env-entry-name>ejb/account/AccountDAOClass</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>
com.sun.j2ee.blueprints.customer.account.dao.AccountDAOImpl
</env-entry-value>
</env-entry>
<resource-ref>
<res-ref-name>jdbc/EstoreDataSource</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
</entity>
</ejb-jar>
List entities = ejbJar.getEntityList( );
for (Iterator i = entities.iterator(); i.hasNext( ); ) {
Entity entity = (Entity)i.next( );
String displayName = entity.getDisplayName( );
String homeInterface = entity.getHome( );
// etc.
}dealer-name, and a Java class called
DealerName is generated. An XML Schema defines the
servlet element as having an attribute called
id and a child element named
description, and the resultant Java class
(Servlet) has a getId() method
as well as a getDescription() method. You get the
idea—a mapping is made between the structure laid out by the
XML constraint document and a set of Java classes. You can then
compile these classes and begin converting between XML and Java.
http://java.sun.com/xml/jaxb/index.html. The
specification, as of this writing, is currently released as Version
0.21, and the implementation is a 1.0 release. I'll
cover setting up JAXB for use with the examples in the next chapter.
org.xml.sax.ErrorHandler interface. This allows
parsing warnings and errors to be dealt with gracefully, rather than
bringing a system to a grinding halt. Most data binding projects
allow you to set an ErrorHandler implementation on
a class to be unmarshalled (prior to the unmarshalling, of course) so
you can customize error handling. In the Lutris Enhydra project, for
example, the error handler implementation shown in Example 2-1 demonstrates
how errors can
be logged before being reported back to the application.
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
<SOAP-ENV:Body>
<resp:stockQuoteResponse xmlns:resp="http://www.stockQuotes.com">
<quote symbol="ALGX" name="Allegiance Telecom">
<volume>2,964,600</volume>
<averageVolume>924,318</averageVolume>
<marketCap>411,700,000</marketCap>
</quote>
</resp:stockQuoteResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
public class Quote {
private String symbol;
private String name;
private float volume;
private float averageVolume;
private long marketCap;
public String getSymbol( );
public String getName( );
public float getVolume( );
public float getAverageVolume( );
public long getMarketCap( );
// Other mutator methods
}public static EjbJar unmarshal(InputStream inputStream)
throws IOException {
return (EjbJar)Unmarshaller
.unmarshal(inputStream, EjbJar.class);
}
http://www.newInstance.com.
<!ELEMENT movies (movie+)>
<!ATTLIST movies
version CDATA #REQUIRED
>
<!ELEMENT movie (title, cast, director?, producer*)>
<!ELEMENT cast (actor+)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT director (#PCDATA)>
<!ELEMENT producer (#PCDATA)>
<!ELEMENT actor (#PCDATA)>
<!ATTLIST actor
headliner (true | false) 'false'
>
xml-java-binding-schema. It must also have a
single attribute, version, and currently the only
allowed value for this attribute is
1.0-ea.
element element (yup, you read that
right). By supplying the root attribute and giving
it
a value of true, you've given
JAXB what it needs. Add to this the name
attribute, which identifies the element you're
working on and, finally, the type attribute, which
tells JAXB what type of Java construct to create from the element.
For the movies element, you want a Java class, so
use the class value for this attribute.
http://java.sun.com/xml/jaxb and follow the
links to download the reference implementation of JAXB. I also
recommend that you download the PDF specification for reference. Once
you've got the release (named something like
jaxb-1_0-bin.zip),
you'll want to extract this to a directory on your
hard drive. On my Windows machine, I used c:\dev\javajaxb\jaxb-1.0, and
it's extracted at /dev/javajaxb/jaxb-1.0 on my Mac (running OS
X).
@echo off if "%JAVA_HOME%" == "" goto java_home_error if "%JAXB_HOME%" == "" goto jaxb_home_error set LOCALCLASSPATH=%JAVA_HOME%\lib\tools.jar;%JAXB_HOME%\lib\jaxb-xjc-1.0-ea.jar echo Starting JAXB Schema Compiler...
unmarshal( ) method
(or whatever it's called with your framework).
Rather than relying on a black box process, you'll
be able to know exactly what goes on, troubleshoot oddities in your
applications, and maybe even help out the framework programmers with
a bug here and there.
unmarshal( ) method
(or whatever it's called with your framework).
Rather than relying on a black box process, you'll
be able to know exactly what goes on, troubleshoot oddities in your
applications, and maybe even help out the framework programmers with
a bug here and there.
root and
child elements in this document fragment is
completely irrelevant when using data binding:
InputStream or a
Reader, both from the java.io
package. When using JAXB, you'll need to limit your
input format to InputStreams, as
Readers aren't supported
(although many other frameworks do support
Readers, it is simple enough to convert between
the two input formats).
unmarshal( ) method.
The answer with respect to the JAXB framework is that the stream is
closed. That effectively ends the use of the stream once
unmarshalling occurs. Trying to
use the stream after
unmarshalling results in an exception like this:
java.io.IOException: Stream closed
at java.io.BufferedInputStream.ensureOpen(BufferedInputStream.java:123)
at java.io.BufferedInputStream.reset(BufferedInputStream.java:371)
at javajaxb.RereadStreamTest.main(RereadStreamTest.java:84)unmarshal( ) method
invocation).
MovieServlet class. This class
provides web access, through a GET request, to the
data in the current movie database. I won't spend
time covering the semantics of servlet code; if you
aren't comfortable with servlets, check out Jason
Hunter's Java Servlet
Programming (O'Reilly). In any case, look
at the example code, and I'll discuss how the
data-bound classes are used.
package javajaxb;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;
// Servlet imports
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
// Movie database generated classes
import javajaxb.generated.movies.*;
public class MoviesServlet extends HttpServlet {
/** The Movies database object */
private Movies movies = null;
/** Any error that occurred. */
private String errorMessage = null;
/** The XML document storing the movie database */
private static final String MOVIES_XML_DOCUMENT =
"/dev/javajaxb/ch04/src/xml/movies.xml";
public void init(ServletConfig config) throws ServletException {
super.init(config);
// Load the database using JAXB
try {
// Load the XML
File xmlFile = new File(MOVIES_XML_DOCUMENT);
FileInputStream inputStream = new FileInputStream(xmlFile);
// Unmarshal
movies = Movies.unmarshal(inputStream);
} catch (Exception e) {
errorMessage = e.getMessage( );
}
}
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
// Handle any error conditions that might have occurred.
if (movies == null) {
error(res);
}
// Get output stream
PrintWriter out = res.getWriter( );
res.setContentType("text/html");
// Write out movie database
out.println("<HTML><HEAD><TITLE>Movie Database</TITLE></HEAD>");
out.println("<BODY>");
out.println("<H2 ALIGN='center'>Movie Database</H2>");
List movieList = movies.getMovie( );
for (Iterator i = movieList.iterator(); i.hasNext( ); ) {
Movie movie = (Movie)i.next( );
// Title
out.print("<B><FONT SIZE='+1'>");
out.print(movie.getTitle( ));
out.println("</FONT></B><BR />");
// Director
String director = movie.getDirector( );
if (director != null) {
out.print("Director: ");
out.print(director);
out.println("<BR />");
}
// Producer
out.println("Producers:<BR /><UL>");
List producerList = movie.getProducer( );
for (Iterator j = producerList.iterator(); j.hasNext( ); ) {
out.print("<LI>");
out.print((String)j.next( ));
out.println("</LI>");
}
out.println("</UL>");
// Cast
out.println("Starring:<BR /><UL>");
Cast cast = movie.getCast( );
List actorList = cast.getActor( );
for (Iterator j = actorList.iterator(); j.hasNext( ); ) {
Actor actor = (Actor)j.next( );
out.print("<LI>");
out.print(actor.getContent( ));
if (actor.getHeadliner( ).equalsIgnoreCase("true")) {
out.print(" (Headliner)");
}
out.println("</LI>");
}
out.println("</UL>");
out.println("<HR WIDTH='80%' />");
}
out.println("</BODY></HTML>");
out.close( );
}
private void error(HttpServletResponse res) throws IOException {
PrintWriter out = res.getWriter( );
res.setContentType("text/plain");
out.write(" ************* ERROR OCCURRED ***************\n\n");
out.write("Error: " + errorMessage + "\n");
out.close( );
}
}thriller,
comedy, and drama are allowed
for the genre element, you would not be able to
marshal a Java object whose genre member variable
was set to the value package javajaxb;
import java.io.File;
import java.io.FileOutputStream;
// Generated Classes
import javajaxb.generated.movies.*;
public class ValidationTest {
public static void main(String[] args) {
try {
// Create a movie database
Movies movies = new Movies( );
// version attribute NOT set
// Create a new movie
Movie movie = new Movie( );
movie.setTitle("Attack of the Clones");
movie.setDirector("George Lucas");
movie.getProducer( ).add("Rick McCallum");
movies.getMovie( ).add(movie);
// Set cast
Cast cast = new Cast( );
Actor obiwan = new Actor( );
obiwan.setContent("Ewan McGregor");
obiwan.setHeadliner("true");
cast.getActor( ).add(obiwan);
Actor anakin = new Actor( );
anakin.setContent("Hayden Christensen");
anakin.setHeadliner("true");
cast.getActor( ).add(anakin);
movie.setCast(cast);
// Create output stream
File file = new File("output.xml");
FileOutputStream outputStream = new FileOutputStream(file);
// Marshal back out
movies.marshal(outputStream);
} catch (Exception e) {
e.printStackTrace( );
}
}
}marshal() method is about as
simple as it gets. In this section, I'll continue to
use the MoviesServlet introduced in Chapter 4 and demonstrate how changes can be made and
marshalled back out to XML. This will give you a clear idea of how
marshalling works in a realistic way.
import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import java.util.Iterator; import java.util.List; // Servlet imports import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; // JAXB imports import javax.xml.bind.StructureValidationException; // Movie database generated classes import javajaxb.generated.movies.*;