Search This Blog

Loading...

Friday, August 26, 2011

ADF: Oracle ADF task flows


Task Flow-

ADF Task Flows is a new feature that will ship with ADF 11g. In simple terms, it is a tool to encapsulate page flow/navigation. A set of ADF Controller activities, control flow rules and managed beans that interact to allow a user to complete a task. It is much more than that in reality. A set of screens grouped into a Task Flow can be reused from wherever the application requires the same business function. A task flow can be a completely independent component with interaction through input and return parameters. 

A cool feature is when a task flow is generated as using page fragments (Note: a task flow can have either JSF Pages or JSF Fragments; not both). Such a task flow can be embedded into an existing screen as a region, so you have a main frame that stays static while a sub region contains an entire flowThe main component is the task flow definition file. This is an xml file on the lines of the faces-config.xml and adfc-config.xml. The various pages in a flow are represented by a view component and the navigation between the pages by a control-flow.

he return from a task flow is defined as a task-flow-return element. Note that this does not need to know where the task flow was called from. Of course, that’s necessary for a task flow to be reusable. Every task flow to be used in the application is then defined in adfc-config.xml. A task definition file can be dragged into the adfc-config in design mode. Navigations to a task flow are defined as control flows in adfc-config. These control flows can be anonymous so that they can be used from any JSF page in the application.

Bounded task flow represents modular and reusable application flows with a defined entry (i.e., default activity) and zero to many defined exit points (i.e., task flow return activities). They can be called from other task flows, referenced from a browser URL or embedded as a region in a view. They support reuse, parameters, transaction management and reentry.

A specialized form of ADF Controller task flow that has a single entry point and zero or more exit points. It contains its own set of private, control flowregion. Bounded task flows should be used for every other situation. In most circumstances these bounded rules, activities, and managed beans. A bounded task flow allows reuse, parameters, transaction management, and reentry. When dropped on a page, it becomes a
task flows will be hosted within the core page on the unbounded task flow and, as such, will be made up of JSF fragments rather than whole pages. A called ADF bounded task flow can accept input parameters and can pass return values to the caller upon exit

In addition, bounded task flows have the following features:
Operate within their own private memory scope–page flow scope are loaded lazily at runtime A new instance of TaskFlowContext (can be accessed using EL ${controllerContext.currentViewPort.taskFlowContext}) will be created each time a bounded ADF flow is entered. This context:

Manages the lifespan of all DataControl instances within the bounded task flow holds the information about the task flow ID and whether or not it contains uncommitted data.Don’t support multiple transactions when sharing the data control frame with parent flow To call a bounded task flow directly from a URL, the default activity must be a view activity can be set to be critical (i.e., dictates the framework to create an implicit save point when entering a bounded task flow. Also helps to prevent users from closing the browser window or browser tab if uncommitted data is present).

If protected by ADF Security, authorization is checked first.You can create train-based activities in a bounded task flow and only one train is allowed in each.Bounded task flow should be used if it:
Should be reused in same or other applications
Should run as part of a page within a region container
Requires an isolated transaction context
Changes data and then either commits or rollbacks on exit
Has a requirement for a single entry point

A Fusion web application always contains an ADF unbounded task flow, which contains the entry point or points to the application. Its XML configuration file (i.e., adfc-config.xml) is automatically created when building a new application using the Fusion Web Application (ADF) application template or when adding the ADF Page Flow Technology Scope to an existing or new web project. There will always exist a single instance of unbounded task flow at runtime, even if there is no activity added to it.

A set of activities, ADF control flow rules, and managed beans that interact to allow a user to complete a task. An unbounded task flow has a single point of entry. unbounded task flow should only be used to
define entry points to your application, for example the home page, pages that will be deep linked from emails and so on.

A unbounded task flow has the following features:

You cannot declaratively specify input parameters for it.It cannot contain a default activity (i.e., an activity designated as the first to run in the task flow). This is because an unbounded task flow does not have a single point of entry.It can be configured by one or many configuration files that are parsed and loaded the first time the user starts the application.View activities of an unbounded task flow can be configured bookmarkable managed beans that are in session or application scope should be configured in the unbounded task flow definition.You cannot create a train from activities in an unbounded task flow.You cannot use a task flow template as the basis for creating a new unbounded task flow


Read more: http://www.techartifact.com/blogs/2011/07/basic-of-task-flow-in-oracle-adf.html#ixzz1W5dfUEkI

Test: Unit Testing for Java EE

Think testing Java EE applications is difficult, inconvenient, or too complex? Learn why this isn't the case and how do unit testing efficiently in this article.



Testing is one of the remaining mysterious areas of Java Platform, Enterprise Edition (Java EE). It is a common misconception that testing Java EE applications is hard, inconvenient, or too complex. This has not been true since the inception of Java EE 5 more than five years ago. In this article, I delve into unit testing. In a subsequent article, I will explore integration and embedded container tests.

Ask an Oracle About the Future of Java

I will use an “oracle” application that is able to predict the future of Java by using some consultants behind the scenes. For clarification, an “oracle” is defined as follows:
“In Classical Antiquity, an oracle was a person or agency considered to be a source of wise counsel or prophetic opinion, predictions or precognition of the future, inspired by the gods. As such it is a form of divination.” [http://en.wikipedia.org/wiki/Oracle].
In modern times, even an oracle would rely on representational state transfer (REST) to expose his predictions (see Listing 1). OracleResource is an Enterprise JavaBeans (EJB) 3.1 bean, which is exposed via Java API for RESTful Web Services (JAX-RS) as a REST resource and gateway to Contexts and Dependency Injection (CDI) managed beans. OracleResource maintains an injected pool of consultants (Instance<Consultant> company) and asks the first consultant to predict the future of Java.
@Path("javafuture")
@Stateless
public class OracleResource {
  @Inject
  Instance<Consultant> company;
  @Inject
  Event<Result> eventListener;
  @GET
  @Produces(MediaType.TEXT_PLAIN)
  public String predictFutureOfJava(){
         checkConsultantAvailability();
         Consultant consultant = getConsultant();
         Result prediction = consultant.predictFutureOfJava();
         eventListener.fire(prediction);
         if(JAVA_IS_DEAD.equals(prediction))
            throw new IllegalStateException("Please perform a sanity / reality check");
         return prediction.name();
  }
  void checkConsultantAvailability(){
      if(company.isUnsatisfied())
         throw new IllegalStateException("No consultant to ask!");
 }
 Consultant getConsultant(){
   for (Consultant consultant : company)
        return consultant;
   return null;
 }
}
Listing 1: EJB 3.1 Bean as a REST Resource and Gateway to CDI Managed Beans
Consultant is a Java interface implemented by a Blogger, ReasonableConsultant, and SmartConsultant. OracleResource just picks the first one and asks it about the future. All answers are accepted, except JAVA_IS_DEAD, which causes an IllegalStateException. Usually, you would use a javax.inject.Qualifier to disambiguate your choice, but a javax.enterprise.inject.Instance is harder to test, so I used that to make testing more “interesting.”
public class Blogger implements Consultant{
  @Override 
  public Result predictFutureOfJava() {
         return Result.JAVA_IS_DEAD;
  }
}
Listing 2: A Blogger Consultant Implementation
All predictions are distributed as transactional events. Each prediction is executed in an independent transaction started by the EJB container. It is the convention; no additional configuration is required for this purpose.
The event is received by a PredictionAudit EJB 3.1 bean, which persists all successful and failed predictions with Java Persistence API (JPA) 2, since some consultants are known for rolling back their decisions (see Listing 3).
@Stateless
public class PredictionAudit { 
  @PersistenceContext
  EntityManager em; 
  public void onSuccessfulPrediction(@Observes(during= TransactionPhase.AFTER_SUCCESS) 
                                     Result result){
         persistDecision(result,true);
  }
 public void onFailedPrediction(@Observes(during= TransactionPhase.AFTER_FAILURE) 
                                Result result){
       persistDecision(result,false);}
 void persistDecision(Result result,boolean success) {
      Prediction prediction = new Prediction(result,success);
      em.persist(prediction);
 public List<Prediction> allDecisions(){
        return this.em.createNamedQuery(Prediction.findAll).getResultList();}
}
Listing 3: Event-Driven PredictionAudit
The CDI event nicely decouples the OracleResource from the PredictionAudit, but it makes testing harder at the same time. The JPA 2 entity Prediction is persisted on each prediction, regardless of whether the transaction is committed or rolled back (see Listing 4).
@Entity
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@NamedQuery(name=Prediction.findAll,query="Select d from Prediction d")
public class Prediction {
 public final static String PREFIX = "com.abien.testing.oracle.entity.Prediction.";
 public final static String findAll = PREFIX + "findAll";
 @Id
 @GeneratedValue
 @XmlTransient
 private long id; 

 @Column(name="prediction_result")
 @Enumerated(EnumType.STRING)
 private Result result; 
 @Temporal(TemporalType.TIME)
 private Date predictionDate;
 private boolean success;
 public Prediction() {
        this.predictionDate = new Date();
 } 
 public Prediction(Result result, boolean success) {
        this();
        this.result = result;
        this.success = success;
 }
//bookkeeping methods omitted
}
Listing 4: JPA 2 Entity Decision 

Maven 3 and Unit Testing—Before You Start 

There is nothing special about unit testing Java EE 6 applications. You only have to add the JUnit library into your pom.xml file (see Listing 5) and put your classes into the src/test/java directory. All JUnit tests will be executed automatically during the standard Maven lifecycle: mvn clean install.
 <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>4.8.2</version>
   <scope>test</scope>
</dependency>
Listing 5: JUnit Library Inclusion in pom.xml
You will get a strange error by loading the Java EE 6 API classes included by the standard Maven archetype (see Listing 6).
 <dependency>
  <groupId>javax</groupId>
  <artifactId>javaee-web-api</artifactId>
  <version>6.0</version>
  <scope>provided</scope>
</dependency>
Listing 6: Unusable Reference to API
The standard Java EE 6 APIs in the Maven repository were processed by a tool, which removes the method body implementation from the bytecode and makes the javaee-web-api dependency unusable for unit testing. Any attempt to load the classes from the Java EE 6 API leads to an error like the following:
Absent Code attribute in method that is not native or abstract in class file javax/enterprise/util/TypeLiteral
java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/enterprise/util/TypeLiteral
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
Listing 7: Error Caused by Loading a Class from Java EE 6 API
You should replace the Java EE 6 API classes by the application vendor implementation. For GlassFish v3.1, the most convenient way is to use the single dependency on the embedded container:
 <dependency>
  <groupId>org.glassfish.extras</groupId>
  <artifactId>glassfish-embedded-all</artifactId>
  <version>3.1</version>
  <scope>provided</scope>
</dependency>
Listing 8: Java EE 6 API Replacement
You could, of course, pick and choose the CDI, JPA, EJB, etc. libraries for JUnit testing or compilation, or you could use working alternatives from JBoss or Geronimo Maven mirrors.

Why Drink Mockito?

Mockito is an easy-to-use, open source mocking library. Mockito is able to create “smart proxies” (a.k.a. mocks) from classes or interfaces. These proxies do not come with any behavior, but they are still perfectly usable. You can invoke methods, but will get the default values, or null, back. The behavior of the mocks can be recorded after their creation with when(mock.getAnswer()).then(42) syntax.
Mockito is perfectly suitable for “simulating” any inconvenient classes, resources, or services. You can start with Mockito just by knowing a single class org.mockito.Mockito. The when-then “domain specific language” is composed of static methods from the Mockito class. The org.mockito.Mockito class is well documented. In fact, the whole documentation set was generated from the JavaDoc markup in the org.mockito.Mockito class.

Unit Testing Java EE 6 with Some Mockito

PredictionAudit is intended to set the “success” flag dependent on the transaction outcome and use the EntityManager to persist the Prediction entity. To test the PredictionAudit class precisely will have to “simulate” the EntityManager. We will test only whether the method EntityManager#persist receives the correct parameter, not whether the Prediction entity is actually persisted. (We will explore integration testing of the interaction between PredictionAudit and the actual JPA EntityManager functionality in a subsequent article.)
A mocked-out EntityManager instance is created with the static and generified mock(EntityManager.class) method.
import static org.mockito.Mockito.*;
public class PredictionAuditTest {
   private PredictionAudit cut; 


   @Before
   public void initializeDependencies(){
     cut = new PredictionAudit();
     cut.em = mock(EntityManager.class);
  @Test
  public void savingSuccessfulPrediction(){
    final Result expectedResult = Result.BRIGHT;
    Prediction expected = new Prediction(expectedResult, true);
    this.cut.onSuccessfulPrediction(expectedResult);
    verify(cut.em,times(1)).persist(expected);}
 @Test
 public void savingRolledBackPrediction(){
   final Result expectedResult = Result.BRIGHT;
   Prediction expected = new Prediction(expectedResult, false);
   this.cut.onFailedPrediction(expectedResult);
   verify(cut.em,times(1)).persist(expected);}
}
Listing 9: Unit Testing and Mocking of PredictionAudit
The mocked-out EntityManager instance is directly injected into the default visible field PredictionAudit#em. Within the test method savingSuccessfulPrediction (see Listing 9), a Result instance is created and passed to the onSuccessfulPrediction method, which creates a Prediction instance and invokes the EntityManager#persist (see Listing 3). The static method verify(cut.em,times(1)).persist(expected) verifies whether the EntityManager#persist method is invoked exactly one time with the expected parameters.

A More Complex Mocking Case

The EJB 3.1 OracleResource bean’s injection of the javax.enterprise.event.Event and javax.enterprise.inject.Instance instances is far more interesting to test. The initialization and mocking of CDI dependencies is performed again with the Mockito#mock method (see Listing 10).
public class OracleResourceTest {
  private OracleResource cut;


  @Before
  public void initializeDependencies(){
    this.cut = new OracleResource();
    this.cut.company = mock(Instance.class);
    this.cut.eventListener = mock(Event.class);
  }
Listing 10: Initialization and Mocking of CDI Dependencies
Let’s start with a test of the helper method checkConsultantAvailability verification of the consultant’s availability. We expect an IllegalStateException if no Consultant implementation was found. The static method Mockito#when records expected behavior for an instance returned by the Mockito#mock method. We just return true for the method Instance#isUnsatisfied and expect an IllegalStateException:
 @Test(expected=IllegalStateException.class)
 public void checkConsultantAvailabilityWithoutConsultant()
 {
  when(this.cut.company.isUnsatisfied()).thenReturn(true);
  this.cut.checkConsultantAvailability();
 }
Listing 11: Prerecording Mock Behavior
The EJB bean OracleResource throws an IllegalStateException if a Consultant offers an insane prediction. The Blogger implementation of the Consultant interface always returns JAVA_IS_DEAD, which causes the IllegalStateException. To test that behavior, we have to mock out the Iterator returned by javax.enterprise.inject.Instance:
 Iterator mockIterator(Consultant consultant) {
   Iterator iterator = mock(Iterator.class);
   when(iterator.next()).thenReturn(consultant);
   when(iterator.hasNext()).thenReturn(true);
   return iterator;
 }
Listing 12: Mocking Out the Iterator
We change the behavior of Instance to return the mocked-out Iterator instance instead:
 @Test(expected=IllegalStateException.class)
 public void unreasonablePrediction(){
   Consultant consultant = new Blogger();
   Iterator iterator = mockIterator(consultant);
   when(this.cut.company.iterator()).thenReturn(iterator);
   this.cut.predictFutureOfJava();
}
Listing 13: Returning the Mocked-Out Iterator
Mocking out the instance gives you control over which Consultant implementation is actually used. In our case, we can just use the Blogger implementation to check whether the IllegalStateException is properly thrown. You could also create a Consultant mock and return it instead of the real Blogger instance. This would be especially reasonable for a Consultant implementation with heavy dependencies on the Java EE platform.
The Event instance was also mocked out, which allows you to verify already-performed method invocations:
 @Test
 public void unreasonablePredictionFiresEvent(){
  Consultant consultant = new Blogger();
  Result expectedResultToFire = consultant.predictFutureOfJava();
  Iterator iterator = mockIterator(consultant);
  when(this.cut.company.iterator()).thenReturn(iterator);
  try{
   this.cut.predictFutureOfJava();
  }catch(IllegalStateException e{}
  verify(this.cut.eventListener,times(1)).fire(expectedResultToFire);
}
Listing 14: Testing the Event#fire Invocation
Testing of the unsuccessful case is a bit trickier. We swallow the IllegalStateException first and then check whether the method Event#fire was actually invoked.

It’s Like Java SE

Unit testing of Java EE 6 applications is no different than testing Java Platform, Standard Edition (Java SE). Java EE 6 components are just annotated classes. You should not treat them in a special way; instead, focus on the verification of the business logic.
It is a common mistake to test everything inside a container. Even a Java EE 6 container takes a few seconds to start and deploy your application. Testing your business logic in a container is just waste of time and introduces unnecessary complexity. In Java EE 6, you should always separate unit tests from integration tests. Unit tests and integration tests should be even separately executed. True unit tests with a mocked-out environment are lightening fast. The execution of PredictionAuditTest and OracleResourceTest don’t even take a half a second:
-------------------------------------------------------
   T E S T S
-------------------------------------------------------
Running com.abien.testing.oracle.boundary.OracleResourceTest
Tests run: 6, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.254 sec
Running com.abien.testing.oracle.control.PredictionAuditTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.025 sec
Results :
Tests run: 8, Failures: 0, Errors: 0, Skipped: 0
Listing 15: Test Results

Myth #1: You Need Interfaces for Mocking

The introduction of interfaces is often motivated by mocking. Modern frameworks, however, do not need interfaces for mocking any more. Mocks can be easily created directly from Plain Old Java Object (POJO) classes. PredictionArchiveResource uses the directly injected PredictionAudit class (see Listing 16).
@Path("predictions")
@Stateless
public class PredictionArchiveResource {
  @EJB
  PredictionAudit audit;
  @GET
  @Produces(MediaType.APPLICATION_JSON)
  public List<Prediction> allPredictions(@DefaultValue("5") @QueryParam("max") int max{
    List<Prediction> allPredictions = audit.allPredictions();
    if (allPredictions.size() <= max)
        return allPredictions;
    else
        return allPredictions.subList(0, max);}
}
Listing 16: Injection of a POJO Class
Although PredictionAudit is a class and not an interface, it can be easily mocked out. To test the size limit of the returned list, the PredictionAudit class is completely mocked out (see Listing 17).
public class PredictionArchiveResourceTest { 
 PredictionArchiveResource cut; 
 @Before
 public void initialize(){
   this.cut = new PredictionArchiveResource();
   this.cut.audit = mock(PredictionAudit.class);
 }


 @Test
 public void allDecisionsWithMaxLesserReturn() throws Exception {
   int expectedSize = 2;
   List<Prediction> prediction = createDecisions(expectedSize);
   when(this.cut.audit.allPredictions()).thenReturn(prediction); 
   List<Prediction> allDecisions = this.cut.allPredictions(3);
   assertThat(allDecisions.size(), is(expectedSize));
 }
 @Test
 public void allDecisionsWithMaxGreaterReturn() throws Exception {
    int max = 5;
    int expected = 3;
    List<Prediction> prediction = createDecisions(max);
    when(this.cut.audit.allPredictions()).thenReturn(prediction); 
    List<Prediction> allDecisions = this.cut.allPredictions(expected);
    assertThat(allDecisions.size(), is(expected));
 }
 @Test
 public void allDecisionsWithMaxEqualReturn() throws Exception {
   //obvious code omitted
 }
 List<Prediction> createDecisions(final int nr) {
   return new ArrayList<Prediction>(){{
          for (int i = 0; i < nr; i++)
               add(new Prediction(Result.BRIGHT, true)); }};
 }
}
Listing 17: Java Class Mocking
The only noteworthy business logic in the class PredictionArchiveResource is the limitation of the list size (see Listing 16). The maximum value of QueryParameter is used to compute the size of the sublist. A PredictionArchiveResource mock instance allows the return of a List<Prediction> with an arbitrary size. Controlling the list contents and size without accessing the JPA layer (or even the database) significantly simplifies the test. A mock also dramatically speeds up the test execution. A database access takes seconds, whereas accessing a mock is accomplished in milliseconds.
Java EE 6 made interfaces optional. You can inject classes (CDI managed beans and EJB beans) instead of interfaces without sacrificing any “enterprise” features. There is also no reason to use interfaces for mocking any more. Using plain classes, not interfaces, as a general building block not only makes the implementation of production code leaner, but it also simplifies testing. You do not have to decide whether to mock out a class or interface.

Conclusion

So far, we tested only the internal functionality of objects and methods. The surrounding infrastructure was completely mocked out to make the tests as simple as possible.

Our testing effort exactly fits the unit test definition: “In computer programming, unit testing is a method by which individual units of source code are tested to determine if they are fit for use. A unit is the smallest testable part of an application. In procedural programming a unit may be an individual function or procedure. In object-oriented programming a unit is usually a method…” (http://en.wikipedia.org/wiki/Unit_testing)
Although the results of all our unit tests are “green,” we don’t know whether the application is deployable. A JPA 2 mapping error, an inconsistent persistence.xml, or a misspelled JPA query just cannot and must not be tested with classic unit tests.

Infrastructure-dependent logic such as CDI event delivery, sophisticated dependency injection, or JPA queries can be tested only with integration tests in an environment similar to production. In a subsequent article, I will cover different flavors of integration tests.

See Also