ESSNET on SDMX II
WP4 “Harmonization of existing tools”
Tutorial of the NSI SDMX Web Service
Final Version 2.3
13.09.2012
Type of Document / Project deliverableReference:
Issue: / Revision: / 2.3 / Status: / Final
Created by: / Emil Hurmuzov / Date: / 13.09.2012
Updated by: / Emil Hurmuzov / 07.07.2012
Approved by:
Document Change Record
Issue/ Revision / Date / Change2.2 / 07.07.2012 / Final version
2.3 / 13.09.2012 / Corrections/Additions based of ESTAT’s feedback
[Title]
Table of contents Page
NSI SDMX WebService JavaEE 6 – Version 2.3 / Date Updated: 9/17/2012 11:43:36 a9/p9 / Page 3 of 27 Page iiiPrepared by: E.H. / Reviewed by:
[Title]
1 Introduction 4
1.1 Purpose 4
1.2 Reference Documents and Standards 4
2 Description of NSI SDM Web Service 5
2.1 Workflow 5
3 Creation of the example 7
3.1 Creating the WSDLs for NSI SDMX WebService 7
3.2 Starting with the Project 7
3.3 Generating Web Service Classes (by JAXB) 10
3.4 Generating JPA Classes from the Database (Census2011MappingStore) 15
3.4.1 Connecting to Mapping Store Database 15
3.4.2 Creating JPA Entities from Database 16
3.4.3 Creating Session Beans for Entity Classes 19
3.5 Implementation of the business logic – SubmitStructureBean 20
4 Preparing test scenarios for the NSI SDMX Web Service 24
5 Using NSI SDMX Web Service 26
NSI SDMX WebService JavaEE 6 – Version 2.3 / Date Updated: 9/17/2012 11:43:36 a9/p9 / Page 3 of 27 Page iiiPrepared by: E.H. / Reviewed by:
[Title]
List of figures Page
NSI SDMX WebService JavaEE 6 – Version 2.3 / Date Updated: 9/17/2012 11:43:36 a9/p9 / Page 3 of 27 Page iiiPrepared by: E.H. / Reviewed by:
[Title]
NSI SDMX WebService JavaEE 6 – Version 2.3 / Date Updated: 9/17/2012 11:43:36 a9/p9 / Page 3 of 27 Page iii
Prepared by: E.H. / Reviewed by:
[Title]
List of tables Page
NSI SDMX WebService JavaEE 6 – Version 2.3 / Date Updated: 9/17/2012 11:43:36 a9/p9 / Page 3 of 27 Page iiiPrepared by: E.H. / Reviewed by:
[Title]
Table 11: Terms and Abbreviations 4
NSI SDMX WebService JavaEE 6 – Version 2.3 / Date Updated: 9/17/2012 11:43:36 a9/p9 / Page 3 of 27 Page iiiPrepared by: E.H. / Reviewed by:
[Title]
NSI SDMX WebService JavaEE 6 – Version 2.3 / Date Updated: 9/17/2012 11:43:36 a9/p9 / Page 3 of 27 Page iii
Prepared by: E.H. / Reviewed by:
[Title]
NSI SDMX WebService JavaEE 6 – Version 2.3 / Date Updated: 9/17/2012 11:43:36 a9/p9 / Page 3 of 27 Page iii
Prepared by: E.H. / Reviewed by:
[Title]
NSI SDMX WebService JavaEE 6 – Version 2.3 / Date Updated: 9/17/2012 11:43:36 a9/p9 / Page 3 of 27 Page iii
Prepared by: E.H. / Reviewed by:
1 Introduction
1.1 Purpose
The purpose of this document is to provide a step-by-step tutorial for building a NSI SDMX Web Service based on a modern Java technologies – Java Enterprise Edition 6. This approach can be used to improve/enhance the current modules of SDMX RI by implementing a particular functionality of SDMX-ML 2.0 for specific needs and environment requirements of NSIs. The current example shows how to implement the “Submit Structure” service that is part of SDMX Registry specification but missing in the implementation of SDMX NSI WebService version 2.3.0.
1.2 Reference Documents and Standards
The following documentation and standards were used in design and development of the example application:
1. SDMX-ML version 2.0 – Schema and Documentation
2. Java Enterprise Edition 6.0
Terms and abbreviations
Acronym / Definition /JavaEE 6 / Java Enterprise Edition version 6
JAX-WS / Java API for XML Web Services
JPA / Java Persistence API
EJB 3.1 / Enterprise Java Bean version 3.1
CDI / Contexts and Dependency Injection
POJO / Plain Old Java Object
JAXB / JavaArchitectureforXMLBinding
WSDL / Web Service Definition Language
Table 11: Terms and Abbreviations
26
2 Description of NSI SDMX Web Service
NSI SDMX Web Service is an implementation of the SDMX 2.0 standard. This implementation is based on JavaEE v.6 and can be run on any application server that supports this specification with very little changes in the deployment configurations. Current version runs on Glassfish v. 3.x server which is the reference implementation of the JavaEE 6 specification.
Below is a list with advantages of the provided approach:
1. It can be used with any version of the SDMX standard. And even more – with any combination of versions of SDMX-ML and Mapping Store Database.
2. It can be deployed on a preferred by the organization environment and not on the required by the SDMX RI implementation.
3. It’s not an easy task for a developer to “inject” new functionality into the existing code of the SDMX RI. This requires senior level of experience, risks of breaking another functionality and need of extensive testing of full functionality.
The main disadvantage of this approach is the impossibility to support more than a one particular version of the SDMX ML specification. That is because the application does not support a concept like the SDMX Model, used in the SDMX RI.
The application uses following technologies:
· Java API for XML-Based Web Services (JAX-WS) 2.2
· JavaArchitectureforXMLBinding(JAXB)2.2
· Enterprise JavaBeans 3.1
· Java Persistence 2.0
2.1 Workflow
The application has following main modules:
ñ Web Service – this module is based on the JAX-WS standard. It contains POJO Java classes that correspond to the structures defined in XSDs and WSDLs and generated by JAXB technology. The module automatically transforms the received Web Service request from XML to Java classes – ready for using in the Business logic.
The response of the Web Service is generated in the same way – Business Logic creates Java classes containing result data and passes them to the Web Service which automatically generates valid XML for the response.
ñ Data Access – this module is based on the JPA standard. In current example the Java classes that correspond to the Database tables and relations between them are generated from the existing test Database – Census2011MappingStore – used in BNSI which is based on the version 2.5 of the Mapping Store from SDMX RI and used for the Census Hub project.
The module is configured to use a container managed transactions and this eliminates the need of manually control the transaction boundaries.
ñ Business Logic – this module is responsible for decisions based on the web service request – for example – StructureSubmit request may contains actions “Insert”, “Update“ or “Delete”.
ñ Response Builder is a very simple module. It just generates Java objects containing response data that should be included in the response XML and returned to the client.
Figure 2 NSI SDMX Web Service Component diagram
3 Creation of the example
The creation of the NSI SDMX WebService requires the following development environment to be installed before starting:
ñ JDK 6 (or later)
ñ Netbeans IDE 7 or later
ñ Glassfish 3.1 or later
3.1 Creating the WSDLs for NSI SDMX WebService
In this application we are creating two WSDL files – sdmxabstract.wsdl and sdmx.wsdl.
The sdmxabstract.wsdl file is an abstract definition of the web service – it contains:
ñ imports of SDMX standard XSDs
ñ definitions of types
ñ definitions of messages
ñ definition of operations (in portType section)
The sdmx.wsdl contains import of sdmxabstract.wsdl and concrete bindings to SOAP transport.
The splitting of the WSDL to abstract and implementation is a good practice in providing modules to other developers for reuse. The abstract WSDL provides (describes) all standard functionality of the web service and can be used without any change in any deployment environment. The implementation WSDL should be created by the implementer based on the concrete deployment environment and technology used in this implementation – for example SOAP transport, JMS Transport, Integration applications as Tibco etc.
The next important step is to define a ResponseFault type which we'll use to send back an error code (info) to the client in case of failure of the service or other application problems.
3.2 Starting with the Project
ñ File → New Project → Categories: Java ЕЕ; Projects: EJB Module. Next
ñ Enter Project Name and Project Location. Next.
ñ Choose Glassfish 3.1 server, Java EE Version: Java EE 6; and Enable Context and Dependency Injection.
ñ Finish and the project skeleton is ready.
ñ
Create a wsdl folder into the project folder and copy sdmxabstract.wsdl and sdmx.wsdl files. Copy all XSD files in xsds folder. The project folder should looks like this:
3.3 Generating Web Service Classes (by JAXB)
Right click on the Project name – SdmxService and choose New → Other. From Categories select Web Services and from File Types select WebService from WSDL. Click Next.
Fill the next page with the following data and press Finish:
This action will parse the WSDLs and XSDs and create Java classes (in Generated Sources (jax-ws) folder) and SdmxService.java class. This class is a Stateless EJB which will be responsible for accepting web service calls from the clients.
To generate a more readable and usable code (it depends on developer's style of working with web services) right click the sdmxService item in the Web Services folder of the project and select “Edit Web Service Attributes”. Select WSDL Customization and disable the Wrapper Style option:
The same result can be achieved using the command line tool wsimport. The documentation is available on http://docs.oracle.com/javase/6/docs/technotes/tools/share/wsimport.html.
After finishing the “Create Web Service from WSDL” action the project contains following items:
@WebService(serviceName = "sdmxService", portName = "sdmxPort",
endpointInterface = "com.hurmuzov.sdmx.wsdl.sdmxservice.binding.SdmxPortType",
targetNamespace = "http://hurmuzov.com/sdmx/wsdl/SdmxService/Binding",
wsdlLocation = "META-INF/wsdl/SdmxService/sdmx.wsdl")
@Stateless
public class SdmxService {
…...
}
This is how the generated SdmxService.java file looks like.
The wizard generates empty class methods for every web service method:
public GetKeyFamilyResponse getKeyFamily(GetKeyFamily request)
throws ResponseFault {
//TODO implement this method
throw new UnsupportedOperationException("Not implemented yet.");
}
Below is the code of the SubmitStructure Web service method. All methods of the Web Service have the same simple structure:
· Defines the Response class;
· Checks for not null request message and returns a ResponseFault message in this case;
· In a try-catch block calls the submitStructure method of the injected SubmitStructureBean and assigns the response to the declared Response class. In case of Exception – generates an appropriate ResponseFault and throws it.
public SubmitStructureResponse submitStructure(SubmitStructure request)
throws ResponseFault {
SubmitStructureResponse response;
if (request == null ||
request.getRegistryInterface() == null ||
request.getRegistryInterface()
.getSubmitStructureRequest() == null) {
throw buildResponseFaultNoRequest();
}
try {
response = ssBean.submitStructure(request.getRegistryInterface().getSubmitStructureRequest());
} catch (SdmxServiceException sse) {
ResponseFault fault = buildResponseFault(sse);
throw fault;
}
return response;
}
3.4 Generating JPA Classes from the Database (Census2011MappingStore)
3.4.1 Connecting to Mapping Store Database
To connect to the Mapping Store we are using the wizard of the Netbeans – Right click the Microfoft SQL Server Driver in the Services tab and click Connect using… from the menu. Fill in the required data to connect to the Database:
This step creates a connection to the Database which will be used to create a JDBC connection pool in the Glassfish server on deployment of the application.
3.4.2 Creating JPA Entities from Database
To create a JPA Entities we’re using the Netbeans’ wizard – right click the SdmxService project and select New -> Other. From the next screen select Persistence for Category and Entity Classes from Database for File Type.
On the next window first choose the created connection to the Mapping Store database for Database Connection. Then click the Add All button. This will generate Entity Classes for all database tables.
Here is an example of the generated Entity classes – Artefact.java. Some fine-tuning additions to the class was made (for example to and a generated value to the table’s ID column with the table strategy:
@Entity
@Table(name = "ARTEFACT")
@XmlRootElement
@NamedQueries({
@NamedQuery(name = "Artefact.findAll", query = "SELECT a FROM Artefact a"),
..MORE NAMED QUERY LINES ..
@NamedQuery(name = "Artefact.findByIsFinal", query = "SELECT a FROM Artefact a WHERE a.isFinal = :isFinal")})
public class Artefact implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(generator="InvTab")
@TableGenerator(name="InvTab", table="SEQUENCE_ID",
pkColumnName="TABLE_NAME", valueColumnName="LAST_ID",
pkColumnValue="ALL")
@Basic(optional = false)
@Column(name = "ART_ID")
private Long artId;
@Column(name = "ID")
private String id;
@Basic(optional = false)
@Column(name = "VERSION")
private String version;
@Column(name = "AGENCY")
private String agency;
@Column(name = "VALID_FROM")
private String validFrom;
@Column(name = "VALID_TO")
private String validTo;
@Column(name = "IS_FINAL")
private Boolean isFinal;
@OneToOne(cascade = CascadeType.ALL, mappedBy = "artefact")
private Codelist codelist;
@OneToOne(cascade = CascadeType.ALL, mappedBy = "artefact")
private Dsd dsd;
@OneToOne(cascade = CascadeType.ALL, mappedBy = "artefact")
private Hierarchy hierarchy;
@OneToOne(cascade = CascadeType.ALL, mappedBy = "artefact")
private HclCode hclCode;
@OneToOne(cascade = CascadeType.ALL, mappedBy = "artefact")
private Hcl hcl;
@OneToMany(mappedBy = "artefact")
private Collection<LocalisedString> localisedStringCollection;
@OneToOne(cascade = CascadeType.ALL, mappedBy = "artefact")
private Dataflow dataflow;
@OneToOne(cascade = CascadeType.ALL, mappedBy = "artefact")
private ConceptScheme conceptScheme;
@OneToOne(cascade = CascadeType.ALL, mappedBy = "artefact")
private CategoryScheme categoryScheme;
@OneToOne(cascade = CascadeType.ALL, mappedBy = "artefact")
private Hlevel hlevel;
public Artefact() {
}
public Artefact(Long artId) {
this.artId = artId;
}
public Artefact(Long artId, String version) {
this.artId = artId;
this.version = version;
}
.. Getters and Setters..
3.4.3 Creating Session Beans for Entity Classes
As Entity classes are just an annotated POJO classes we need an additional layer that will operate over these classes. This layer will be implemented as a Stateless session beans.
Right click the SdmxService project and select New->Other. From the next screen select Persistence for Category and Session Beans for Entity Classes for File Type.
On the next screen select Add All and Next.
These steps generates Session beans for Entity classes that provide basic functionality for manipulating entities – create, edit, remove, find, count, etc.