Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components

This step-by-step starter hands-on provides an example how to make a JAX-WS webservice proxy in JDeveloper, and save retrieved data from this webservice in a batch-job to your own database with ADF Business Components.
Duration: 60 minutes.

For this hands-on example, imagine that your company wants to expand internationally and that reliable, up to date country information is absolutely critical. Recently there were some changes in the number of countries and there might be in the future. Since 1990, 33 new countries have been created. A few months ago the world welcomed a new country (South-Sudan) and yet we dont know what will happen in Libya (maybe it will be separated in West and East-Libya?). Your company wants to weekly synchronise its internal countries database table with up-to-date country information from a recognised country-monitoring institution that delivers up-to-date country information by a webservice.

Part 1: Create the country webservice client with JAX-WS

We are going to create a webservice client proxy for a country webservice available on:

http://webservices.oorsprong.org/websamples.countryinfo/CountryInfoService.wso?WSDL

Look at the wsdl file of this webservice and lets have a look at it so that we know to which webservice we talk to. Open de wsdl in de browser, for example in Firefox. At the bottom are all the wsdl operations that we are interested in:

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 101

These operations (for example CountryIntPhoneCode) have input (tns:CountryIntPhoneCodeSoapRequest) and output (tns:CountryIntPhoneCodeSoapResponse) messages. These messages are also in the wsdl defined:

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 91

The part parameters is also referring to their own definition:

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 81

In this example a standard ISO country-code is submitted to the webservice as request parameter for the operation CountryIntPhoneCode. The webservice will give back the international telephone-code back. We are going to use also 3 other operations from this webservice.

1-Create in JDeveloper a new application and call it for example CountriesBatchJob and the project WsClientproxy.

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 1

2-Create a webservice proxy (JAX-WS Style) for the wsdl describing the country webservice:

http://webservices.oorsprong.org/websamples.countryinfo/CountryInfoService.wso?WSDL

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 2

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 3

Give appropiate package names. Click next –> next –> finish.

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 4

Regenerate the webservice proxy in case you see any red crosses in the generated overview.

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 5

The client class CountryInfoServiceSoapClient will open. Save all.

3-Add in the main() method:

System.out.println("Code ZW; "+countryInfoServiceSoapType.countryName("ZW"));

Test the webservice. (select CountryInfoServiceSoapClient –> right mouse –> run)

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 6

OK, the client is ready en works!

Part 2: ADF Business Components

The current database table COUNTRIES from Oracles HR schema is used in this example. Use might need to unlock it first. We will synchronise the rows of the COUNTRIES table with up-to-date countries data from the webservice.
Fortunately the table has already a column COUNTRY_ID that is the PK and is the ISO-landcode.

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 7 1

1- Add columns to the table COUNTRIES with the following script:

alter table
COUNTRIES
add
(
CAPITAL varchar2(500) ,
INTPHONECODE varchar2(500) ,
COUNTRYFLAG varchar2(500) ,
LANGUAGENAME varchar2(500)
)

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 7 2

2-Add a new generic project in this application and call it for example ADFBC.

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 8

3-Start the wizard ADF Business Components from tables to create the objects for the Country table. Create a database connection in the wizard with the HR schema. Test it.

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 9

Walk through the wizard steps. We only need 1 EntityObject (call it: Country), 1 ViewObject (call it: CountryVw) and an ApplicationModule (call it: AppModule).

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 10

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 10 1

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 11

Click finish. In the end it should look like this:

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 12

4-Change the ViewObject usage name from CountryVw1 to CountryVw. (Click the pencil on the right bottom)

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 13

5- Test the ApplicationModule AppModule (select AppModule in tree –> right mouse –> run):

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 14

6-Create a Java class. Call it BatchJobSynchronizeCountries. Deselect constructors and select main method;

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 15

7-Type bc4jclient followed by CTRL + ENTER .
Test-code is generated by JDeveloper:

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 16

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 17

8-The generated names (amDef and config) need to be changed to your names. Look in bc4j.xcfg for the correct names: This file is in the common folder of your ADFBC project. On my computer:

C:\JDeveloper\mywork\CountriesBatchJob\ADFBC\src\nl\amis\services\common


Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 18

The selected part are the (amDef and config names) we need. Use these names in BatchJobSynchronizeCountries.java

Replace ViewObject to CountryVw:
Add:
System.out.println("Number of countries in CountryVw: "+vo.getEstimatedRowCount());

9-Run the client:

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 19

Fortunately the call to the countries table succeeded.

10-Query and print all countries and country-codes. Add:

//Query and print all countries
vo.executeQuery();
int rownr = 0;
while (vo.hasNext()) {
rownr++;
Row curCountry = vo.next();
String isoCountryCode = (String)curCountry.getAttribute("CountryId");
System.out.println("(" + rownr + ") isoCountryCode: " + isoCountryCode);
}

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 20

Oracle comes standard with 25 country records in the sample Countries table in the HR schema.

Part 3: Synchronize your countries table with data from the webservice

Lets return to the client (proxy) project in JDeveloper.
1-We see 2 lines of code that instantiate a proxy object. With this object we can later call the operations from the webservice. Copy these lines.

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 21

2-Return to our ADFBC project to BatchJobSynchronizeCountries.java.
Paste the 2 copied lines under the code we just edited. We can see red compiler lines under our copied code:

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 22

This is because JDeveloper cannot find the previous generated client proxy classes. The ADFBC project doesnt know from the existence of our client project. Go to ADFBC project –> right mouse –> properties –> dependencies.
3-Add a dependency:

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 23

Save all. Now JDeveloper is able to find the classes and with ALT+ENTER you have can select the import we need and except for one the red lines disappear. It cannot find the variable countryInfoService. We need to declare it.

4- Add :

private static CountryInfoService countryInfoService;

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 24

Now the class will compile.

5-Add the following code under the proxy instantiation:

System.out.println("--- (" + rownr + ")\t: " + isoCountryCode+" country : "+countryInfoServiceSoapType.countryName(isoCountryCode));
System.out.println("--- (" + rownr + ")\t: " + isoCountryCode+" capitalCity : "+countryInfoServiceSoapType.capitalCity(isoCountryCode));
System.out.println("--- (" + rownr + ")\t: " + isoCountryCode+" countryFlag : "+countryInfoServiceSoapType.countryFlag(isoCountryCode));
System.out.println("--- (" + rownr + ")\t: " + isoCountryCode+" IntPhoneCode: "+countryInfoServiceSoapType.countryIntPhoneCode(isoCountryCode));

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 25

Run this class.

Now, all country-codes are retrieved from the our database. For each country a request is send to the webservice for the country name, the capital city, the country flag and the international phone the data from this webservice is printed out:

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 99

6- Updating our COUNTRIES table with the data from the webservice

We need to update/synchronize all data from the webservice with our COUNTRIES table. Look at the specific ViewObjectRow attribute names in CountriesVw:

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 27

We need to use these names to map the values from the webservice to the Country ViewObject attributes.
Replace the whole main() method with:

public static void main(String[] args) {
String amDef = "nl.amis.adfbc.services.AppModule";
String config = "AppModuleLocal";
ApplicationModule am =
Configuration.createRootApplicationModule(amDef, config);
ViewObject countryVw = am.findViewObject("CountryVw");

// Work with your appmodule and view object here
System.out.println(“Number of countries in CountryVw: “+countryVw.getEstimatedRowCount());

//Get generated webservice proxy classes form the client project
countryInfoService = new CountryInfoService();
CountryInfoServiceSoapType countryInfoServiceSoapType = countryInfoService.getCountryInfoServiceSoap();

//1- First update existing country rows in the COUNTRIES table
countryVw.executeQuery();
int rownr=0;
while (countryVw.hasNext()) {
rownr++;
Row curCountry = countryVw.next();
String isoCountryCode = (String)curCountry.getAttribute(“CountryId”);
System.out.println(“— UPDATING (” + rownr + “)\t isoCountryCode: ” + isoCountryCode+” country: “+countryInfoServiceSoapType.countryName(isoCountryCode));

//Put attributes on your ViewObject row
curCountry.setAttribute(“Capital”, countryInfoServiceSoapType.capitalCity(isoCountryCode));
curCountry.setAttribute(“Intphonecode”, countryInfoServiceSoapType.countryIntPhoneCode(isoCountryCode));
curCountry.setAttribute(“Countryflag”, countryInfoServiceSoapType.countryFlag(isoCountryCode));
curCountry.setAttribute(“Languagename”, countryInfoServiceSoapType.languageName(isoCountryCode));
curCountry.setAttribute(“CountryName”, countryInfoServiceSoapType.countryName(isoCountryCode));
}
//commit transaction
am.getTransaction().commit();
System.out.println(“Country-batch SUCCEFULLY updated the COUNTRIES table”);
Configuration.releaseRootApplicationModule(am, true);
}

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 27 1

7-This will update all current country records we have in the COUNTRIES table with data from the webservice. Run the class.

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 26

This will update all our country records with the country information from the webservice and commit them. Our update-batch job has been successful!

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 29

Part 4 – Adding new countries from the webservice

Now, only existing records of the COUNTRIES table are updated. New countries are not yet added and we will do that now.

1-Add just above //commit transaction:

//-----------------------START------------------------------
//Query all countries and put them in a HashMap.
//Purpose: separate an UPDATE and an INSERT in COUNTRIES table
countryVw.executeQuery();
HashMap landCodesMap = new HashMap();
while (countryVw.hasNext()) {
Row curCountry = countryVw.next();
landCodesMap.put(curCountry.getAttribute("CountryId"),curCountry.getAttribute("CountryName"));
}

//2- Insert new country rows in the COUNTRIES table
//Get all countrycodes from the webservice
ArrayOftCountryCodeAndName arrayOftCountryCodeAndName = countryInfoServiceSoapType.listOfCountryNamesByCode();
List tCountryCodeAndNameList = arrayOftCountryCodeAndName.getTCountryCodeAndName();
for(TCountryCodeAndName tCountryCodeAndName:tCountryCodeAndNameList){

String isoCountryCode = tCountryCodeAndName.getSISOCode();
//Add it country to table COUNTRIES when it does not yet exists
if (!landCodesMap.containsKey(tCountryCodeAndName.getSISOCode())) {
System.out.println(” INSERTING IN COUNTRIES TABLE isoCountryCode: "+tCountryCodeAndName.getSISOCode()+" country: "+tCountryCodeAndName.getSName());
// Create new row and add it to the rowset
Row newCounrtyRow = countryVw.createRow();
countryVw.insertRow(newCounrtyRow);

newCounrtyRow.setAttribute("CountryId", tCountryCodeAndName.getSISOCode());
newCounrtyRow.setAttribute("Capital", countryInfoServiceSoapType.capitalCity(isoCountryCode));
newCounrtyRow.setAttribute("Intphonecode", countryInfoServiceSoapType.countryIntPhoneCode(isoCountryCode));
newCounrtyRow.setAttribute("Countryflag", countryInfoServiceSoapType.countryFlag(isoCountryCode));
newCounrtyRow.setAttribute("Languagename", countryInfoServiceSoapType.languageName(isoCountryCode));
newCounrtyRow.setAttribute("CountryName", countryInfoServiceSoapType.countryName(isoCountryCode));
}
}
//

First, we need to identify countries that do not exist yet in our COUNTRIES table. We need a collection (for example a HashMap) with all our current country-records. Later, if the webservice returns a countrycode our hashMap doesnt contain, we know that we have to insert that country in our table.

countryVw.executeQuery();
HashMap landCodesMap = new HashMap();
while (countryVw.hasNext()) {
Row curCountry = countryVw.next();
landCodesMap.put(curCountry.getAttribute("CountryId"),curCountry.getAttribute("CountryName"));

Secondly, we need to get all available country codes from the webservice:

ArrayOftCountryCodeAndName arrayOftCountryCodeAndName = countryInfoServiceSoapType.listOfCountryNamesByCode();
List tCountryCodeAndNameList = arrayOftCountryCodeAndName.getTCountryCodeAndName();

Then, we are going to loop through all the country codes and check whether we need to insert it or not:

for(TCountryCodeAndName tCountryCodeAndName:tCountryCodeAndNameList){
String isoCountryCode = tCountryCodeAndName.getSISOCode();
//Add it country to table COUNTRIES when it does not yet exists
if (!landCodesMap.containsKey(tCountryCodeAndName.getSISOCode())) {
//..
}
}

Then we create a new row and add it to the rowset:

Row newCounrtyRow = countryVw.createRow();
countryVw.insertRow(newCounrtyRow);

And we can set all attribute values:

newCounrtyRow.setAttribute("CountryId", tCountryCodeAndName.getSISOCode());
newCounrtyRow.setAttribute("Capital", countryInfoServiceSoapType.capitalCity(isoCountryCode));
newCounrtyRow.setAttribute("Intphonecode", countryInfoServiceSoapType.countryIntPhoneCode(isoCountryCode));
newCounrtyRow.setAttribute("Countryflag", countryInfoServiceSoapType.countryFlag(isoCountryCode));
newCounrtyRow.setAttribute("Languagename", countryInfoServiceSoapType.languageName(isoCountryCode));
newCounrtyRow.setAttribute("CountryName", countryInfoServiceSoapType.countryName(isoCountryCode));

At the last moment we need to commit the transaction:

am.getTransaction().commit();

2-Run the class. Now, First existing countries are updated and then new countries from the webservice are inserted:

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 30

And when we look at our COUNTRIES table we see all the new countries from the webservice;

Hands-on: Synchronize your database from a webservice with JAX-WS and ADF Business Components 31

Our synchronize-batch task which took approximately 10 minutes to run – has succeeded!

Download this complete sample project from here: CountriesBatchJob.zip
Download this hands-on in word: Hands-on JAX-WS.doc