Getting started with Web Services Using Apache Axis

NOTE:This article pertains to Beta 2 of Apache Axis,
released in April 2002.

In this article, I will discuss the basics of web services
and explore how Apache Axis, an open-source SOAP toolkit, and can be
used to create, deploy, and access such services. After a quick
introduction, we'll discuss downloading and installing Axis.
Then, we'll build a simple web service and communicate with it.
Finally,
we'll discuss some of the details behind a more advanced example.

Introduction

Web services technology has quickly become an important enabler
of true distributed computing over the Internet. By using
web services, consumers and providers of functionality can
quickly connect, without the usual integration hassles, in
a way that is language-independent and platform-independent. For
example, if you develop remote functionality in C++ on a Microsoft
Windows NT system, your friend using Java on Sun Solaris will be
access it over the Internet.

To motivate the need for web services, let's consider an example.
Suppose you have developed a useful Java class that you would
like to distribute to others via the Internet. How would you
(at Internet site x) make Java functionality accessible to
your remote friend (at Internet site y)?

One option is to use something like Java IDL (i.e., CORBA).
After all, doesn't CORBA and the IIOP protocol allow distributed objects
(potentially written in different languages) to communicate with
each other over the Internet? Well, yes and no. CORBA-IIOP solutions,
while possible, can be problematic in terms of security and ease of
deployment. In terms of security, ensuring that IIOP will work
through firewalls is often painful, since IIOP traffic does not
travel on port 80, as does normal HTTP traffic. A second major
issue is the lack of simple deployment. Unless they want to really
do some lower level programming, both participants in an IIOP exchange
must have Object Request Brokers (ORBs), which manage objects locally
and route requests to available instances. There are other issues,
but we don't have the space to get into a full-blown debate.
However, in all fairness, I should at least note that there do exist
counter-arguments
.

Well, what about skipping all of this complexity and just using servlets?
For example, you could embed your functionality in a servlet and
route its output back to callers. However, doing so involves a lot
of ugliness:

You have to build servlet wrappers for each piece of
functionality you want to deploy.

You need to manually print the output of the Java methods
of interest.

All variable types have been lost (unless you describe them explicitly -- and all your clients know about and obey your cooked-up protocol)

What we really want is some way to combine the flexibility and
interoperability of CORBA with the ease of deployments that
Java servlets provide. So, does such as solution exist? As it turns out,
it does: web services.

Web Services

Web services leverage the de-facto platform indepedence of the
Web and the extensibility and flexibility of XML to simplify distributed
computing on the Internet. The concept is straightforward: those that want
to distribute functionality publish web services, those that
want to use that functionality access those services.

The conceptual web services technology stack is shown in Figure 1.

Figure 1

Let's start by explaining a few of the acronyms:

WSDL: Web Services Description Language, which is how web services
are declared.

SOAP: Simple Object Access Protocol, which is the mechanism for
how services are invoked.

UDDI: Universal Description, Discovery, and Integration
specification, which is how services can be located.

There are
a variety of transports that one can use to communicate with
a web service - RPC, email, FTP, and HTTP, for example. In this
short tutorial, we will focus on HTTP, since that is the
protocol most readers will likely find applicable.

So then, in a nutshell, the technology stack in Figure 1 describes
how web services can be described, deployed, and accessed. In this
article, we will assume that we know the web service we want and where
it is deployed; thus, it only makes sense that access (SOAP) is our
chief concern. And this is exactly where Apache Axis comes in.

Apache Axis

Apache Axis is
a SOAP toolkit that makes it easy to create, deploy, and consume web
services. By using Axis, you will be able to quickly convert existing
Java functionality into web services, deploy those services, and be able
to communicate with them remotely via the Internet, usually through
firewalls (if necessary).

More precisely, Axis is an implementation of SOAP. Most people
like to think of it as a toolkit. From the programmer's point of
view, it's like an API. It makes it easy for you to communicate -
with SOAP - to a remote object, without having to worry about the
details associated with the protocol. In practice, it is a lot
like using RPC, CORBA, RMI, or any of the other distributed
computing technologies you may have experience with. The
process is largely the same: you describe the target of
your communication, invoke the remote method and marshall
your parameters, and then demarshall the return values.
Since AXIS makes this process simpler than ever, development
is a breeze.

The SOAP Protocol

SOAP is a simple an extensible protocol for communication between
application-level objects. It is a standard that originated between
a number of vendors, including Microsoft and IBM. However, its
support has grown to include Sun and is now generally viewed as the
best open standard for structured communication between objects
on the Web.

As described above, SOAP messages are
encoded with XML and the protocol can be deployed over a variety of
transports. In contrast to other synchronous protocols, SOAP communication
is one-way: from sender to receiver. Upon this, higher-level
request-response designs can be implemented.

A SOAP message consists of an envelope that contains an optional SOAP
header and a mandatory SOAP body.
The header is a mechanism for extensibility; we won't worry about
it much more here. The body contains the guts of the communication
between parties. For example, the body could contain information
on the remote method to be called, on the parameters to call it
with, etc. As a detailed example of a SOAP message, consider
the simple example (note that there is no header here -- remember,
it is optional) shown in Figure 2.

Figure 2

This example illustrates a request to a SOAP node such that
the method "GetCurrentTime" is invoked with the parameters
"city" (Las Vegas) and "state" (of Nevada). The service
containing that method is found at example.com. With this
simple example, you now have a feel for what SOAP messages look like.
If you are interested in a more detailed description of the
SOAP protocol, check out the W3C note.
For our discussion here, I summarized SOAP messaging for the purposes
of underscoring that:

SOAP messages are encoded with XML and thus make it a message-based
protocol.

Methods and parameters can be declared in a SOAP message, but
they ultimately are associated with service and typing information
(such as whether the parameters are integers, floating points, etc.),
so that translation of those messages is proper and accurate.

SOAP is a relatively simple protocol.

If you inferred that much from the above, you got the major points.
Time to move on.

Getting started

In the rest of this article, I will describe what you need to do to get
started with Axis. Afterwards , you should be able to:

Download and install Axis

Create and deploy web services

Access those services remotely over the network

Although it is possible to describe how to generally use Axis, I
am going to take a more "in the trenches" approach, since I want
you to be able to run the examples I describe. Although the existing
Apache Axis documentation does a fine job of getting you started,
it does take a little while to identify some of the key configuration
issues. My hope is that this document streamlines that process
even more.

Assumptions and Dependencies

First, keep in mind that this article pertains to the Beta 2 of
Apache Axis, released in April of 2002. Pre-production open source
software often changes and it may be possible that post-beta-2
changes make some of this document invalid, so please consider
that if trying to use this document with any other release of
Axis.

Second, since this document goes into the details of configuring Axis,
it makes some assumptions:

You are using Microsoft Windows 2000.

You have the Java 1.3 JDK

You have TCP/IP network access.

You have no services running on port 8080 of your machine
(although you could easily adapt the examples below if you do).

Third, before you get started with Axis, you also need to have a J2EE
compliant subsystem that implements the Java 2.2 Servlet specification.
A good candidate for that is the
Apache Tomcat
Java servlet container. This tutorial assumes that you are using
the latest (at least at this time!) stable version: Tomcat 4.03.
As you know, you can run Tomcat independent of your web server.
It runs on a specified port (8080 by default) and can be started
up with a simple boot script that is included with the release.
You can install Tomcat anywhere on your machine. It will likely
choose c:\Program Files\Apache Tomcat 4.0 by default. Whether it
is this or another location of your choosing, no matter - the
point of installation is referred to hereafter as $TOMCAT_HOME.

Now, just to make sure no odd problems occur during our installation
of Axis, make sure that Tomcat is not running. We will
start it up later.

Finally, to parse the XML, you need to have an XML parsing
library available, such as Xerces or the Java API for XML Processing (JAXP).
Opting for an all-Apache approach, I used
Xerces 2.0.1,
which comes with the following libraries (available in the top level
directory of the Xerces release):

xmlParserAPIs.jar

xercesImpl.jar

xercesSamples.jar

You probably only need the first two of these JAR files, but it is
important that you have Xerces 2 and that you know where these files are.
You will need them later.

Downloading, Installing, and Configuration

In this section, I describe how to download and configure Apache
Axis as a web application for your servlet container (Tomcat).
Once installed, clients will be able to access SOAP nodes on your
server via an Apache Axis servlet.

The first step is to download the
Axis release. This is usually
a ZIP file. At the time of this writing it was located
here.
You can install this release anywhere on your machine; for example,
I installed it under c:\Program Files\Apache Group\xml-axis-beta2.

The second step is to integrate Axis as a web application of
Apache Tomcat. This step is extremely simple: just copy (recursively)
the webapps/axis directory under the webapps directory of your
Tomcat installation (i.e., $TOMCAT_HOME\webapps). Next,
copy the XML parser libraries (such as the 3 Xerces JAR files mentioned
above) to the $TOMCAT_HOME\webapps\axis\lib directory.

Next, a very important point that is sort of buried in the
current Axis instructions and FAQ: relocation of the RPC library Axis uses.
Specifically, you need to move (or copy) the file lib/jaxrpc.jar to
common/lib directory, under your Tomcat home (i.e.,
$TOMCAT_HOME\common\lib).

Finally, one point about setting up your environment.
Later in this article, you will need to compile some Java classes.
To do so means that you need to setup your classpath to use the
Axis libraries. I find it most simple to define a setup file
that augments the classpath to include the following libraries
(all found in $AXIS_HOME/lib):

Before moving on, it might be useful to do a sanity check and
make sure that Tomcat works fine outside of Axis. That way, if
you have a problem in the next section, you can potentially
rule out Tomcat. So, for example, you should be able to
point your web browser at
http://localhost:8080/examples/servlets/index.html
and be able to execute the Hello World servlet example.

Web services made easy

Okay, you've downloaded and installed everything. You've ensured
that Tomcat works. Time to start building and testing out web
services with Axis. We'll start out with a very easy
example - this should quickly convince you how easy it is
to deploy web services with Axis.

Turning Java classes into instant web services

The easiest way to get started is to simply copy any
independent Java class into your Axis web application
directory and access it via SOAP remotely. This is easier
than you think. There are only three steps involved: (a) developing
the Java class, (b) deploying it, and (c) building and running
a client to access it.

The first step is to develop a Java class. Let's keep things
really simple and try out a Hello World -style class. We'll
develop one method, called greet() that takes someone's name
as a parameter and returns a nice greeting message with that
person's name.

To do this, locate the $AXIS_HOME/samples directory. Create
a new subdirectory called "hello". In this subdirectory,
create the file Hello.java, and include the following code:

NOTE:We're keeping Hello.java in the $AXIS_HOME/samples/hello
directory to keep things consistent with the rest of the Axis
built-in examples.

Now, do NOT compile Hello.java. Just copy it into
$TOMCAT_HOME/webapps/axis and name it Hello.jws. Clients (such
as the one we develop next) will request this service and the Axis
servlet will compile and execute our Hello.java class on the fly!
As you can see, developing a web service could not be more
painless. We didn't have to use a single library or implement
a single interface.

Accessing a web service

Time to build a client to access our service. This is where
we finally see some library code. But, as you will soon notice,
it's very simple and straightforward.

Again, to keep things consistent with the examples provided
by the Axis release, let us develop our client code in the
file HelloClient.java, which we will store at $AXIS_HOME/samples/hello.
In an abstract sense, HelloClient.java needs to do the following:

Connect to the our Hello service (a SOAP endpoint)

Invoke the service method remotely, marshalling parameters
in and out.

Here, there are obviously a few more things to note. Let's
take them one at a time.

Line 1: We place our code in the samples/hello package, to keep
things consistent with the other Axis examples.

Lines 15-20: We collect runtime options, such as the port
number of the destination service and the arguments to that service.

Lines 27-33: We set key parameters of our call to the remote
method. This is the heart of the client, where we set our
endpoint, describe the method we want to invoke and the parameters we
are providing, and then declare the return type of that method.
This prepares the remote call.

Line 35: We invoke the remote method and cast the
return object, since we know what know the type it will return.
Note that our runtime argument is passed in as a parameter as
part of an Object array. Thus, integers, strings, and other types
can be mixed (heterogenously) in this array for other types of
methods.

Line 37: We print out the reply.

Now, we can simply compile this client, specifically:

javac samples/hello/HelloClient.java

and then run the client:

java samples.hello.HelloClient -p8080 Greg

which returns the message:

Nice to meet you, Greg!

As you can see, development is pretty simple with Axis.
It hides behind the scenes and makes SOAP-based connectivity quick
and painless. Part of the magic behind why you were able to simply
copy the Hello.java file and have it accessible to your client
has to do with the $TOMCAT_HOME/webapps/axis/WEB-INF/web.xml
deployment descriptor file. In that file, you will find
the following section:

Figure 3

These instructions tell Tomcat to run the Axis servlet on
all requests to files that end in .jws. You'll also notice
that the compiled class is stored in $TOMCAT_HOME/webapps/axis/WEB-INFjwsClasses as Hello.class.

Wait, where's the SOAP?

The Axis API does such a good job of hiding the details
in example above, you're probably wondering: where is the SOAP?
Actually, on the wire, XML-encoded SOAP messages are being exchanged.
Axis comes with a tool called tcpmon that allows you to
see this (it monitors the target TCP port). If you were to look
at it, the request would look something like what you see in
Figure 4 and the reply like you see in Figure 5.

Figure 4

Figure 5

A more advanced example

As the Axis documentation suggests, there are a variety of cases
where you cannot simply copy your Java source files into the
web application deployment directory. You may not have the source
code or you may want to use other handlers during processing, etc.
Both reasons motivate us to look at a more general method for deploying
and accessing services with Axis

In this example, let us focus on the development and deployment
of a service that we will call "LoudService". This service takes
an input string and returns the uppercase form of the string, as
if the string were being spoken loudly.

The steps involved in development and deployment are:

Development of the LoudService class

Development of a LoudService client

Development of the deployment descriptor

Deployment of the service using the descriptor

Access by the client

Previously, steps 3 and 4 were hidden from us; now we will
perform them explicitly.

Developing the LoudService

The code for LoudService is just as simple as the code for the
Hello service we developed earlier:

Let us store this file in a new directory at $AXIS_HOME/samples/loud.
We can compile this file and store the resulting LoudService.class
in another new directory, this time under the Tomcat hierarchy:
$TOMCAT_HOME/webapps/axis/WEB-INF/classes/samples/loud.

Developing the client

Developing the client is not that much different from what
we did earlier. As the code below shows, the main difference
is that we use the QName API to specify the name of the service (LoudService)
and the method (serviceMethod) we intend to execute.
Notice that the endpoint URL is obtained automatically (in this
case, it is: http://localhost:8080/axis/servlet/AxisServlet --
the class and method are resolved dynamically at runtime).

We can then store this file in $AXIS_HOME/samples/loud and compile
it with the Java compiler.

Developing the deployment descriptor

The Axis web services deployment descriptor (WSDD) is an XML-encoded way of
specifying details about how SOAP-accessible functionality can
be deployed. There are a variety of options for deployment, but
we'll focus on the simple task of deployment as a web service.
The type of descriptor we need is shown in Figure 6. We don't have
the space to go into all of the options for how to deploy services;
but, using the example below, you should be able to get an idea.

Figure 6

We name this descriptor deploy.wsdd and store it in
$AXIS_HOME/samples/loud.

Deployment and client access

Now it is time to deploy our new service. To do that,
we use the Axis administrative service and call it with
the deployment descriptor above:

java org.apache.axis.client.AdminClient deploy.wsdd

The admin service reports that the service was loaded and
now you can use the client to access this service.

java samples.loud.Client "what did you say?"

which returns

WHAT DID YOU SAY?

Although this example was a little more complicated because
of the deployment considerations, we see that it is not terribly difficult
and in return we gain greater flexibility.

Conclusion

Of course, there are many more features and interesting details
related to Apache Axis than we can cover here. However, the
two examples we discussed above should hopefully clarify where
Axis fits in the overall web services architecture, give you a better
understanding about what Axis can do, get you started using its tools
and libraries, and leave you curious about more advanced features.
As you can Axis is simple,
easy to use, and powerful. We can deploy web services from
existing functionality in a very short time and thus
rapidly move towards true Internet distributed computing.

Logging in J2SE 1.4

The ability to log error, warning, or debugging information can be a critical part of any application. Logging
is so critical that logging systems have been independently developed and implemented hundreds if not thousands
of times. The Apache project developed a framework (log4j) which is widely used. With the release of J2SE 1.4,
we finally have a logging API built into the language. The new API is found in the package, java.util.logging.

The functionality of the logging API has been divided into three different types of objects. Logger objects
are the controllers. Handler objects determine where the logging information will be published. Formatter
objects control what the published log information will look like.

Listing 1 contains a listing of a program using logging. Listing 2
contains the log output of the program.

Loggers

Logger objects are the main entry points into the logging API. Messages you wish to log will be passed into
a logger object. The logger will determine if the message should be logged and send it to the appropriate Handler
object.

Loggers are not directly instantiated but are created with the getLogger(String loggerName) static method
of the Logger class. Logger objects are named using the package naming standard. Here is an example of creating
a Logger object:

Logger logger = Logger.getLogger("com.aag");

The Logger class has many methods that can be used to send log messages to the Handler objects. The basic version
is:

void log(Level level, String msg)

The Level class defines seven different levels as static constants. Ranging from highest to lowest, these are:
SEVERE, WARNING, INFO, CONFIG, FINE , FINER, and FINEST. To send
a warning level message to the log we created earlier we would use:

logger.log(Level.WARNING, "A warning message");

You can also use:

logger.warning("A warning message");

There is a version of the log method for each of the seven levels. There is also an overloaded version of the
log method that you can use to log exceptions:

The Logger class has a setLevel method that can be used to filter logging messages:

void setLevel(Level level)

The logger will ignore messages that are below the level specified in the setLevel method. For example, if you
wanted to ignore all messages except SEVERE and WARNING level messages, you would use:

logger.setLevel(Level.WARNING);

In addition to the seven static constant levels we mentioned earlier, the Level class also contains two other
constants. Level.ALL is used to accept all messages. This ends up being the same as specifying Level.FINEST. Level.OFF
is used to reject all messages sent to the Logger.

By default, the Logger object will send all messages to System.err in a format that is human readable. If some
other functionality is required, the API provides Handler and Formatter classes.

Handlers

A Handler object controls how messages are published but not how they will appear. The API provides five Handler
classes:

MemoryHandler ? sends the log messages to a memory buffer.

StreamHandler ? sends the log messages to an output stream. The other three
Handlers are sub-classed from StreamHandler.

ConsoleHandler ? sends messages to System.err.

FileHandler ? sends messages to a file. FileHandler allows you to create a group of rotating
files to hold log messages.

SocketHandler ? sends messages to a socket.

The Logger class has the addHandler(Handler handler) and removeHandler(Handler handler) methods to
determine which Handlers will receive log messages. To change the Logger to send all log messages to a
file named "out.log" instead of using the default ConsoleHandler, you would use:

Creating your own Handler class is fairly simple. The Handler abstract class contains only three methods:

public void close( )

public void flush( )

public void publish(LogRecord log)

I will leave it as an exercise for the reader to design a Handler that sends log messages to a JMS topic.

The level can be set for Handlers just as we can set it for Loggers. In this way a Logger can have multiple
Handlers attached that to it with each Handler processing messages based on its own level criteria. For example,
SEVERE messages could be sent to the console while INFO messages and above are logged in a file. To set the level
for a Handler to report only SEVERE messages, you would use:

handler.setLevel(Level.SEVERE);

Different Handlers have different default levels. ConsoleHandler uses Level.INFO as the default while FileHandler
uses Level.ALL as its default.

Formatters

In addition to controlling where messages are sent, the logging API also provides two classes to control the
appearance of the log messages. SimpleFormatter produces a log message in "human readable" form. This is the default
Formatter used by ConsoleHandler. XMLFormatter writes the log messages in an XML format. This is the default
used by FileHandler. Samples of both formats are shown blow. To change the FileHandler to use the SimpleFormatter
you would code:

Writing your own Formatter class is a simple exercise. The Formatter abstract class has three methods to use:

String format(LogRecord log)

String getHead(Handler handler)

String getTail(Handler handler)

The getHead( ) and getTail( ) methods are invoked at the beginning and ending of logging. These can be used
to specify information that should be written either before or after the actual logging data. The format( ) method
is invoked once for each message to be logged. The method is given a LogRecord object that contains all
the information about the log message. The LogRecord has several useful methods:

Level getLevel( ) - returns the Level of this LogRecord

String getMessage( ) - returns the actual message

long getMillis( ) - returns a long representing the date/time this LogRecord was created

String getSourceClassName( )returns the name of the class that generated this message

String getSourceMethodName( ) - returns the name of the method that generated this message

Throwable getThrown( ) - returns the exception associated with this log message if there is one

Filters

The logging API provides a Filter interface that can be used to filter messages either at the Logger or at the
Handler. The Filter interface contains one method:

boolean isLoggable(LogRecord log)

If the Filter returns false, the LogRecord is ignored and not sent or processed by the Handler. Filters can
be used to reject log records based on any criteria. For example, log records could be rejected based on the class
that generated them or the day of the week or by the message contents. Adding a Filter to a Handler or Logger is
done using the setFilter( ) method. An example of using this:

Conclusions

There are several areas where the logging API has some shortcomings. Security is an issue that may have potential
problems. Another area of potential annoyance is with multi-threaded applications. The API does not synchronize any
methods so there may be a problem of log messages not appearing in the order they were written to the log.

Overall, however, the logging API is a well written, if basic, logging system. I recommend that anyone doing
development examine this API to see if it meets their needs. For those who are unsatisfied with the API, the Apache
Project's log4j is available and continues in development.

Well, I was going to talk about Stereotyping this time - but that is such a SERIOUS topic. So I thought that we would just take a pause and go over some of the games that are played in JVMLand.

Let's go over the rules for the following games:

1. Dark Shadows

2. What's my Line

3. Hide and go Seek

I. Dark Shadows
This is a game of solitaire that is played by one object inside itself. The trick is to get one of your members to prevent another one from being seen. In order to do this you have to learn how to shadow the Scope of another member.

For instance, if you have an instance variable named x, you could cleverly create a local variable in a method with the SAME name. Now without that local variable it would be easy to get the instance variable using its simple name even from within the method. The scope of x extends into the method easily. But once you put in the local variable - poof - you have succeeded in shadowing x! Now the only way to get the instance variable is to specify "this.x" to tell it apart from your local x. (Very Wicked).

Now it's your turn. Go ahead and try this with any field, local variable, method parameter, constructor parameter or exception handler parameter.

Try it with Labels! Try it with methods! You can use a method of an inner class to shadow the method of the containing class and REALLY cause confusion! Notice that you can do all this with NO inheritance involved.

When you get to the advanced stage you can try shadowing types. If you put an import package statement at the top of your class that would bring in a class named X, then at the last minute use the single-import syntax (you know - where you provide the fully qualified name of a class) then you can shadow the type X class that WOULD have been used.

It's easy and it's fun!

II. What's my Line
This is a game similar to Dark Shadows but uses mixed double declarations. The trick is to make your names so obscure that you confuse the compiler so much that it can not tell what you are talking about. If you do it correctly, the compiler will resort to the rule book to make the decision on what to do.

For instance, take any two of the following: a variable, a class name or interface name, a package declaration. Now make sure that they have the exact same name. Now use that name to invoke an action.

For instance, create a class named ABC. Now have another class that is also visible that has an instance variable and name it ABC:
SomeClass ABC = new SomeClass();

Now go ahead and try to use ABC. Try using "ABC.x" and see what happens. The compiler sits there thinking - do they want a static variable named x from class ABC, or do they want the instance variable x from the object referenced by variable ABC???

HA! You have succeeded in obscuring the declaration. No way the compiler can figure it out. So it's time to go to the rules.

If you go ask the JLS Wizard (the keeper of the rules) he will say:
"In these situations, the rules specify that a variable will be chosen in preference to a type, and that a type will be chosen in preference to a package. "

So, in this case, the compiler will treat ABC as the variable instead of the class type. It will decide that you want the instance variable x from the object referenced by variable ABC.

Now it's your turn. Try it with interfaces and package names, or whatever combination you prefer.

But Beware!! If you get TOO obscure - so that the compiler can not decide which one to pick, you will get compliants about being "ambiguous". So if you inherit two different variables with the same name but different types - neither one will take priority and the compiler will be very upset.

III. Hide and go Seek
This is a game that is played by Parents and their Subs and is by far the most complicated. The rules go like this. The Parent has a bunch of members including methods, static methods, instance variables and static variables. All these things might potentially be inherited by the Sub. The Sub (either a sub-class or a sub-interface depending on who is playing) tries to hide the parent's member. If he succeeds in hiding it, the Sub gets a point. If he can't hide it, the Parent gets the point.

The test for whether or not it works is this:

It must compile cleanly.

The member must be available to be inherited. So a version of the Sub without the member of the same name should still be able to reference that name because it inherited it from the Parent.

Having the member in the Sub must cause the Sub's version to be used.

You must be able to get the Parent's version from a variable of the type of the Parent. This eliminates overriding from being the cause. If there is overriding, you just can't get that Parent's version. That late binding stuff is strict.

Of course anyone who has played this game very much realizes that the real trick to this game is making sure that you know what can be inherited and which of those can be overridden. Anything that can be inherited but can't be overridden - can be hidden.

For hiding variables with the same name it is almost TOO easy - the types do not even need to match.

If the Parent's member is a:

and the sub uses the same name for a:

Sub Score

Parent Score

Comments

>

static variable

static variable

+1

Get hidden using Parent.varName

static variable

instance variable

+1

Get hidden using super.varName or Parent.varName

instance variable

static variable

+1

Get at hidden using super.varName

instance variable

instance variable

+1

Get hidden using super.varName

private variable

any variable

+1

Can't hide what you can't inherit. But of course you can still HAVE a variable with the same name - it is just not hiding anything.

have the same return type (even though variables don't have to be the same type - methods DO - I know, life is not fair)

be as much or more accessible than the Parent

not have a throws clause that conflicts with the Parent throws - this keeps things typesafe

If the Parent's member is a:

and the sub uses the same name for a:

Sub Score

Parent Score

Comments

static method

static method

+1

Get hidden using Parent.methodName

instance method

instance method

+1

Polymorphism is not hiding

abstract method

any method

+1

Polymorphism is not hiding

static method

instance method

0

0

Compile error. Attempting to "override" a static method with an instance method.

instance method

static method

0

0

Compile error. Attempting to override an instance method with a static method.

final method

static or instance method

0

0

Compile error. Final means FINAL!

private method

Method with same return type and throws.

+1

Can't hide what you can't inherit - you just HAVE a method with same name.

Final class with regular method

Can't sub-class anyway.

+1

Can't hide what you can't inherit.

Constructor

Constructor

+1

Can't hide what you can't inherit. Heck, as constructors, they couldn't even be named the same name anyway.

Static initializer

Static initializer

+1

Can't hide what you can't inherit.

Instance initializer

Instance initializer

+1

Can't hide what you can't inherit.

So far the score is Subs 6 - Parents 8.

Once you get the hang of it - start trying it with inner classes. Do you REALLY know what you get because of scope and what you get because of inheritance? Now try it with inner classes that are ALSO sub-classes of the Parent. Or you could try double inheritance using interfaces. For a real challenge use sub-interfaces with inner classes. The possibilities are endless.

It's where you come to learn Java, and just like the cattle drivers of the
old west, you're expected to pull your weight along the way.

The Cattle
Drive forum is where the drivers get together to complain, uh rather,
discuss their assignments and encourage each other. Thanks to the enthusiastic
initiative of Johannes
de Jong, you can keep track of your progress on the drive with the Assignment Log. If you're tough enough to get through the nitpicking,
you'll see your name on the Graduation Log.

Gettin' them doggies...
The past month has been a whirlwind of ol' timers coming back, and spurs
being passed around like crazy! The list of
active drivers shows around 18 drivers lately, the majority kickin' up dust in
the OOP and Servlets corrals. Those doggies are the tough 'uns, so
writin' em up and cleaning out the nits takes a bit longer.

And a shiny spur goes to...
The past month has been wilder than a Texas Twister when it comes to
graduates!? Josue Cedeno wrangled his first graduation by passing through the Java Basics course.? Good job Josue!

At the OOP
corral, Rick Prevett and Sam Tilley blazed through the
assignments and got themselves a second spur.? Y'all done real good!

Back from being out on the range...
We're glad to announce that Joel Cochran and Paul Ralph decided
they had enough of the easy life and came back to the dirt and the grime
that is the Cattle Drive.? Glad to have y'all back, we're planning on
workin' ya hard!

Saddle sore... Ronald Schindler has got his eye on the silver spur for OOP.?
Keep wrastlin' with the code, Ronald, you'll be there in no time!

Peter
Gragert is serving up his final assignment in the Servlets
section.? We'll save you a seat at the graduation saloon!

And it's
finally here, the instructor's solution to JDBC-4 has been completed.? Jason Adam and Lance
Finney can see their JDBC spur on the horizon.

Nitpicking is hard work too...
We know they're workin' reeeeeally hard, after all we've seen what those assignments look like once the nitpickers have combed through 'em. Hats off to Marilyn deQueiroz and Jason
Adam for their dedication and patience with the pesky vermin that always manage to make their way into those assignments.

Tips for the Trail?
While comments are good to have, and can help clarify parts of your code,
too many comments can make a program unreadable.? Instead, focus on
writing code that uses identifiers and expressions that explain themselves,
and leave comments to the trickier parts of your program.? Like
we've mentioned time and again, readability is one of the most important
goals of the Cattle Drive, and for writing code in general!

Take the most popular J2EE resource - theserverside.com. Have the people who actually built the site using J2EE technologies throw in the best practices as EJB design patterns. Open the stage for hundreds of developers to read, critique and say yea or nay. Painstakingly update the pattern repository incorporating the developer feedback. Repeat this process for nearly a year. What do you get? The best catalog of EJB design patterns ever written - by developers for developers.

Let?s face it. Many of the standard GOF design patterns are hard to apply in the EJB world. The learning curve is steep and the mistakes can be very expensive. This book gives you everything you need to design, develop, deploy and maintain industry strength J2EE applications using EJB technology.

The book is divided into two parts. Part one - EJB Pattern Language is a repository of the true and the tried strategies such as Transaction and Persistence Patterns, Session Facade, and Message Facade, JDBC for reading, Versioning etc. Part Two - titled "Best Practices for EJB Design and Implementation" is a collection of idioms, tips, do's and dont's specific to EJB projects.

This book is a great working reference, every EJB developer must have on the bookshelf. For those who have just begun their journey through the J2EE land, getting started with "Mastering Enterprise JavasBeans-2nd Edition by Ed Roman" provides the required background.

The book comes with a nifty chart for quick reference. The implementations can be downloaded freely from theserverside.com.

These folks were all selected based on their history of helpful, informative posts, and we're very happy to have them join us. Welcome, all!

Also, you'll notice that many of the other bartender names are moving around to different forums, as we've given everyone a chance to move around and try new things if they wish. So, if you see that your favorite forum has a new bartender, please make him/her welcome there. Enjoy...

As always JavaRanch is dedicated to providing you with the best source of information on Java Programming and Engineering.