In this blog I will describe the use of LOV’s in Humantasks. I will describe three different type of LOV’s.
1. LOV with fixed values
2. LOV feeded by the content of a database table
3. LOV feeded via a webservice
The blog is devided into two part. In the first part I descibed the first two types (https://technology.amis.nl/2012/04/04/lovs-in-humantask-part-1-of-2/). In this second part I will descibe the third type.
3. LOV feeded via a webservice
As an example I will add a LOV with the values: Male, Female and Unknown to a Gender (geslacht in dutch) field. In this blog the terms Gender and Geslacht are sometimes mixed. In both cases the same thing is meant.
For demo purposes I created a webservice arround the database table create in the first part of this blog. But any webservice return a List Of Values will do.
3.1. Create Client Proxy
Create a Generic Project. This project is used to create a Web Service Proxy. A java proxy is gegenerated to make calls to the webservice. The java proxy offers the possibility to integrate the webservice functionality into the ADF (java) taskscreens.
Specify a name for the project (WsClientProxy). Press Finish.
Add a Web Service Proxy to the project.
Pick JAX-WS Style. Press Next.
Enter the WSDL Document URL of the consuming webservice.
In the example it is http://LUX164.arnhem.local:8001/soa-infra/services/default/ExposedWS/GenderService?WSDL
Press Next.
Specify ‘Package Name’ and ‘Root Package for Generated Types’. Accept all other defaults in the wizard. Press Finish.
The Java class GeslachtWS_ptClient is opend. Update the main method. Add the following code fragment:
// Add your code to call the desired methods. List<MoaGeslacht> lovTest =geslachtWS_ptt.geslachtWSSelect(null).getMoaGeslacht(); for (MoaGeslacht lovRegel: lovTest) { System.out.println("Afkorting : " + lovRegel.getAfkorting()); System.out.println("GeslachtNaam: " + lovRegel.getGeslachtnaam()); }
Run the main method to test the webservice proxy. An output example is shown below:
Afkorting : M GeslachtNaam : Man Afkorting : F GeslachtNaam : Vrouw Afkorting : U GeslachtNaam : Onbekend Process exited with exit code 0.
3.2. Create View Objecten
To make use of the LOV, a View Object to access the data is required. We also need a View Accessor to Access this View Object from the humantask. This View Accessor can add additional filters to the LOV.
Start by creating an ‘ADF Model Project’ for the View object’s.
Project creation
Create an ‘ADF Model Project’ in the same application as the humantask is located.
This ‘Model Project’ is used to create the ADF Business Components. Specify the Project name (LOVViews). Press Next.
Specify a Default Package (LOV). Press finish.
Add Webservice dependencies
Before the webservice(s) can be used, we first must modify the dependencies between all related projects. Both theLOVViews project as the Human tasks project have a dependency on the webservice. Here we will add this dependency.
Go the the project properties of the LOVViews project. Select Dependencies and start edit mode by clicking the pencil.
Check the ‘Build Output’ dependency of ExposedWS and WSClientProxy. Press OK.
Now go the the project properties of the ‘Human task’ project. Select Dependencies and start edit mode by clicking the pencil. Add the ‘Build Output’ dependencies of the ExposedWS project en WSClientProxy project.
View Object
The first ADF BC will be a View Object. A View Object is used here to select data.
Create the View Object within the LOVViews project.
The View Object is getting it’s data from a database. For this purpose, the next step will be to setup a connection with this database.
After this. A wizard is started for the creation of the View Object.
Specify a View Object name (GeslachtWSView or GenderWSView) with ‘Rows populated programmatically’. Press Next.
Press New to add the ‘transient view attributes’ Abbreviation/Afkorting and GenderName/GeslachtNaam.
Check ‘Key Attribute’ for the Afkorting / Abbreviation attribuut.
Press 2x Next. Check ‘Generate View Row Class’. Press Next.
Now we reached the ‘Application Module’ step.
Check-on ‘Applicatie Module’. Specify an Application Module name (AppModule) and press Finish.
Go to edit mode (pencil) for each attribute of witch the ‘display witdh’ needs to be changed.
Maximum length of Abbriviation/Afkorting is 1 character. Of GenderName/GeslachtNaam it is 20.
View Implementation
During the creation of the View Object in the previous paragraph we specified ‘Rows populated programmatically’. Here we will implement this.
Add the abstracte class WsViewImpl to the LOVViews project.
Press OK. Source code is shown below:
Update/replace this source with:
package LOV; import java.math.BigDecimal; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.util.Iterator; import java.util.List; import oracle.jbo.server.ViewObjectImpl; import oracle.jbo.server.ViewRowImpl; import oracle.jbo.server.ViewRowSetImpl; public abstract class WsViewImpl extends ViewObjectImpl { public WsViewImpl() { super(); } protected oracle.jbo.domain.Date toOracleDate(java.util.Calendar calendar) { oracle.jbo.domain.Date jboDate = new oracle.jbo.domain.Date(); Timestamp t = jboDate.timestampValue(); t.setTime(calendar.getTime().getTime()); return new oracle.jbo.domain.Date(t); } protected oracle.jbo.domain.Number toOracleNumber(int i) { return new oracle.jbo.domain.Number(i); } protected oracle.jbo.domain.Number toOracleNumber(double d) { try { return new oracle.jbo.domain.Number(d); } catch (SQLException e) { return null; } } protected oracle.jbo.domain.Number toOracleNumber(BigDecimal b) { try { return new oracle.jbo.domain.Number(b); } catch (SQLException e) { return null; } } protected abstract List retrieveArrayFromWebService(Object qc, Object[] params); private void storeNewIterator(Object qc, List rs) { setUserDataForCollection(qc, rs.iterator()); hasNextForCollection(qc); } protected void executeQueryForCollection(Object qc, Object[] params, int noUserParams) { storeNewIterator(qc, retrieveArrayFromWebService(qc, params)); super.executeQueryForCollection(qc, params, noUserParams); } private Iterator getArrayIterator(Object qc) { return (Iterator)getUserDataForCollection(qc); } protected boolean hasNextForCollection(Object qc) { boolean hasNext = getArrayIterator(qc).hasNext(); if (!hasNext) { setFetchCompleteForCollection(qc, true); } return hasNext; } protected abstract void fillRow(Object data, ViewRowImpl row); protected ViewRowImpl createRowFromResultSet(Object qc, ResultSet resultSet) { Iterator iterator = getArrayIterator(qc); ViewRowImpl row = createNewRowForCollection(qc); fillRow(iterator.next(), row); return row; } public long getQueryHitCount(ViewRowSetImpl viewRowSet){ return super.getQueryHitCount(viewRowSet); } }
After that change the code of GeslachtWSViewImpl.java. Replace it by:
package LOV; import java.util.List; import oracle.jbo.server.ViewRowImpl; import webservice.proxy.GeslachtService; import webservice.proxy.GeslachtWS_ptt; import webservice.proxy.types.MoaGeslacht; public class GeslachtWSViewImpl extends WsViewImpl { private static GeslachtService geslachtService; protected List retrieveArrayFromWebService(Object qc, Object[] params) { try { geslachtService = new GeslachtService(); GeslachtWS_ptt geslacht_ptt = geslachtService.getGeslachtWS_pt(); List<MoaGeslacht> geslachtList = geslacht_ptt.geslachtWSSelect(null).getMoaGeslacht(); return geslachtList; } catch (Exception e) { e.printStackTrace(); return null; } } protected void fillRow(Object data, ViewRowImpl row) { MoaGeslacht geslachtRegel = (MoaGeslacht)data; populateAttributeForRow(row, GeslachtWSViewRowImpl.AFKORTING,geslachtRegel.getAfkorting()); populateAttributeForRow(row, GeslachtWSViewRowImpl.GESLACHTNAAM,geslachtRegel.getGeslachtnaam()); } }
View Accessor
Create a second View Object with name GeslachtWSAccessor/GenderWSAccessor in the LOVViews project.
Set ‘Read-only access through SQL query’. Press Next.
Specify a dummy query. Press Next until step 8 is reached.
Check ‘Applicatie Module’ again. Press Finish.
Now extend this View Object with a ‘transient attribute’ . For this, press the green sign.
Specify the attribute (ViewAttr). Set Updatable op ‘Always’. Press OK.
Selecteer this new added attribute and go into Edit mode by clicking the pencil.
Select Control Hints and change the ‘Control Type’ from default into ‘Input Text with List of Values’ . Press OK.
Connecting the View Accessor with the View Object
The created View Object and View Accessor must be connected with each other. To do this, click the green plus sign in the ‘List of Values’ section.
Press the green plus sign again (now behind List Data Source) in new appearing screen.
Shuttle GeslachtWSView/GenderWSView to the right side. Press OK.
Select Afkorting/Abbreviation as ‘List Attribute’ in the List of Return Values.
Select the ‘UI Hints’ tab and shuttle both available attributes to the right. Press OK.
As a finishing touch we need to change the datasource reference.
Open the AppModule.xml file and then select the Configurations tab. Go into Edit mode for the AppModuleLocal by clicking the pencil.
Select JDBC Datasource als ‘Connection Type’. Now the ‘Datasource Name’ changes into java:comp/env/jdbc/MOA_UTILSDS. Manually change this into the JNDI name as specified on the WebLogic Server. In my case: ‘jdbc/MOAUtils’.
3.3. Attach the LOV to a taskfield
Open the humantask where the LOV is needed. Drag and Drop the LovTargetViewAttr attribute (from the GeslachtWSAccessor1) on the taskDetails page. A popup menu appears.
Choose ‘ADF LOV ChoiceList‘ (short lists) or ‘ADF LOV input‘ (long lists).
The ChoiceList type show a short list with the posibility to enter a Search(zoeken) popupscreen. The input type directly start the Search popupscreen.
The LOV is now connected to the transient attribute. In my case it must be connected to the Gender/Geslacht attribute.
The source code of the ChoiceList type:
<af:inputComboboxListOfValues id="viewAttr1Id" popupTitle="Search and Select: #{bindings.ViewAttr1.hints.label}" value="#{bindings.Geslacht.inputValue}" label="#{bindings.ViewAttr1.hints.label}" model="#{bindings.ViewAttr1.listOfValuesModel}" required="#{bindings.ViewAttr1.hints.mandatory}" columns="#{bindings.ViewAttr1.hints.displayWidth}" shortDesc="#{bindings.ViewAttr1.hints.tooltip}"> <f:validator binding="#{bindings.ViewAttr1.validator}"/> </af:inputComboboxListOfValues>
Change this into:
<af:inputComboboxListOfValues id="viewAttr1Id" popupTitle="Zoek en Selecteer #{bindings.Geslacht.hints.label}" value="#{bindings.Geslacht.inputValue}" label="#{bindings.Geslacht.hints.label}" model="#{bindings.ViewAttr1.listOfValuesModel}" required="#{bindings.ViewAttr1.hints.mandatory}" columns="#{bindings.ViewAttr1.hints.displayWidth}" shortDesc="#{bindings.ViewAttr1.hints.tooltip}"> <f:validator binding="#{bindings.ViewAttr1.validator}"/> </af:inputComboboxListOfValues>
What has changed?
– Title popup search screen
– Input field lable
– Attached field
3.4. Deployment
Before we can deploy the project, an Application property must change. Open the ‘Application Properties’.
Switch off ‘Auto Generate and Synchronize weblogic-jdbc.xml Descriptors During Deployment’ .
Deploy Project.
Here you can download a sample project (LOV_Voorbeeld)
Hi Marcel
Thanks for the sample. Can you tell me if the value selected in the lov input text will be returned to the bpel process in the human task receive?
Can you tell me if this works with a Microsoft SQL Server database?
Thanks a lot
Hi
I’am new in these matters and I don’t understand how to use this code in my problem:
The Java class GeslachtWS_ptClient is opend. Update the main method. Add the following code fragment:
// Add your code to call the desired methods.
List<MoaGeslacht> lovTest =geslachtWS_ptt.geslachtWSSelect(null).getMoaGeslacht();
for (MoaGeslacht lovRegel: lovTest) {
System.out.println(“Afkorting : ” + lovRegel.getAfkorting());
System.out.println(“GeslachtNaam: ” + lovRegel.getGeslachtnaam());
}
Could you please give me some guidance?
Thanks in advance
Pedro Pereira
Hi Pedro,
Sorry for the late reaction.
I have added a sample project to the original post. You can find the download link at the bottom of the post.
Maybe you can try to deploy this project and look through the source files.
If you still have questions please let me know.
Regards,
Marcel