Java CAPS Tip: Migrating a Simple eVision Application to Visual Web Pack

With the advent of Visual Web Pack (VWP) and Netbean 6 as an eVision developer you may want to take advantage of the superior development and GUI facilities available within VWP. JavaCAPS does not provide any automated migration from eVision to VWP rather this article will describe what you will need to consider and implement to migrate your application to the new environment. Although the eVision application I will use may be consider simplistic and contrived the implementation strategy is based on Sun recommended architectural practices for developing eVision and SOA applications using JavaCAPS.

Resources
Scenario Description

The simple uses the travel Derby database tables shipped with the NetBeans 6.0 installation and provides a simple eVision based Two-Page-CRUD example which splits the graphical Page-Flow functionality from the re-usable Business Sub-Processes that deal with the database. It should be considered that in a real-world example the Sub-Processes would, most likely, be more complex but these examples are simple because their detail is insignificant to this article. The page flow within the scenario consists of 3 pages, Trip List Page, Modify Trip Page and a Create Trip Page. The user will enter on the Trip List page, which will be automatically populated with all data, and be provided with a number of actions.

eVision Project
Project Structure
The eVision project contains a number of Sub-Processes that perform the key functionality, in this case Database access, required to retrieve and edit trip information. Theses are then linked into the main page flow as Sub-Process call between the pages and the values mapped directly. This design paradigm follows the Sun recommended design patterns. If you have build your eVision Page flows with in-line processing, rather than sub-processes, you will need to convert that processing to a sub-process design before this example will work for you.

The page flow implemented can be seen in the image below which shows that the application will initially enter on the trip list page, having selected all appropriate persons and trip types, and then based on the option chosen within the page execute one of the following :
  1. Create a Trip
  2. Modify a Trip
  3. Delete a Trip
  4. Exit
This functionality is achieved using the eVision Page links with the appropriate information mapped accordingly. The Page Flow below graphically depicts the core functionality and navigation of the application. If you compare this with the VWP Page Navigation below you will see that allot of the Process Flow information is lost in the graphic representation. Not withstanding this VWP does provide a superior development environment and runtime implementation although it is aimed at the more technical developer.

If you import the JavaCAPS Project, which can be downloaded here, it will be easier for you to view the mappings and navigation. The eVision screens built for the application can be seen at the end of this article. The application can be built by using the Connectivity Map in eVisionExample/CM/EV/cmEVision and the environment envBlogeVision.



Pageflow
eVision Page Flow

Page Navigation
Visual Web Pack Page Navigation

To allow VWP to call the Sub-Processes you will need to expose them as externally available Web Services. In the attach JavaCAPS Project I have included a second environment, envBlogVWP, and Connectivity Map, eVisionExample/CM/VWP/cmVWP. This can be used to build and deploy the Sub-Processes as externally available Web Services. I will assume in the next section that these have been deployed on an integration server running on localhost:18000.

Visual Web Pack Project

As mentioned previously their is currently no way to migrate your eVision Pages directly to VWP and I suspect, given the difference, their never will be and so you will need to rebuild the pages from scratch. This said personally I find it quicker to develop using VWP than eVision.

Web ServiceThe first thing we will need to do is import the WSDL definitions associated with the JavaCAPS Web Services, or the original, and this is done within the Services (Tab)->Web Services. For this example it will generate the 6 operation for the TripPort. It should be noted that to successfully import and then use the Web Services as native DataProviders the definition has some specific requirements, these are show in the attached WSDL, listed below:
  • Message parts must be created using an Element rather than a specific type and the element must be defined in a local in-line schema.
        <message name="ListTripsRequestMessage">
            <wsdl:part name="parameters" element="params:ListTrips"/>
        </message>
        <message name="ListTripsResponseMessage">
            <wsdl:part name="result" element="params:ListTripsResponse"/>
        </message>


  • This in-line element can only contain a sequence with a single sub-element of a specific Complex Type.
    <xsd:complexType name="ListTripsRequestComplexType">
        <complexContent>
        <extension base="params:ContextComplexType">
           <sequence>
              <xsd:element name="tripId" type="xsd:string" minOccurs="0"/>
           </sequence>
        </extension>
       </complexContent>
    </xsd:complexType>
    <xsd:complexType name="ListTripsResponseComplexType">
       <xsd:sequence>
        <xsd:element name="trip" type="params:TripComplexType" minOccurs="0" maxOccurs="unbounded"/>
       </xsd:sequence>
    </xsd:complexType>

    <xsd:element name="ListTrips" type="params:ListTripsRequestComplexType"/>

    <xsd:element name="ListTripsResponse" type="params:ListTripsResponseComplexType"/>


  • The name of the input element must be the same as the operation it will be used in.
  • nillable element option should not be used because this will cause your strings to be returned as JAXBElements and not Strings.
To create the Trip List screen we will do the following:
  1. Drag a Table Object from the Pallet onto the Page.
    • This will create a tripPortListTrip1 DataProvider and a tripPortClient1 provider instance which should be renamed to listTripPortClient.
  2. Select the "listTrips" operation from the WebService definition and drop it onto the Table, it may take a few second for the cursor to change so that you can do this, which will modify the Table to use the generated DataProvider. The Table Layout will need to be modified to display the chosen columns, see below, and 2 additional button columns will need to be added for the Modify and Delete actions..
  3. Drag an additional instance of the TripPort, from the WebServices, onto the page and rename the resulting tripPortClient1 to deleteTripPortClient.
  4. Drag 2 more button onto the page; these will become the Add and Refresh buttons.
  5. Because of the way JavaCAPS generates / Deploys Web Services we will need to modify the the Addresses associated with the Web Service Calls and this can be done by adding the following to the init() method:

    // TODO - add your own initialiation code here

    // We need to set the WebService address because the JavaCAPS needs
    // a specific address per Web Service
    listTripPortClient.setAddress("http://localhost:18001/TripManager/ListTrips/TripPort");
    deleteTripPortClient.setAddress("http://localhost:18001/TripManager/DeleteTrip/TripPort");


  6. Create the following properties in the SessionBean and generate the appropriate Getters / Setter.

    private String tripId = "";
    private String personId = "";
    private String tripTypeId = "";
    private Date depDate = new Date(System.currentTimeMillis());
    private String depCity = "";
    private String destCity = "";
    private boolean modifyTrip = true;


  7. We can now add the code behind the buttons:

    public String addBtn_action() {
        getSessionBean1().setTripId("");
        getSessionBean1().setPersonId("");
        getSessionBean1().setTripTypeId("");
        getSessionBean1().setDepCity("");
        getSessionBean1().setDestCity("");
        getSessionBean1().setDepDate(new Date(System.currentTimeMillis()));
        getSessionBean1().setModifyTrip(false);
        return "add";
    }

    public String refreshBtn_action() {
        // TODO: Process the action. Return value is a navigation
        // case name where null will return to the same page.
        return null;
    }

    public String modifyBtn_action() {
        try {
            getSessionBean1().setTripId((String) getValue("#{currentRow.value['tripId']}"));
            getSessionBean1().setPersonId((String) getValue("#{currentRow.value['personId']}"));
            getSessionBean1().setTripTypeId((String) getValue("#{currentRow.value['triptypeid']}"));
            getSessionBean1().setDepCity((String) getValue("#{currentRow.value['depcity']}"));
            getSessionBean1().setDestCity((String) getValue("#{currentRow.value['destcity']}"));
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            getSessionBean1().setDepDate(sdf.parse(((String) getValue("#{currentRow.value['depdate']}")).substring(0, 10)));
            getSessionBean1().setModifyTrip(true);
            return "modify";
        } catch (ParseException ex) {
            Logger.getLogger(TripListPage.class.getName()).log(Level.SEVERE, null, ex);
            error(ex.getMessage());
            return null;
        }
    }

    public String deleteBtn_action() {
        try {
            String tripId = (String) getValue("#{currentRow.value['tripId']}");
            deleteTripPortClient.deleteTrip(null, tripId, null, null);
        } catch (FaultResponseMessage ex) {
            Logger.getLogger(TripListPage.class.getName()).log(Level.SEVERE, null, ex);
            error(ex.getMessage());
        }
        return null;
    }

    It can be seen from the above code that the Add and Modify button simply populate the SessionBean properties and return a value that directs the page navigation to the EditPage we will create. The Delete button takes the current tripId and passes it to the deleteTrip WebService call and then returns null causing the screen to be redisplayed and the table refreshed.
  8. Create a new Page, TripEditPage, and add display fields for the various elements of a trip, see below, and 2 buttons (Save and reject). Create the Person and Trip Type fields as DropDowns which we will then populate from from services.
  9. Drag the listPersons operation onto the Person DropDown and modify the binding so that the value is personId and the display value is name. You should then rename the tripPortClient to personListTripPortClient.
  10. Drag the listTripTypes operation onto the Trip Type DropDown and modify the the bindings so the value is the typeId and the display is the name. This should create another tripPortClient that should be renamed to tripTypesTripPortClient. If it dows not then simply drag another copy of the TripPort onto the Canvas, rename it and assign it to the tripPortListTripTypes1 DataProvider.
  11. Drag the TripPort on to the canvas two more times and rename the resulting properties addTipPortClient and modifyTripPortClient.
  12. Again we will need to set the Address of the WebServices within the init() methods as follows:

    // TODO - add your own initialiation code here

    addTripPortClient.setAddress("http://localhost:18001/TripManager/CreateTrip/TripPort");
    modifyTripPortClient.setAddress("http://localhost:18001/TripManager/ModifyTrip/TripPort");
    tripTypesTripPortClient.setAddress("http://localhost:18001/TripManager/ListTripTypes/TripPort");
    personListTripPortClient.setAddress("http://localhost:18001/TripManager/ListPerson/TripPort");


  13. The prerender() method should be modified to set the current PersonId and TripTypeId from the SessionBean.
  14. The Save Button action needs the following code:

    public String saveBtn_action() {
        TripComplexType trip = new TripComplexType();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
       
        trip.setDepcity(getSessionBean1().getDepCity());
        trip.setDepdate(sdf.format(getSessionBean1().getDepDate()));
        trip.setDestcity(getSessionBean1().getDestCity());
        trip.setTripId(getSessionBean1().getTripId());
       
        trip.setPersonId((String)personDD.getSelected());
        trip.setTriptypeid((String)typeDD.getSelected());

        try {
            if (getSessionBean1().isModifyTrip()) {
                modifyTripPortClient.modifyTrip(null, trip, null, null);
            } else {
                addTripPortClient.createTrip(null, trip, null, null, null);
            }
        } catch (FaultResponseMessage ex) {
            Logger.getLogger(TripEditPage.class.getName()).log(Level.SEVERE, null, ex);
        }
        return "save";
    }


  15. The pages should be link together using the Page Navigation editor as above.
  16. The Project can now be built and deployed.
It should be noted that you will be unable to deploy both the eVision application and the Web Services on the same integration server because their will be a name conflict for the Web Services within the integration server.

Hopefully this example gives you an idea on how you can migrate you eVision application without needing to rewrite significant pieces of your core application.

Screen Comparison

List Types

eVision Trip ListVWP Trip List

Create Trip

eVision Create TripVWP Create Trip

Modify Trip

eVision ModifyTripVWP Modify Trip

Resources

Comments:

Post a Comment:
Comments are closed for this entry.
About

As a member of the Oracle A-Team we specialise in enabling and supporting the Oracle Fusion Middleware communities.

Search

Archives
« April 2014
MonTueWedThuFriSatSun
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    
       
Today