ADF Integration

If you have existing ADF entities, use JDeveloper to create a service method that has a FindCriteria object as a parameter. This allows SmartGWT to pass search criteria, sort order and other information to ADF so that ADF can use it to generate efficient SQL queries.

To connect SmartGwtEE to an ADF Data Model, the ADF Data Model must be deployed with a Service Interface. That way, we can make calls from the Project to the published methods of the Service Interface.

Next is an example of how to do this from a SmartgwtEE Project.

1.- First define a Custom DataSource Stub:

    public class ADFDatasource extends BasicDataSource {

        public DSResponse executeAdd(DSRequest req) throws Exception {
            return null;
        }

        public DSResponse executeFetch(DSRequest req) throws Exception {
            return null;
        }

        public DSResponse executeRemove(DSRequest req) throws Exception {
            return null;
        }

        public DSResponse executeUpdate(DSRequest req) throws Exception {
            return null;
        }
    }

2.-  Then, build the methods to Create, Update, Remove and Fetch for the ADFDatasource.java Class:

2.1.- The Create method:  private tst.common.UsersViewSDO createRecord (Map values)

// Create a context to the weblogic application server
Context context = getInitialContext();

// Locate an EJB for the service interface.
// ejbName variable holds the name of the EJB
AppModuleService data = (AppModuleService)context.lookup(ejbName);

// Define the XML schema that describes the structure of the XML document for the published service interface
// schemaLocation variable holds the location of the XML schema
// The schema variable holds the name of the XML schema document.
SDOHelper.INSTANCE.defineSchema(schemaLocation, schema);

// Create an object for the UsersViewSDO interface. We do this using DataFactory interface.
// This is used as the response
tst.common.UsersViewSDO user = (tst.common.UsersViewSDO)DataFactory.INSTANCE.create(tst.common.UsersViewSDO.class);

// The "Values" variable, holds all of the information to create a new record, so, we need to pass it to the user variable
this.setProperties(values, user);

// Invoke the createUsersView1 method for the published service interface and pass the user bean as a parameter
data.createUsersView1(user);

2.2.- The Update method:  private tst.common.UsersViewSDO updateRecord (Map values, Map oldValues)

// Create a context to the weblogic application server
Context context = getInitialContext();

// Locate an EJB for the service interface.
// ejbName variable holds the name of the EJBAppModuleService data = (AppModuleService)context.lookup(ejbName);

// Define the XML schema that describes the structure of the XML document for the published service interface
// schemaLocation variable holds the location of the XML schema
// The schema variable holds the name of the XML schema document.SDOHelper.INSTANCE.defineSchema(schemaLocation, schema);

// Create an object for the UsersViewSDO interface, we do this using DataFactory interface
// This will also be used as the response
tst.common.UsersViewSDO user = (tst.common.UsersViewSDO)DataFactory.INSTANCE.create(tst.common.UsersViewSDO.class);

// Any fields that have not changed are null, so these fields need to be retrieved from the "oldValues" variable, because the "Values" variable only holds
// the fields to update (i.e. the fields that have changed)
DataTools.putAllNotPresent(values, oldValues);

// "Values" has the fields to update, so, pass it to the user variable
this.setProperties(values, user);

// Invoke the updateUsersView1 method for the published service interface and pass the user bean as a parameter
data.updateUsersView1(user);

2.3.- The Remove method:  private tst.common.UsersViewSDO removeRecord (Map values)

// Create a context to the weblogic application server
Context context = getInitialContext();

// Locate an EJB of the service interface.
// ejbName variable holds the name of the EJBAppModuleService data = (AppModuleService)context.lookup(ejbName);

// Define the XML schema that describes the structure of the XML document for the published service interface
// schemaLocation variable holds the location of the XML schema
// The schema variable holds the name of the XML schema document.SDOHelper.INSTANCE.defineSchema(schemaLocation, schema);

// Create an object for the UsersViewSDO interface, we do this using DataFactory interface.
// This will also be the response
tst.common.UsersViewSDO user = (tst.common.UsersViewSDO)DataFactory.INSTANCE.create(tst.common.UsersViewSDO.class);

// The "Values" variable has the fields to update, so, pass it to the user variable
this.setProperties(values, user);

// Invoke the deleteUsersView1 method for the published service interface and pass the user bean as a parameter
data.deleteUsersView1(user);

2.4.- The Fetch method: private List fetchRecordsFilter (DSRequest req, DSResponse resp)

// This list will be the response
List<tst.common.UsersViewSDO> collection = null;

// Create a list of fields to sort (if necessary)
List ascDescF = req.getSortByFields();

// Create a context to the weblogic application server
Context context = getInitialContext();

// Locate an EJB of the service interface.
// ejbName variable holds the name of the EJB
AppModuleService data = (AppModuleService)context.lookup(ejbName);

// Define the XML schema that describes the structure of the XML document for the published service interface
// schemaLocation variable holds the location of the XML schema
// The schema variable holds the name of the XML schema document.SDOHelper.INSTANCE.defineSchema(schemaLocation, schema);

// Create an object for the UsersViewSDO interface, we do this using DataFactory interface.
tst.common.UsersViewSDO user = (tst.common.UsersViewSDO)DataFactory.INSTANCE.create(tst.common.UsersViewSDO.class);

// Implement sorting, we can sort on any field
// Create an object of SortOrder
SortOrder sorter = (SortOrder)DataFactory.INSTANCE.create(SortOrder.class);

// Create a sort attribute for the SortOrder
SortAttribute orderBy = null;

List sortFields = new ArrayList();

// Iterate over the list of fields to sort by
for (int i = 0; i < ascDescF.size(); i++) {
    // get an object of SortAttribute
    orderBy = (SortAttribute)DataFactory.INSTANCE.create(SortAttribute.class);

    // get the field name to sort
    String fieldToSort = (String)ascDescF.get(i);

    // Verify if the field is ascending or descending
    if (fieldToSort.startsWith("-")) {//here is descending
        orderBy.setDescending(true);
        // set the field to sort
        orderBy.setName(fieldToSort.substring(1,fieldToSort.length()));
    } else {//here is ascending
       // set the field to sort
       orderBy.setName(fieldToSort);
    }
    // Set the orderBy object in the list
    sortFields.add(orderBy);
}

// Set the list to the sorter object
sorter.setSortAttribute(sortFields);

// NEXT

// Implement criteria
// create a FindCriteria object
FindCriteria findCriteria = (FindCriteria)DataFactory.INSTANCE.create(FindCriteria.class);
findCriteria.setExcludeAttribute(true);

// Apply the sorting to the criteria
findCriteria.setSortOrder(sorter);

// Create a list for the ChildFindCriteria variable
List listFindCriteriaChild = new ArrayList();

// Create a list of ViewCriteriaItem objects
List<ViewCriteriaItem> listViewCriteriaItems = new ArrayList();

// Set the criteria selected from the client side
Set setView = criteria.entrySet();
Iterator iterator = setView.iterator();
while(iterator.hasNext()) {
    Map.Entry map =(Map.Entry)iterator.next();
    // getKey is used to get key of Map
    String key=(String)map.getKey();

    // getValue is used to get value of key in Map
    String value=(String)map.getValue();
    List listValue = new ArrayList();
    // create a ViewCriteriaItem object in the list, this is done for each criteria selected
    ViewCriteriaItem viewCriteriaItem = (ViewCriteriaItem)DataFactory.INSTANCE.create(ViewCriteriaItem.class);
    // criteria is our Map object with the criterias selected
    listValue.add(criteria.get(key));

    // Set the field that the criteria applies to
    viewCriteriaItem.setAttribute(key);
    viewCriteriaItem.setValue(listValue);

    // Add the criteria item to the ViewCriteriaItems list
    listViewCriteriaItems.add(viewCriteriaItem);

    // Set the field name to apply criteria to. In this case we add it to another list
    listFindCriteriaChild.add(key);
}

List group = new ArrayList();

// Assign the ViewCriteriaRow object to a list
group.add(viewCriteriaRow);

// Create a ViewCriteriaRow object
ViewCriteriaRow viewCriteriaRow = (ViewCriteriaRow)DataFactory.INSTANCE.create(ViewCriteriaRow.class);

// Assign the ViewCriteriaItems list to the viewCriteriaRow object
viewCriteriaRow.setItem(listViewCriteriaItems);

// Create a ViewCriteria object
ViewCriteria viewCriteria = (ViewCriteria)DataFactory.INSTANCE.create(ViewCriteria.class);

// Assign the list to the ViewCriteria object
viewCriteria.setGroup(group);

// Assign the ViewCriteria object to the FindCriteria object, like a filter
findCriteria.setFilter(viewCriteria);

// Create a list
List listChildFindCriteria = new ArrayList();

// Create a ChildFindCriteria object
ChildFindCriteria childFindCriteria = (ChildFindCriteria)DataFactory.INSTANCE.create(ChildFindCriteria.class);

// assign the list (listFindCriteriaChild) to our ChildFindCriteria object
childFindCriteria.setChildFindCriteria(listFindCriteriaChild);

// Assign the ChildFindCriteria object to a list
listChildFindCriteria.add(childFindCriteria);

// Finally, assign the list to the FindCriteria object
findCriteria.setChildFindCriteria(listChildFindCriteria);

// NEXT

// Implement data paging
long totalRows = -1;

// Verify if pagination is required
if (req.isPaged()) {
    if (req.getEndRow() != DSRequest.ENDROW_UNSET) {
    // if specified, endRow overrides batchSize
        if (req.getEndRow() - req.getStartRow() > req.getBatchSize()) {
            req.setBatchSize(req.getEndRow() - req.getStartRow());
        }
    }
    // Run the query to retrieve total records
    collection = data.findUsersView1(findCriteria, null);
    totalRows = collection.size();
}

// Set startRow/endRow
long startRow = 0;
long endRow = 0;
if (totalRows != 0) {
    startRow = req.getStartRow();
    endRow = req.getEndRow();
}

// Store startRow and endRow on the DSResponse
resp.setStartRow(startRow);
resp.setEndRow(endRow);

// Set fetch start row
findCriteria.setFetchStart((int)startRow);

// Set the size of the fetch
findCriteria.setFetchSize((int)endRow-(int)startRow);

// Finally run the query
// Invoke the findUsersView1 method for the published service interface and pass the FindCriteria object as a parameter
collection = data.findUsersView1(findCriteria, null);

// Store the total number of rows to the DSResponse
resp.setTotalRows(totalRows);

3.- Now we define the Java Class for the Server Side of the SmartgwtEE Project:

ADFDataSource.java
public class ADFDataSource extends BasicDataSource {

	    // Override all four CRUD operations - create, retrieve, update and delete
	    // (add, fetch, update and remove in SmartClient terminology).

	    // Note that the parameters sent by the client arrive here already converted to Java Maps
	    // by the SmartClient Server - with SmartClient Pro, Power and Enterprise Editions, there's
	    // no need to worry about conversion to and from XML or JSON even in a custom DS
	    // implementation

	String ejbName = "ejb/ServiceBeanUser";
	String schemaLocation = "tst/common/serviceinterface/";
	String schema = "AppModuleService.xsd";

	    public DSResponse executeAdd(DSRequest req) throws Exception {
	        DSResponse resp = new DSResponse();
	        resp.setData(createRecord(req.getValues()));
	        resp.setStatus(0);
	        return resp;
	    }

	    public DSResponse executeFetch(DSRequest req) throws Exception {
	        DSResponse resp = new DSResponse();
	        resp.setData(fetchRecordsFilter(req, resp));
	        resp.setStatus(0);
	        return resp;
	    }

	    public DSResponse executeRemove(DSRequest req) throws Exception {
	    	return new DSResponse(removeRecord(req.getValues()));
	    }

	    public DSResponse executeUpdate(DSRequest req) throws Exception {
	    	return new DSResponse(updateRecord(req.getValues(),req.getOldValues()));
	    }

	// -----------------------------------------------------------------------------------------
	// Code for actual data creation and manipulation.
	//
	// You can replace the code below to implement any data access approach you actually want to use.
	//
	// -----------------------------------------------------------------------------------------

	    // Create a record and return it.
	    private tst.common.UsersViewSDO createRecord (Map values) throws Exception {
	    	Context context = getInitialContext();
	        AppModuleService data = (AppModuleService)context.lookup(ejbName);
	        SDOHelper.INSTANCE.defineSchema(schemaLocation, schema);
	        tst.common.UsersViewSDO user = (tst.common.UsersViewSDO)DataFactory.INSTANCE.create(tst.common.UsersViewSDO.class);
	        this.setProperties(values, user);
	        data.createUsersView1(user);
	        return user;
	    }

	    // Sample server side sorting/filtering/paging
	    private List fetchRecordsFilter (DSRequest req, DSResponse resp) throws Exception {
	    	List<tst.common.UsersViewSDO> collection = null;
	    	Map criteria = req.getCriteria();
	    	List ascDescF = req.getSortByFields();

	    	Context context = getInitialContext();
	        AppModuleService data = (AppModuleService)context.lookup(ejbName);
	        SDOHelper.INSTANCE.defineSchema(schemaLocation, schema);
	        tst.common.UsersViewSDO user = (tst.common.UsersViewSDO)DataFactory.INSTANCE.create(tst.common.UsersViewSDO.class);

	        //get all users
	        if (criteria.isEmpty()) {
	            collection = data.findUsersView1(null, null);
	        } else {
	            //Implement sorting
	            //sort by any field
	            SortOrder sorter = (SortOrder)DataFactory.INSTANCE.create(SortOrder.class);
	            SortAttribute orderBy = null;
	            List sortFields = new ArrayList();
	            for (int i = 0; i < ascDescF.size(); i++) {
	         	orderBy = (SortAttribute)DataFactory.INSTANCE.create(SortAttribute.class);
	        	String fieldToSort = (String)ascDescF.get(i);
		       	if (fieldToSort.startsWith("-")) {
		      	    orderBy.setDescending(true);
		            orderBy.setName(fieldToSort.substring(1,fieldToSort.length()));
		        } else {
		            orderBy.setName(fieldToSort);
		        }
		        sortFields.add(orderBy);
	            }
	            // Assign the sortable fields to the sorter variable
	            sorter.setSortAttribute(sortFields);

	            // Implement criteria
	            FindCriteria findCriteria = (FindCriteria)DataFactory.INSTANCE.create(FindCriteria.class);
	            findCriteria.setExcludeAttribute(true);
	            findCriteria.setSortOrder(sorter);

	            //List for the ChildFindCriteria variable
	            List listFindCriteriaChild = new ArrayList();
		    List<ViewCriteriaItem> listViewCriteriaItems = new ArrayList();
		    Set setView = criteria.entrySet();
	            Iterator iterator = setView.iterator();
	            while(iterator.hasNext()) {
	                Map.Entry map =(Map.Entry)iterator.next();
	                // getKey is used to get key of Map
	                String key=(String)map.getKey();
	                // getValue is used to get value of key in Map
	                String value=(String)map.getValue();
	                List listValue = new ArrayList();
		        ViewCriteriaItem viewCriteriaItem = (ViewCriteriaItem)DataFactory.INSTANCE.create(ViewCriteriaItem.class);
		        listValue.add(criteria.get(key));
		        viewCriteriaItem.setAttribute(key);
		        viewCriteriaItem.setValue(listValue);
		        listViewCriteriaItems.add(viewCriteriaItem);
	        	listFindCriteriaChild.add(key);
	            }
		    ViewCriteriaRow viewCriteriaRow = (ViewCriteriaRow)DataFactory.INSTANCE.create(ViewCriteriaRow.class);
		    viewCriteriaRow.setItem(listViewCriteriaItems);
	            List group = new ArrayList();
	            group.add(viewCriteriaRow);

	            ViewCriteria viewCriteria = (ViewCriteria)DataFactory.INSTANCE.create(ViewCriteria.class);
	            viewCriteria.setGroup(group);
	            findCriteria.setFilter(viewCriteria);

		    List listChildFindCriteria = new ArrayList();
		    ChildFindCriteria childFindCriteria = (ChildFindCriteria)DataFactory.INSTANCE.create(ChildFindCriteria.class);
		    childFindCriteria.setChildFindCriteria(listFindCriteriaChild);
		    listChildFindCriteria.add(childFindCriteria);
		    findCriteria.setChildFindCriteria(listChildFindCriteria);

	            // Implement data paging
	            long totalRows = -1;
	            if (req.isPaged()) {
	                if (req.getEndRow() != DSRequest.ENDROW_UNSET) {
	                    // if specified, endRow overrides batchSize
	                    if (req.getEndRow() - req.getStartRow() > req.getBatchSize()) {
	                        req.setBatchSize(req.getEndRow() - req.getStartRow());
	                    }
	                }
		        // Run the query to know total records
		      	collection = data.findUsersView1(findCriteria, null);
		      	totalRows = collection.size();
	            }

	            // Set startRow/endRow
	            long startRow = 0;
	            long endRow = 0;
	            if (totalRows != 0) {
	                startRow = req.getStartRow();
	                endRow = req.getEndRow();
	            }
	            resp.setStartRow(startRow);
	            resp.setEndRow(endRow);

	            //run the query
	            findCriteria.setFetchStart((int)startRow);
	            findCriteria.setFetchSize((int)endRow-(int)startRow);
	            collection = data.findUsersView1(findCriteria, null);
		    resp.setTotalRows(totalRows);
	        }
		return collection;
	    }

	    // Returns removed record.
	    private tst.common.UsersViewSDO removeRecord (Map values) throws Exception {
	    	Context context = getInitialContext();
	    	AppModuleService data = (AppModuleService)context.lookup(ejbName);
	        SDOHelper.INSTANCE.defineSchema(schemaLocation, schema);
		tst.common.UsersViewSDO user = (tst.common.UsersViewSDO)DataFactory.INSTANCE.create(tst.common.UsersViewSDO.class);
		this.setProperties(values, user);
		data.deleteUsersView1(user);
		return user;
	    }

	    // Returns updated record.
	    private tst.common.UsersViewSDO updateRecord (Map values, Map oldValues) throws Exception {
	    	Context context = getInitialContext();
	        AppModuleService data = (AppModuleService)context.lookup(ejbName);
	        SDOHelper.INSTANCE.defineSchema(schemaLocation, schema);
	        tst.common.UsersViewSDO user = (tst.common.UsersViewSDO)DataFactory.INSTANCE.create(tst.common.UsersViewSDO.class);
                //the fields no updated(nulls) we must to get it from oldValues variable, because
	        //values variable only have pk field and the fields to update, the fields no
	        //updated are null
	        DataTools.putAllNotPresent(values, oldValues);
	        this.setProperties(values, user);
	        data.updateUsersView1(user);
		return user;
	    }

	    public static Context getInitialContext() throws javax.naming.NamingException {
	            Properties p = new Properties();
	            p.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
	            p.put(Context.PROVIDER_URL, "t3://localhost:7001");
	            return new javax.naming.InitialContext(p);
	    }

}

4.- Finally, define the ds.xml DataSource file.

<?xml version="1.0" encoding="UTF-8"?>
<DataSource
    ID="user"
    serverConstructor="com.smartgwt.sample.server.ADFDataSource"
    dropExtraFields="true"
>
    <fields>
        <field name="CodName"  valueXPath="codName"       type="text"  	   title="Cod. Name"        primaryKey="true" />
        <field name="Name"     valueXPath="name"	  type="text"      title="Name"             required="true"   />
        <field name="LastName" valueXPath="lastName"  	  type="text"      title="Last Name"        required="true"   />
        <field name="Age"      valueXPath="age"	  	  type="integer"   title="Age"	            required="true"  />
    </fields>

</DataSource>

An important point to note:, in this example, the field name property is defined as "CodName", but we also have a valueXPath of "codName" specified on the DataSource field.  The valueXPath statement will cause getCodName() to be invoked but the value will be stored in the resulting Records as "CodName" because the field.name is uppercase. This has been done, because, in the example ADF Data Model, the attributes name has an initial uppercase letter.


Below is an explanation of how to create a Service Interface of the ADF Data Model from JDeveloper 11g

1. In this example,  a simple ADF Data Model has been created, with one Entity Object and one View Object,The next stage is to publish the Data Model with a Service Interface. To do that, double-click on the model (AppModule) to display the various options available.

2.- Select Service Interface and click on the green plus sign ("+") found on the right-hand side:

3.- Define the service interface. In this case simply retain the default values and click Next.


4.- The next window allows for selecting custom methods. This can be ignored in this case. Simply click Next:


5.-Now Select the view object that has been defined in the data model, in this case, select UsersView1:


6.- By selecting the view object, it will move to the right-hand side. The basic operations of the view that can be published are displayed in the lower grid. Select  the 4 main operations: Create, Update, Delete and Find. Then click Next:


7.- Finally, a summary of all the service methods that will be published is displayed. Click Finish:


8.- Various Java, XML and other files, can now be viewed that the wizard has created.


Now select the Configurations tab of the module and choose the AppModuleService from the list of values ​​that appear.


Select the last record, where the value of Type is SI (Service Interface) with a double click.

Under Connection Type, select JBDC URL from the dropdown list, then click OK:

9.- Some modifications are now required in the generated code before this can be deployed to the application server.

Firstly, change the ejb-jar.xml file. Access the code using a double click in the left hand tree and change the name of the EJB:


10.- In the label <ejb-name> rename to ServiceBeanUser and save the change:


11. Now, double click on weblogic-ejb-jar.xml in the left hand tree to modify it:


12.- Rename the EJB:


Under the definition of our  EJB:now add:

<stateless-session-descriptor>
              <business-interface-jndi-name-map>
	                <business-remote>tst.common.serviceinterface.AppModuleService</business-remote>
	                <jndi-name>ejb/ServiceBeanUser</jndi-name>
	      </business-interface-jndi-name-map>
</stateless-session-descriptor>

13.- Next, change the interface generated by the wizard, (the interface can be found in the right hand tree under the root UsersView),  double click to edit

:

14.-Extend the Interface to make it Serializable, then save:


15.- Now change the EJB. In this example, the EJB file is called AppModuleServiceImpl.java.  This file is located in AppModule/Appmodule.xml/serviceinterface.  double click to accees it:


16.- Rename the EJB and the mapping to the EJB. Expand the generated annotations created by the wizard and at the first line, where it currently states:

@Stateless(name="tst.common.AppModuleServiceBean", mappedName="AppModuleServiceBean")
Change it to:
@Stateless(name="ServiceBeanUser", mappedName="ejb/ServiceBeanUser")


17.- The data model is now ready for deployment in the application server. The next step is to create a profile deployment.  Double click on the project (Project-ADF) and select New:


Select Deployment Profiles from the left hand tree, and then select Business Component Service Interface on the right side, then click OK:

18.-  Specify the name of the deployment profile (set this to “Profile-BCSI”) and click OK:


19.- The files that will be created when the project is exported can now be viewed, Click OK:


Change the name of the Project.

Right click on the name of the Project and select Properties, In the Project Properties window, select Java EE Application from the left hand side and enter the name of the Project as AppADF.


20.- Then, access the Properties of the Application. Click on the icon beside the name of the Application and from the context menu select Application Properties:


21.- Click on Deployment on the left hand side and the right side displays a view of the deployment profile that has been created:


22.- Create another deployment profile. In this cae it will be an EAR. Click the New button:


Enter the name AppADF-Ear, ensuring EAR File is selected in the Archive Type dropdown, then click OK:

23.-  Select the option Application Assembly in the left hand tree, and then select MiddleTier from the right hand tree, then click OK.


24.- In the next window leave all values as default: . Click OK:


25.-Finally, Generate the EAR file for the application and deploy it.