Recipe20.1.Validating Parameters Passed to a Method


Recipe 20.1. Validating Parameters Passed to a Method

Problem

You want to validate the parameters passed to a method.

Solution

Create an aspect that modularizes the parameter checking logic. Declare a pointcut to capture the execution of the method where the parameters are to be checked. The pointcut should expose the parameters to the corresponding advice so it can perform the checks.

Depending on the result of the parameter checking, the advice will proceed with the methods execution or safely override the method whenever the parameters are not suitable.

Discussion

Validation of method parameters is a chore every developer has to be concerned with whenever he has no control over how his clients will use a component. Even when the developer is writing the clients that will use a particular component, a useful practice would be to the values passed to a method are acceptable before working with those values.

This checking often confuses the logic within a method by introducing initial checking code that has little relationship to the job that the method is to complete. By using AspectJ, you can check a method's parameters separately from the core business logic of a method to make the solution cleaner.

The main method on a Java application is a common place where the parameters being supplied cannot be controlled and have to be checked before the application can continue execution. The normal means of achieving these checks is to code the test logic using an if statement into the main method and to produce an error message if the parameters provided on the command line do not meet the requirements of the application.

Example 20-1 shows a typical main method with the traditional parameter validation and checking support code highlighted.

Example 20-1. Interleaving traditional command-line argument checking with the business logic of the main method
package com.oreilly.aspectjcookbook; import java.net.URL; import java.net.MalformedURLException; public class TraditionalMainApplication {    private static final String COMMAND_LINE_USAGE =           "TraditionalMainAppliction usage :\n\n" +          "\tjava TraditionalMainApplication <url>";    public static void main(String[] args)    {       if (args.length == 1)       {          try          {             // Assuming that the first argument supplied is a url             // Concentrating on the business logic, not validation which             // is handled by the aspect.             URL url = new URL(args[0]);             System.out.println("Application Started, doing stuff with " + url);          }          catch (MalformedURLException mue)          {             System.err.println(COMMAND_LINE_USAGE);             System.err.println("Please enter a valid URL for <url>");          }       }       else       {          System.err.println(COMMAND_LINE_USAGE);       }    } }

First, the traditionalMainApplication class declares the COMMAND_LINE_USAGE constant that contains a message that will be displayed to the user if a problem occurs with the arguments passed to the main method. Then an if statement within the main method checks that the right number of arguments have been supplied; if not, the error message is displayed. Finally, one of the parameters is a URL, and since this could be invalid, this is checked by a try/catch block. All of this occurs before the main method can do anything useful such as starting the application.

Refactoring the checking logic into a separate method moves the problem to another part of the same class and doesn't offer a satisfactory solution. AspectJ can remove these messy beginnings to your application by creating an aspect such as the one shown in Example 20-2.

Example 20-2. Parameter checking using an aspect
package com.oreilly.aspectjcookbook; import java.net.URL; import java.net.MalformedURLException; public aspect VerifyMethodArgsAspect {    private static final String COMMAND_LINE_USAGE =        "MyAppliction usage :\n\n" +       "\tjava MainApplication <url>";        public pointcut captureMain(String[] arguments) :        execution(void MainApplication.main(String[])) &&        args(arguments);    public pointcut createURLCalledinMainMethod( ) :        call(java.net.URL.new(..)) &&        withincode(public void MainApplication.main(String[]));        void around(String[] arguments) : captureMain(arguments)    {       if (arguments.length == 1)       {               // Test that the host and port are valid          try          {             URL url = new URL(arguments[0]);             proceed(arguments);          }          catch(MalformedURLException mfe)          {             System.err.println(COMMAND_LINE_USAGE);             System.err.println("Please enter a valid URL for <url>");          }       }       else       {          System.err.println(COMMAND_LINE_USAGE);       }    }        // If necessary soften the exception that would normally have been raised    // if the url parameter was badly formed, but only in the validated main     // method    declare soft : MalformedURLException : createURLCalledinMainMethod( ); }

The VerifyMethodArgsAspect aspect declares the captureMain(String[]) pointcut that interrupts the execution of the main method and provides the arguments to the corresponding advice. The around( ) advice then checks the number of parameters and that the URL parameter is valid before calling proceed( ) with the original arguments if everything checks out. If any problems occur with the arguments then the error messages are displayed in the same way as before.

Using an aspect to modularize the parameter checking logic leaves your main method looking much neater without losing any of that important checking behavior, as shown in Example 20-3.

Example 20-3. Providing the parameter checking logic via an aspect leaves the main method to focus on its job
package com.oreilly.aspectjcookbook; import java.net.URL; public class MainApplication {    public static void main(String[] args)    {       // Assuming that the first argument supplied is a url       // Concentrating on the business logic, not validation which       // is handled by the aspect.       URL url = new URL(args[0]);              System.out.println("Application Started, doing stuff with " + url);    } }

The main method logic still uses the URL argument as before, but because the aspect has provided the necessary checking to ensure a problem will not occur, it is reasonably safe to use the declare soft statement to save the main method from having to explicitly handle the MalformedURLException.

The createURLCalledinMainMethod() pointcut captures where the exception would normally be raisedi.e., when a java.net.URL instance is created and within the main methodand this is the only join point where the MalformedURLException is to be softened. Without this softening of the exception, the main method would have to handle the possibility of a MalformedURLException being thrown even with the aspect based checking.

See Also

The execution(Signature) pointcut is described in Recipe 4.4; The args([TypePatterns || Identifiers]) pointcut is covered in Recipe 11.3; the around( ) form of advice is shown in Recipe 13.4; softening exceptions is discussed in Recipe 16.5.



AspectJ Cookbook
Aspectj Cookbook
ISBN: 0596006543
EAN: 2147483647
Year: 2006
Pages: 203
Authors: Russ Miles

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net