Some reader favorites:
EJB fundamentals and session beans
Create a scrollable virtual desktop in Swing
More action with Struts 2
In a recent review of Struts 2 in Action, JW Blogger Oleg Mikheev notes that Struts 2 is "just a collection of extensions built upon WebWork, which is ultimately
the right thing to learn before starting a Struts 2 project." While Struts 2 has some architectural flaws, Oleg calls WebWork
well-designed, well-tested, and reliable. What are your experiences using Struts 2 and WebWork?
Also see "Hello World the WebWork way," a JavaWorld excerpt from WebWork in Action, by Patrick Lightbody and Jason Carreira.
| Memory Analysis in Eclipse |
| Enterprise AJAX - Transcend the Hype |
We will consider each use in turn.
Sometimes, however, this isn't acceptable. In such cases, you need an approach that doesn't require packaging the GUI and the functionality together. Custom scoping allows the two to be separate, and still protects the functionality from scripting.
String class. If an object's state cannot change, references can be safely passed to the object throughout the application.However, this doesn't always work. A data-processing program might start with an object containing raw data and slowly add information to the object as it passes through the application. A good example of this would be a stock-screening application that starts with objects containing raw stock data, and then adds more information -- the performance of a single stock relative to the industry, say -- as the objects are processed.
In a small application, you can provide the add methods with a javadoc saying, in effect, "Don't call this unless you are the relative performance comparator." As the application
gets larger, and more engineers work on it, this approach becomes riskier. Hardcoding restrictions into the program, instead
of using comments and hoping that everyone reads them, allows the application to detect access bugs automatically.
public class ImmutableIntArray
{
private int[] data;
public ImmutableIntArray (int[] data)
{
this.data = data;
}
int getElementAt (int index)
{
return data[index];
}
}
There is no method that returns the raw data element, because this would defeat the purpose of making the object immutable. Occasionally, however, client code may need to process the contents of data quickly. Although it may take too long to return a copy of the data, working on the raw data element might be fast enough. It would be a reasonable design decision to grant access to data only to those clients who need it, and not to the entire application.
You can create objects whose class names are visible to the entire program, but which can only be constructed by very restricted clients. The objects of these classes can then be used as key objects. Callers are required to pass in these key objects to method calls, and the method being called can check them against a list of legal keys.
Here's a working example of this:
public class Main
{
static public void main (String[] args)
{
try
{
System.out.print ("This should work ...");
ValidExampleCaller.sampleMethod();
System.out.println (" and it did.");
}
catch (InvalidKeyException e1)
{
e1.printStackTrace();
}
try
{
System.out.println ("This should fail ...");
InValidExampleCaller.sampleMethod1();
}
catch (InvalidKeyException e2)
{
e2.printStackTrace();
}
}
}
/**
*
*/
class InvalidKeyException extends java.lang.Exception
{
public InvalidKeyException (String message)
{
super (message);
}
}
class ExampleCallee
{
/**
* This method prints 'Hi!' to standard out, but can only
* be called by the ExampleCaller class.
*
* @param key 'key' is an object restricting access to this
* method. If 'key' is not an instance of
* class ValidExampleCaller.Key, an InvalidKeyException
* is thrown.
*/
public static void sampleMethod (Object key) throws InvalidKeyException
{
if (key.getClass().getName().equals ("ValidExampleCaller$Key") == false)
throw new InvalidKeyException("Can't call sampleMethod() with key " + key);
System.out.println ("Hi!");
}
}
class ValidExampleCaller
{
static private final class Key
{
}
static public void sampleMethod () throws InvalidKeyException
{
ExampleCallee.sampleMethod (new Key());
}
}
class InValidExampleCaller
{
static private final class Key
{
}
static public void sampleMethod1 () throws InvalidKeyException
{
ExampleCallee.sampleMethod (new Key());
}
}
The ExampleCaller class can call the sampleMethod in ExampleCallee successfully, but no other class can.
Before using this approach, you should consider a number of its details and implications:
ExampleCallee depends on ValidCaller's cooperation: The ExampleCallee class depends on ValidCaller cooperation in enforcing the scoping restrictions. ValidCaller can cheat by making the Key class public, or by handing out references to Key objects. However, even with standard scoping, legal callers can cheat. Our approach assumes cooperation between the valid
caller classes and the callee, just as standard Java scoping does.Key object is a static inner class: This means that both static and nonstatic member functions in the ValidCaller class have access to sampleMethod. To prevent static methods from calling sampleMethod, make the Key object nonstatic.Key object is a private inner class: Making Key private means that subclasses of ValidCaller cannot construct Key objects. Making Key a protected inner class grants access to child classes as well.Key need not be an inner class: Key could be a package-scope class if your intent is to grant any class in a package access to sampleMethod().Key must not be anonymous: The Java language does not specify a naming convention for anonymous inner classes, and different compilers generate different
names for anonymous inner classes. Because of this, you should name the Key class.Standard Java scoping is sufficient for most projects. For large projects, however, you occasionally need to construct very specific scoping relationships. The approach to doing so presented in this article uses only the standard JDK 1.1 language constructs, and does not require any extensions to the Java language. This approach does add some complexity, though, so you should use it with caution. If you find yourself using this technique often, you need to reconsider your design.