Implementing a JAXR Client
This section describes the basic steps to follow in order to implement a JAXR client that can perform queries and updates to a UDDI registry. A JAXR client is a client program that can access registries using the JAXR API. This section covers the following topics:
This tutorial does not describe how to implement a JAXR provider. A JAXR provider provides an implementation of the JAXR specification that allows access to an existing registry provider, such as a UDDI or ebXML registry. The implementation of JAXR in the Application Server is an example of a JAXR provider.
The Application Server provides JAXR in the form of a resource adapter using the Java EE Connector architecture. The resource adapter is in the directory
<JAVAEE_HOME>/lib/install/applications/jaxr-ra. (<JAVAEE_HOME>is the directory where the Application Server is installed.)This tutorial includes several client examples, which are described in Running the Client Examples, and a Java EE application example, described in Using JAXR Clients in Java EE Applications. The examples are in the directory
<INSTALL>/javaeetutorial5/examples/jaxr/. (<INSTALL>is the directory where you installed the tutorial bundle.) Each example directory has abuild.xmlfile that refers to targets in the directory<INSTALL>/javaeetutorial5/examples/bp-project/.Establishing a Connection
The first task a JAXR client must complete is to establish a connection to a registry. Establishing a connection involves the following tasks:
Preliminaries: Getting Access to a Registry
To use the Java WSDP Registry Server, a private UDDI version 2 registry, you need to download and install Java WSDP 1.5 and then to install the Registry Server in the Application Server.
To download Java WSDP 1.5, perform these steps:
- Go to the following URL:
http://java.sun.com/webservices/downloads/1.5/index.html- Under Java Web Services Developer Pack v1.5, click Download.
- On the Login page, click the Download link. (You do not have to log in.)
- Select the Accept radio button to accept the license agreement.
- Click the download arrow for your platform (Solaris or Windows).
- Choose the directory where you will download Java WSDP.
Install Java WSDP as follows:
- Go to the directory where you downloaded Java WSDP 1.5.
- Run the Java WSDP installer. You can follow the instructions that are linked to from
http://java.sun.com/webservices/downloads/1.5/index.html, although these instructions refer to a newer version of Java WSDP.- On the Select a Web Container page of the installer, select No Web Container.
- Choose a directory where you will install Java WSDP.
- Select either a Typical or a Custom installation. If you select Custom, remove the check marks from every checkbox you can except Java WSDP Registry Server. (You cannot remove the check marks from JAXB, JAXP, JAXR, or SAAJ; these technologies are required.)
After the installation completes, install the Registry Server in the Application Server as follows:
- Stop the Application Server if it is running.
- Copy the two WAR files in the directory
<JWSDP_HOME>/registry-server/webapps,RegistryServer.warandXindice.war, to the following directory:
<JAVAEE_HOME>/domains/domain1/autodeploy- Copy the file
<JWSDP_HOME>/jwsdp-shared/lib/commons-logging.jarto the following directory:
<JAVAEE_HOME>/lib- Start the Application Server.
Any user of a JAXR client can perform queries on a registry. To add data to the registry or to update registry data, however, a user must obtain permission from the registry to access it.
To add or update data in the Java WSDP Registry Server, you can use the default user name and password,
testuserandtestuser.Obtaining a Connection Factory
A client creates a connection from a connection factory. A JAXR provider can supply one or more preconfigured connection factories. Clients can obtain these factories by using resource injection.
At this release of the Application Server, JAXR supplies a connection factory through the JAXR RA, but you need to use a connector resource whose JNDI name is
eis/JAXRto access this connection factory from a Java EE application. To inject this resource in a Java EE component, use code like the following:import javax.annotation.Resource;.*; import javax.xml.registry.ConnectionFactory; ... @Resource(mappedName="eis/JAXR") public ConnectionFactory factory;Later in this chapter you will learn how to create this connector resource.
To use JAXR in a stand-alone client program, you must create an instance of the abstract class
ConnectionFactory:import javax.xml.registry.ConnectionFactory; ... ConnectionFactory connFactory = ConnectionFactory.newInstance();Creating a Connection
To create a connection, a client first creates a set of properties that specify the URL or URLs of the registry or registries being accessed. For example, the following code provides the URLs of the query service and publishing service for a hypothetical registry. (There should be no line break in the strings.)
Properties props = new Properties(); props.setProperty("javax.xml.registry.queryManagerURL", "http://localhost:8080/RegistryServer/"); props.setProperty("javax.xml.registry.lifeCycleManagerURL", "http://localhost:8080/RegistryServer/");With the Application Server implementation of JAXR, if the client is accessing a registry that is outside a firewall, it must also specify proxy host and port information for the network on which it is running. For queries it may need to specify only the HTTP proxy host and port; for updates it must specify the HTTPS proxy host and port.
props.setProperty("com.sun.xml.registry.http.proxyHost", "myhost.mydomain"); props.setProperty("com.sun.xml.registry.http.proxyPort", "8080"); props.setProperty("com.sun.xml.registry.https.proxyHost", "myhost.mydomain"); props.setProperty("com.sun.xml.registry.https.proxyPort", "8080");The client then sets the properties for the connection factory and creates the connection:
The
makeConnectionmethod in the sample programs shows the steps used to create a JAXR connection.Setting Connection Properties
The implementation of JAXR in the Application Server allows you to set a number of properties on a JAXR connection. Some of these are standard properties defined in the JAXR specification. Other properties are specific to the implementation of JAXR in the Application Server. Tables 19-1 and 19-2 list and describe these properties.
Table 19-1 Standard JAXR Connection Properties Property Name and Description Data Type Default Valuejavax.xml.registry.queryManagerURLSpecifies the URL of the query manager service within the target registry provider. String Nonejavax.xml.registry.lifeCycleManagerURLSpecifies the URL of the life-cycle manager service within the target registry provider (for registry updates). String Same as the specifiedqueryManagerURLvaluejavax.xml.registry.semanticEquivalencesSpecifies semantic equivalences of concepts as one or more tuples of the ID values of two equivalent concepts separated by a comma. The tuples are separated by vertical bars:id1,id2|id3,id4 String Nonejavax.xml.registry.security.authenticationMethodProvides a hint to the JAXR provider on the authentication method to be used for authenticating with the registry provider. String None;UDDI_GET_AUTHTOKENis the only supported valuejavax.xml.registry.uddi.maxRowsThe maximum number of rows to be returned by find operations. Specific to UDDI providers. String 100javax.xml.registry.postalAddressSchemeThe ID of aClassificationSchemeto be used as the default postal address scheme. See Specifying Postal Addresses for an example. String None
Table 19-2 Implementation-Specific JAXR Connection Properties Property Name and Description Data Type Default Valuecom.sun.xml.registry.http.proxyHostSpecifies the HTTP proxy host to be used for accessing external registries. String Nonecom.sun.xml.registry.http.proxyPortSpecifies the HTTP proxy port to be used for accessing external registries; usually 8080. String Nonecom.sun.xml.registry.https.proxyHostSpecifies the HTTPS proxy host to be used for accessing external registries. String Same as HTTP proxy host valuecom.sun.xml.registry.https.proxyPortSpecifies the HTTPS proxy port to be used for accessing external registries; usually 8080. String Same as HTTP proxy port valuecom.sun.xml.registry.http.proxyUserNameSpecifies the user name for the proxy host for HTTP proxy authentication, if one is required. String Nonecom.sun.xml.registry.http.proxyPasswordSpecifies the password for the proxy host for HTTP proxy authentication, if one is required. String Nonecom.sun.xml.registry.useCacheTells the JAXR implementation to look for registry objects in the cache first and then to look in the registry if not found. Boolean, passed in as String Truecom.sun.xml.registry.userTaxonomyFilenamesFor details on setting this property, see Defining a Taxonomy. String None
Obtaining and Using a RegistryService Object
After creating the connection, the client uses the connection to obtain a
RegistryServiceobject and then the interface or interfaces it will use:RegistryService rs = connection.getRegistryService(); BusinessQueryManager bqm = rs.getBusinessQueryManager(); BusinessLifeCycleManager blcm = rs.getBusinessLifeCycleManager();Typically, a client obtains both a
BusinessQueryManagerobject and aBusinessLifeCycleManagerobject from theRegistryServiceobject. If it is using the registry for simple queries only, it may need to obtain only aBusinessQueryManagerobject.Querying a Registry
The simplest way for a client to use a registry is to query it for information about the organizations that have submitted data to it. The
BusinessQueryManagerinterface supports a number of find methods that allow clients to search for data using the JAXR information model. Many of these methods return aBulkResponse(a collection of objects) that meets a set of criteria specified in the method arguments. The most useful of these methods are as follows:
findOrganizations, which returns a list of organizations that meet the specified criteria--often a name pattern or a classification within a classification schemefindServices, which returns a set of services offered by a specified organizationfindServiceBindings, which returns the service bindings (information about how to access the service) that are supported by a specified serviceThe
JAXRQueryprogram illustrates how to query a registry by organization name and display the data returned. TheJAXRQueryByNAICSClassificationandJAXRQueryByWSDLClassificationprograms illustrate how to query a registry using classifications. All JAXR providers support at least the following taxonomies for classifications:
- The North American Industry Classification System (NAICS). See
http://www.census.gov/epcd/www/naics.htmlfor details.- The Universal Standard Products and Services Classification (UNSPSC). See
http://www.eccma.org/unspsc/for details.- The ISO 3166 country codes classification system maintained by the International Organization for Standardization (ISO). See
http://www.iso.org/iso/en/prods-services/iso3166ma/for details.
index.htmlThe following sections describe how to perform some common queries:
Finding Organizations by Name
To search for organizations by name, you normally use a combination of find qualifiers (which affect sorting and pattern matching) and name patterns (which specify the strings to be searched). The
findOrganizationsmethod takes a collection offindQualifierobjects as its first argument and takes a collection ofnamePatternobjects as its second argument. The following fragment shows how to find all the organizations in the registry whose names begin with a specified string,qString, and sort them in alphabetical order.// Define find qualifiers and name patterns Collection<String> findQualifiers = new ArrayList<String>(); findQualifiers.add(FindQualifier.SORT_BY_NAME_DESC); Collection<String> namePatterns = new ArrayList<String>(); namePatterns.add(qString); // Find orgs whose names begin with qString BulkResponse response = bqm.findOrganizations(findQualifiers, namePatterns, null, null, null, null); Collection orgs = response.getCollection();The last four arguments to
findOrganizationsallow you to search using other criteria than the name: classifications, specification concepts, external identifiers, or external links. Finding Organizations by Classification describes searching by classification and by specification concept. The other searches are less common and are not described in this tutorial.A client can use percent signs (
%) to specify that the query string can occur anywhere within the organization name. For example, the following code fragment performs a case-sensitive search for organizations whose names containqString:Collection<String> findQualifiers = new ArrayList<String>(); findQualifiers.add(FindQualifier.CASE_SENSITIVE_MATCH); Collection<String> namePatterns = new ArrayList<String>(); namePatterns.add("%" + qString + "%"); // Find orgs with names that contain qString BulkResponse response = bqm.findOrganizations(findQualifiers, namePatterns, null, null, null, null); Collection orgs = response.getCollection();Finding Organizations by Classification
To find organizations by classification, you establish the classification within a particular classification scheme and then specify the classification as an argument to the
findOrganizationsmethod.The following code fragment finds all organizations that correspond to a particular classification within the NAICS taxonomy. (You can find the NAICS codes at
http://www.census.gov/epcd/naics/naicscod.txt.)The NAICS taxonomy has a well-known universally unique identifier (UUID) that is defined by the UDDI specification. ThegetRegistryObjectmethod finds an object based upon its key. (See Creating an Organization for more information about keys)String uuid_naics = "uuid:C0B9FE13-179F-413D-8A5B-5004DB8E5BB2"; ClassificationScheme cScheme = (ClassificationScheme) bqm.getRegistryObject(uuid_naics, LifeCycleManager.CLASSIFICATION_SCHEME); InternationalString sn = blcm.createInternationalString( "All Other Specialty Food Stores")); String sv = "445299"; Classification classification = blcm.createClassification(cScheme, sn, sv); Collection<Classification> classifications = new ArrayList<Classification>(); classifications.add(classification); BulkResponse response = bqm.findOrganizations(null, null, classifications, null, null, null); Collection orgs = response.getCollection();You can also use classifications to find organizations that offer services based on technical specifications that take the form of WSDL (Web Services Description Language) documents. In JAXR, a concept is used as a proxy to hold the information about a specification. The steps are a little more complicated than in the preceding example, because the client must first find the specification concepts and then find the organizations that use those concepts.
The following code fragment finds all the WSDL specification instances used within a given registry. You can see that the code is similar to the NAICS query code except that it ends with a call to
findConceptsinstead offindOrganizations.String schemeName = "uddi-org:types"; ClassificationScheme uddiOrgTypes = bqm.findClassificationSchemeByName(null, schemeName); /* * Create a classification, specifying the scheme * and the taxonomy name and value defined for WSDL * documents by the UDDI specification. */ Classification wsdlSpecClassification = blcm.createClassification(uddiOrgTypes, "wsdlSpec", "wsdlSpec"); Collection<Classification> classifications = new ArrayList<Classification>(); classifications.add(wsdlSpecClassification); // Find concepts BulkResponse br = bqm.findConcepts(null, null, classifications, null, null);To narrow the search, you could use other arguments of the
findConceptsmethod (search qualifiers, names, external identifiers, or external links).The next step is to go through the concepts, find the WSDL documents they correspond to, and display the organizations that use each document:
// Display information about the concepts found Collection specConcepts = br.getCollection(); Iterator iter = specConcepts.iterator(); if (!iter.hasNext()) { System.out.println("No WSDL specification concepts found"); } else { while (iter.hasNext()) { Concept concept = (Concept) iter.next(); String name = getName(concept); Collection links = concept.getExternalLinks(); System.out.println("\nSpecification Concept:\n\tName: " + name + "\n\tKey: " + concept.getKey().getId() + "\n\tDescription: " + getDescription(concept)); if (links.size() > 0) { ExternalLink link = (ExternalLink) links.iterator().next(); System.out.println("\tURL of WSDL document: '" + link.getExternalURI() + "'"); } // Find organizations that use this concept Collection<Concept> specConcepts1 = new ArrayList<Concept>(); specConcepts1.add(concept); br = bqm.findOrganizations(null, null, null, specConcepts1, null, null); // Display information about organizations ... } }If you find an organization that offers a service you wish to use, you can invoke the service using JAX-WS.
Finding Services and Service Bindings
After a client has located an organization, it can find that organization's services and the service bindings associated with those services.
Iterator orgIter = orgs.iterator(); while (orgIter.hasNext()) { Organization org = (Organization) orgIter.next(); Collection services = org.getServices(); Iterator svcIter = services.iterator(); while (svcIter.hasNext()) { Service svc = (Service) svcIter.next(); Collection serviceBindings = svc.getServiceBindings(); Iterator sbIter = serviceBindings.iterator(); while (sbIter.hasNext()) { ServiceBinding sb = (ServiceBinding) sbIter.next(); } } }Managing Registry Data
If a client has authorization to do so, it can submit data to a registry, modify it, and remove it. It uses the
BusinessLifeCycleManagerinterface to perform these tasks.Registries usually allow a client to modify or remove data only if the data is being modified or removed by the same user who first submitted the data.
Managing registry data involves the following tasks:
Getting Authorization from the Registry
Before it can submit data, the client must send its user name and password to the registry in a set of credentials. The following code fragment shows how to do this.
String username = "testuser"; String password = "testuser"; // Get authorization from the registry PasswordAuthentication passwdAuth = new PasswordAuthentication(username, password.toCharArray()); HashSet<PasswordAuthentication> creds = new HashSet<PasswordAuthentication>(); creds.add(passwdAuth); connection.setCredentials(creds);Creating an Organization
The client creates the organization and populates it with data before publishing it.
An
Organizationobject is one of the more complex data items in the JAXR API. It normally includes the following:
- A
Nameobject.- A
Descriptionobject.- A
Keyobject, representing the ID by which the organization is known to the registry. This key is created by the registry, not by the user, and is returned after the organization is submitted to the registry.- A
PrimaryContactobject, which is aUserobject that refers to an authorized user of the registry. AUserobject normally includes aPersonNameobject and collections ofTelephoneNumber,EmailAddress, andPostalAddressobjects.- A collection of
Classificationobjects.Serviceobjects and their associatedServiceBindingobjects.For example, the following code fragment creates an organization and specifies its name, description, and primary contact. When a client creates an organization to be published to a UDDI registry, it does not include a key; the registry returns the new key when it accepts the newly created organization. The
blcmobject in the following code fragment is theBusinessLifeCycleManagerobject returned in Obtaining and Using a RegistryService Object. AnInternationalStringobject is used for string values that may need to be localized.// Create organization name and description InternationalString s = blcm.createInternationalString("The Coffee Break"); Organization org = blcm.createOrganization(s); s = blcm.createInternationalString("Purveyor of the " + "finest coffees. Established 1950"); org.setDescription(s); // Create primary contact, set name User primaryContact = blcm.createUser(); PersonName pName = blcm.createPersonName("Jane Doe"); primaryContact.setPersonName(pName); // Set primary contact phone number TelephoneNumber tNum = blcm.createTelephoneNumber(); tNum.setNumber("(800) 555-1212"); Collection<TelephoneNumber> phoneNums = new ArrayList<TelephoneNumber>(); phoneNums.add(tNum); primaryContact.setTelephoneNumbers(phoneNums); // Set primary contact email address EmailAddress emailAddress = blcm.createEmailAddress("jane.doe@TheCoffeeBreak.com"); Collection<EmailAddress> emailAddresses = new ArrayList<EmailAddress>(); emailAddresses.add(emailAddress); primaryContact.setEmailAddresses(emailAddresses); // Set primary contact for organization org.setPrimaryContact(primaryContact);Adding Classifications
Organizations commonly belong to one or more classifications based on one or more classification schemes (taxonomies). To establish a classification for an organization using a taxonomy, the client first locates the taxonomy it wants to use. It uses the
BusinessQueryManagerto find the taxonomy. ThefindClassificationSchemeByNamemethod takes a set ofFindQualifierobjects as its first argument, but this argument can be null.// Set classification scheme to NAICS ClassificationScheme cScheme = bqm.findClassificationSchemeByName(null, "ntis-gov:naics:1997");The client then creates a classification using the classification scheme and a concept (a taxonomy element) within the classification scheme. For example, the following code sets up a classification for the organization within the NAICS taxonomy. The second and third arguments of the
createClassificationmethod are the name and the value of the concept.// Create and add classification InternationalString sn = blcm.createInternationalString( "All Other Specialty Food Stores")); String sv = "445299"; Classification classification = blcm.createClassification(cScheme, sn, sv); Collection<Classification> classifications = new ArrayList<Classification>(); classifications.add(classification); org.addClassifications(classifications);Services also use classifications, so you can use similar code to add a classification to a
Serviceobject.Adding Services and Service Bindings to an Organization
Most organizations add themselves to a registry in order to offer services, so the JAXR API has facilities to add services and service bindings to an organization.
Like an
Organizationobject, aServiceobject has a name, a description, and a unique key that is generated by the registry when the service is registered. It may also have classifications associated with it.A service also commonly has service bindings, which provide information about how to access the service. A
ServiceBindingobject normally has a description, an access URI, and a specification link, which provides the linkage between a service binding and a technical specification that describes how to use the service by using the service binding.The following code fragment shows how to create a collection of services, add service bindings to a service, and then add the services to the organization. It specifies an access URI but not a specification link. Because the access URI is not real and because JAXR by default checks for the validity of any published URI, the binding sets its
validateURIproperty to false.// Create services and service Collection<Service> services = new ArrayList<Service>(); InternationalString s = blcm.createInternationalString("My Service Name")); Service service = blcm.createService(s); s = blcm.createInternationalString("My Service Description"); service.setDescription(is); // Create service bindings Collection<ServiceBinding> serviceBindings = new ArrayList<ServiceBinding>(); ServiceBinding binding = blcm.createServiceBinding(); s = blcm.createInternationalString("My Service Binding " + "Description"); binding.setDescription(is); // allow us to publish a fictitious URI without an error binding.setValidateURI(false); binding.setAccessURI("http://TheCoffeeBreak.com:8080/sb/"); serviceBindings.add(binding); // Add service bindings to service service.addServiceBindings(serviceBindings); // Add service to services, then add services to organization services.add(service); org.addServices(services);Publishing an Organization
The primary method a client uses to add or modify organization data is the
saveOrganizationsmethod, which creates one or more new organizations in a registry if they did not exist previously. If one of the organizations exists but some of the data have changed, thesaveOrganizationsmethod updates and replaces the data.After a client populates an organization with the information it wants to make public, it saves the organization. The registry returns the key in its response, and the client retrieves it.
// Add organization and submit to registry // Retrieve key if successful Collection<Organization> orgs = new ArrayList<Organization>(); orgs.add(org); BulkResponse response = blcm.saveOrganizations(orgs); Collection exceptions = response.getException(); if (exceptions == null) { System.out.println("Organization saved"); Collection keys = response.getCollection(); Iterator keyIter = keys.iterator(); if (keyIter.hasNext()) { Key orgKey = (Key) keyIter.next(); String id = orgKey.getId(); System.out.println("Organization key is " + id); } }Publishing a Specification Concept
A service binding can have a technical specification that describes how to access the service. An example of such a specification is a WSDL document. To publish the location of a service's specification (if the specification is a WSDL document), you create a
Conceptobject and then add the URL of the WSDL document to theConceptobject as anExternalLinkobject. The following code fragment shows how to create a concept for the WSDL document associated with the simple web service example in Creating a Simple Web Service and Client with JAX-WS (page 498). First, you call thecreateConceptmethod to create a concept namedHelloConcept. After setting the description of the concept, you create an external link to the URL of theHelloservice's WSDL document, and then add the external link to the concept.Concept specConcept = blcm.createConcept(null, "HelloConcept", ""); InternationalString s = blcm.createInternationalString( "Concept for Hello Service"); specConcept.setDescription(s); ExternalLink wsdlLink = blcm.createExternalLink( "http://localhost:8080/hello-jaxws/hello?WSDL", "Hello WSDL document"); specConcept.addExternalLink(wsdlLink);Next, you classify the
Conceptobject as a WSDL document. To do this for a UDDI registry, you search the registry for the well-known classification schemeuddi-org:types, using its key ID. (The UDDI term for a classification scheme is tModel.) Then you create a classification using the name and valuewsdlSpec. Finally, you add the classification to the concept.String uuid_types = "uuid:c1acf26d-9672-4404-9d70-39b756e62ab4"; ClassificationScheme uddiOrgTypes = (ClassificationScheme) bqm.getRegistryObject(uuid_types, LifeCycleManager.CLASSIFICATION_SCHEME); Classification wsdlSpecClassification = blcm.createClassification(uddiOrgTypes, "wsdlSpec", "wsdlSpec"); specConcept.addClassification(wsdlSpecClassification);Finally, you save the concept using the
saveConceptsmethod, similarly to the way you save an organization:Collection<Concept> concepts = new ArrayList<Concept>(); concepts.add(specConcept); BulkResponse concResponse = blcm.saveConcepts(concepts);After you have published the concept, you normally add the concept for the WSDL document to a service binding. To do this, you can retrieve the key for the concept from the response returned by the
saveConceptsmethod; you use a code sequence very similar to that of finding the key for a saved organization.String conceptKeyId = null; Collection concExceptions = concResponse.getExceptions(); Key concKey = null; if (concExceptions == null) { System.out.println("WSDL Specification Concept saved"); Collection keys = concResponse.getCollection(); Iterator keyIter = keys.iterator(); if (keyIter.hasNext()) { concKey = (Key) keyIter.next(); conceptKeyId = concKey.getId(); System.out.println("Concept key is " + conceptKeyId); } }Then you can call the
getRegistryObjectmethod to retrieve the concept from the registry:Next, you create a
SpecificationLinkobject for the service binding and set the concept as the value of itsSpecificationObject:SpecificationLink specLink = blcm.createSpecificationLink(); specLink.setSpecificationObject(specConcept); binding.addSpecificationLink(specLink);Now when you publish the organization with its service and service bindings, you have also published a link to the WSDL document. Now the organization can be found via queries such as those described in Finding Organizations by Classification.
If the concept was published by someone else and you don't have access to the key, you can find it using its name and classification. The code looks very similar to the code used to search for a WSDL document in Finding Organizations by Classification, except that you also create a collection of name patterns and include that in your search. Here is an example:
// Define name pattern Collection namePatterns = new ArrayList(); namePatterns.add("HelloConcept"); BulkResponse br = bqm.findConcepts(null, namePatterns, classifications, null, null);Removing Data from the Registry
A registry allows you to remove from it any data that you have submitted to it. You use the key returned by the registry as an argument to one of the
BusinessLifeCycleManagerdelete methods:deleteOrganizations,deleteServices,deleteServiceBindings,deleteConcepts, and others.The
JAXRDeletesample program deletes the organization created by theJAXRPublishprogram. It deletes the organization that corresponds to a specified key string and then displays the key again so that the user can confirm that it has deleted the correct one.String id = key.getId(); System.out.println("Deleting organization with id " + id); Collection<Key> keys = new ArrayList<Key>(); keys.add(key); BulkResponse response = blcm.deleteOrganizations(keys); Collection exceptions = response.getException(); if (exceptions == null) { System.out.println("Organization deleted"); Collection retKeys = response.getCollection(); Iterator keyIter = retKeys.iterator(); Key orgKey = null; if (keyIter.hasNext()) { orgKey = (Key) keyIter.next(); id = orgKey.getId(); System.out.println("Organization key was " + id); } }A client can use a similar mechanism to delete concepts, services, and service bindings.
Using Taxonomies in JAXR Clients
In the JAXR API, a taxonomy is represented by a
ClassificationSchemeobject. This section describes how to use the implementation of JAXR in the Application Server to perform these tasks:Defining a Taxonomy
The JAXR specification requires that a JAXR provider be able to add user-defined taxonomies for use by JAXR clients. The mechanisms clients use to add and administer these taxonomies are implementation-specific.
The implementation of JAXR in the Application Server uses a simple file-based approach to provide taxonomies to the JAXR client. These files are read at runtime, when the JAXR provider starts up.
The taxonomy structure for the Application Server is defined by the JAXR Predefined Concepts DTD, which is declared both in the file
jaxrconcepts.dtdand, in XML schema form, in the filejaxrconcepts.xsd. The filejaxrconcepts.xmlcontains the taxonomies for the implementation of JAXR in the Application Server. All these files are contained in the<JAVAEE_HOME>/lib/appserv-ws.jarfile. This JAR file also includes files that define the well-known taxonomies used by the implementation of JAXR in the Application Server:naics.xml,iso3166.xml, andunspsc.xml.The entries in the
jaxrconcepts.xmlfile look like this:<PredefinedConcepts> <JAXRClassificationScheme id="schId" name="schName"> <JAXRConcept id="schId/conCode" name="conName" parent="parentId" code="conCode"> </JAXRConcept> ... </JAXRClassificationScheme> </PredefinedConcepts>The taxonomy structure is a containment-based structure. The element
PredefinedConceptsis the root of the structure and must be present. TheJAXRClassificationSchemeelement is the parent of the structure, and theJAXRConceptelements are children and grandchildren. AJAXRConceptelement may have children, but it is not required to do so.In all element definitions, attribute order and case are significant.
To add a user-defined taxonomy, follow these steps.
- Publish the
JAXRClassificationSchemeelement for the taxonomy as aClassificationSchemeobject in the registry that you will be accessing. To publish aClassificationSchemeobject, you must set its name. You also give the scheme a classification within a known classification scheme such asuddi-org:types. In the following code fragment, the name is the first argument of theLifeCycleManager.createClassificationSchememethod call.
InternationalString sn =
blcm.createInternationalString("MyScheme");
InternationalString sd = blcm.createInternationalString(
"A Classification Scheme");
ClassificationScheme postalScheme =
blcm.createClassificationScheme(sn, sd);
String uuid_types =
"uuid:c1acf26d-9672-4404-9d70-39b756e62ab4";
ClassificationScheme uddiOrgTypes =
(ClassificationScheme) bqm.getRegistryObject(uuid_types,
LifeCycleManager.CLASSIFICATION_SCHEME);
if (uddiOrgTypes != null) {
Classification classification =
blcm.createClassification(uddiOrgTypes,
"postalAddress", "postalAddress" );
postalScheme.addClassification(classification);
InternationalString ld =
blcm.createInternationalString("My Scheme");
ExternalLink externalLink =
blcm.createExternalLink(
"http://www.mycom.com/myscheme.xml", ld);
postalScheme.addExternalLink(externalLink);
Collection<ClassificationScheme> schemes =
new ArrayList<ClassificationScheme>();
schemes.add(cScheme);
BulkResponse br =
blcm.saveClassificationSchemes(schemes);
}The
BulkResponseobject returned by thesaveClassificationSchemesmethod contains the key for the classification scheme, which you need to retrieve:
if (br.getStatus() == JAXRResponse.STATUS_SUCCESS) {
System.out.println("Saved ClassificationScheme");
Collection schemeKeys = br.getCollection();
Iterator keysIter = schemeKeys.iterator();
while (keysIter.hasNext()) {
Key key = (Key) keysIter.next();
System.out.println("The postalScheme key is " +
key.getId());
System.out.println("Use this key as the scheme" +
" uuid in the taxonomy file");
}
}- In an XML file, define a taxonomy structure that is compliant with the JAXR Predefined Concepts DTD. Enter the
ClassificationSchemeelement in your taxonomy XML file by specifying the returned key ID value as theidattribute and the name as thenameattribute. For the foregoing code fragment, for example, the opening tag for theJAXRClassificationSchemeelement looks something like this (all on one line):
<JAXRClassificationScheme
id="uuid:nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn"
name="MyScheme">The
ClassificationSchemeidmust be a universally unique identifier (UUID).- Enter each
JAXRConceptelement in your taxonomy XML file by specifying the following four attributes, in this order:
idis theJAXRClassificationSchemeidvalue, followed by a/separator, followed by the code of theJAXRConceptelement.nameis the name of theJAXRConceptelement.parentis the immediate parentid(either theClassificationSchemeidor that of the parentJAXRConcept).codeis theJAXRConceptelement code value.The first
JAXRConceptelement in thenaics.xmlfile looks like this (all on one line):
<JAXRConcept
id="uuid:C0B9FE13-179F-413D-8A5B-5004DB8E5BB2/11"
name="Agriculture, Forestry, Fishing and Hunting"
parent="uuid:C0B9FE13-179F-413D-8A5B-5004DB8E5BB2"
code="11"></JAXRConcept>- To add the user-defined taxonomy structure to the JAXR provider, specify the connection property
com.sun.xml.registry.userTaxonomyFilenamesin your client program. You set the property as follows:
props.setProperty
("com.sun.xml.registry.userTaxonomyFilenames",
"c:\mydir\xxx.xml|c:\mydir\xxx2.xml");Use the vertical bar (
|) as a separator if you specify more than one file name.Specifying Postal Addresses
The JAXR specification defines a postal address as a structured interface with attributes for street, city, country, and so on. The UDDI specification, on the other hand, defines a postal address as a free-form collection of address lines, each of which can also be assigned a meaning. To map the JAXR
PostalAddressformat to a known UDDI address format, you specify the UDDI format as aClassificationSchemeobject and then specify the semantic equivalences between the concepts in the UDDI format classification scheme and the comments in the JAXRPostalAddressclassification scheme. The JAXRPostalAddressclassification scheme is provided by the implementation of JAXR in the Application Server.In the JAXR API, a
PostalAddressobject has the fieldsstreetNumber,street,city,state,postalCode, andcountry. In the implementation of JAXR in the Application Server, these are predefined concepts in thejaxrconcepts.xmlfile, within theClassificationSchemenamedPostalAddressAttributes.To specify the mapping between the JAXR postal address format and another format, you set two connection properties:
For example, suppose you want to use a scheme named
MyPostalAddressScheme, which you published to a registry with the UUIDuuid:f7922839-f1f7-9228-c97d-ce0b4594736c.<JAXRClassificationScheme id="uuid:f7922839-f1f7-9228-c97d-ce0b4594736c" name="MyPostalAddressScheme">First, you specify the postal address scheme using the
idvalue from theJAXRClassificationSchemeelement (the UUID). Case does not matter:props.setProperty("javax.xml.registry.postalAddressScheme", "uuid:f7922839-f1f7-9228-c97d-ce0b4594736c");Next, you specify the mapping from the
idof eachJAXRConceptelement in the default JAXR postal address scheme to theidof its counterpart in the scheme you published:props.setProperty("javax.xml.registry.semanticEquivalences", "urn:uuid:PostalAddressAttributes/StreetNumber," + "uuid:f7922839-f1f7-9228-c97d-ce0b4594736c/StreetAddressNumber|" + "urn:uuid:PostalAddressAttributes/Street," + "urn:uuid:f7922839-f1f7-9228-c97d-ce0b4594736c/StreetAddress|" + "urn:uuid:PostalAddressAttributes/City," + "urn:uuid:f7922839-f1f7-9228-c97d-ce0b4594736c/City|" + "urn:uuid:PostalAddressAttributes/State," + "urn:uuid:f7922839-f1f7-9228-c97d-ce0b4594736c/State|" + "urn:uuid:PostalAddressAttributes/PostalCode," + "urn:uuid:f7922839-f1f7-9228-c97d-ce0b4594736c/ZipCode|" + "urn:uuid:PostalAddressAttributes/Country," + "urn:uuid:f7922839-f1f7-9228-c97d-ce0b4594736c/Country");After you create the connection using these properties, you can create a postal address and assign it to the primary contact of the organization before you publish the organization:
String streetNumber = "99"; String street = "Imaginary Ave. Suite 33"; String city = "Imaginary City"; String state = "NY"; String country = "USA"; String postalCode = "00000"; String type = ""; PostalAddress postAddr = blcm.createPostalAddress(streetNumber, street, city, state, country, postalCode, type); Collection<PostalAddress> postalAddresses = new ArrayList<PostalAddress>(); postalAddresses.add(postAddr); primaryContact.setPostalAddresses(postalAddresses);If the postal address scheme and semantic equivalences for the query are the same as those specified for the publication, a JAXR query can then retrieve the postal address using
PostalAddressmethods. To retrieve postal addresses when you do not know what postal address scheme was used to publish them, you can retrieve them as a collection ofSlotobjects. TheJAXRQueryPostal.javasample program shows how to do this.In general, you can create a user-defined postal address taxonomy for any
PostalAddresstModels that use the well-known categorization in theuddi-org:typestaxonomy, which has the tModel UUIDuuid:c1acf26d-9672-4404-9d70-39b756e62ab4with a value ofpostalAddress. You can retrieve the tModeloverviewDoc, which points to the technical detail for the specification of the scheme, where the taxonomy structure definition can be found. (The JAXR equivalent of anoverviewDocis anExternalLink.)