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:
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.