Tuesday, December 13, 2011

An EO validation rule that involves a transient attribute

Problem
Say you have a VO with a transient attribute (e.g., AmountSpent), and an entity-based attribute (e.g., MaxAmount).  The value of AmountSpent (the transient attribute) is set when the application starts.  Then, the user enters a value for MaxAmount (the entity-based attribute) in the UI.

Now, say you need to validate that MaxAmount is greater than AmountSpent.  The transient attribute does not exist in the EO, so a simple Compare validation rule is not possible.

How can you do this? 

Solution
First, create a method on the Application Module to return the value of the transient attribute:

  public Number getAmountSpent() {
    AmountVOImpl vo = this.getAmountVO1();
    AmountVORowImpl row = (AmountVORowImpl)vo.getCurrentRow();
    return row.getAmountSpent();
  }

Next, create a validation rule on the entity-based attribute (MaxAmount).  In this rule, compare the value of MaxAmount to a Groovy expression that calls the AM method. Here's the expression:

  source.getDBTransaction().getRootApplicationModule().getAmountSpent()

Note that you need to use "source" at the start of the Groovy expression. The reason for this is explained in the Fusion Dev Guide.

This rule will give you the validation you need.

Monday, November 21, 2011

Invoking a web service from an ADF managed bean


In this post I describe how to invoke an external web service from an ADF managed bean.  The web service is represented by a web service proxy within the ADF Model project.  The proxy is exposed as a client method on the application module.  A method in a managed bean invokes the client method.

This example uses JDeveloper 11.1.1.3.  The external web service is based on the Cue Cards example “Create a Web Service from a Java Class” found in the JDeveloper Help Center.

See Chapter 13 “Integrating Web Services Into a Fusion Web Application” in the Fusion Developer’s Guide for more information.

Create the proxy


1.       In the Model project, launch the Create Web Service Proxy wizard.

2.       Choose JAX-WS Style.



3.       Enter the WSDL URL and select Copy WSDL Into project.


4.       In the Specify Default Mapping Options window, enter package names that cleanly separate the proxy files from ADF BC components.  E.g., if your ADF BC components are under the package app1.model, then enter:
·         Package Name = app1.proxy.<proxy name>
·         Root Package for Generated Types = app1.proxy.<proxy name>.types


NOTE:  If the web service has asynchronous callback methods, the “Generate As Async” checkbox is enabled.  If you do not plan to use the callback methods, uncheck this box box.  Leaving the box checked creates un-needed web services and a WAR file in the project.

5.       If you do not use the asynchronous callback methods select “Don’t generate any asynchronous methods” in Step 6.


6.       Click Finish.

7.       The JDeveloper workspace looks like this.  Proxy files are cleanly separated from ADF BC components.  Note the jax-ws-catalog file under META-INF.  This is useful for editing the URL endpoint of the web service.



Create an application module method to invoke the proxy


1.       Generate an application module class and open it in the editor.  This is the <AppModule>Impl.java file.

2.       Add a method that instantiates the proxy class and invokes the web service.  For example:

       public int getCreditRating(String ssn) {
           // Instantiate the proxy
           CreditRatingService svc = new CreditRatingService();
           CreditRating creditRating = svc.getCreditRatingSoap12HttpPort();
      
           // Invoke service
           int result;
           try {
               result = creditRating.processRating(ssn);
               System.out.println("  ==Got credit rating");
           } catch (Exception e) {
               result = -1;
               System.out.println("  ==Exception: " + e.getMessage());
               e.printStackTrace();
           }
      
           // Return result
           return result;
       }


3.       Add the new method to the application module client interface


4.       Refresh the Data Control panel

5.       Open the page you want to invoke the method from > go to the Bindings tab > add the operation as an Action Binding


6.       You can now invoke the method from a managed bean, using code like this:

       public void onGetCreditRatingAction(ActionEvent actionEvent) {
           BindingContainer bc =
               BindingContext.getCurrent().getCurrentBindingsEntry();
           OperationBinding ob = bc.getOperationBinding("getCreditRating");
           ob.getParamsMap().put("ssn", "123456789");
           System.out.println("  ==About to get credit rating ...");
           String result = (String)ob.execute();
           System.out.println("  ==Credit rating: " + result);
       }


Saturday, November 19, 2011

Learn ADF

I often come across someone asking for advice on how to start learning ADF.  I point them to this blog post by Shay Shmeltzer.

Another way for beginners to get their feet wet is to go thru the "Cue Cards" exercises under the JDeveloper Help Center.

More advanced learners can go straight to the ADF Insider page.  This page has more than 40 recorded presentations on topics from basic to advanced.