In the previous section we noted that we used OSLC4J to transform Plain Old Java Object (POJO) representations of OSLC resources into RDF, XML, and JSON formats. In this section, we’ll look more closely at how OSLC4J defines OSLC resources. Then we’ll make Bugzilla Bugs available as OSLC Change Management resources in a variety of formats.
What is OSLC4J?
OSLC4J, part of the Eclipse Lyo project, is a Java SDK for developing OSLC provider or consumer implementations. OSLC resources can be modeled with plain old Java objects (POJOs) which are annotated to provide the information OSLC4J needs to create resource shapes, service provider documents, and to serialize/de-serialize OSLC resources from Java to representations such as RDF or JSON.
Defining OSLC resources with OSLC4J
OSLC4J comes with a sample Change Management application that includes the OSLC4J-annotated Java class representing a Change Request (as defined in the OSLC Change Management v2 specification).
The OSLC4J Bugzilla adapter includes that class (ChangeRequest) and extends it with Bugzilla-specific attributes (for example, “Product”, “Platform”, or other attributes that are not part of the OSLC CM specification); this extended change request is called a BugzillaChangeRequest.
Exploring the OSLC4J ChangeRequest class
Open the file ChangeRequest.java
in the org.eclipse.lyo.oslc4j.bugzilla.resources package and explore the variables and methods. For reference, here is the definition of a Change Request in the OSLC Change Management specification.
First, observe the private variables at the top of the ChangeRequest class. These are the attributes of an OSLC CM V2.0 Change Request. Here are first several, which represent the relationships between Change Requests and other OSLC artifacts:
private final Set<Link> affectedByDefects = new HashSet<Link>();
private final Set<Link> affectsPlanItems = new HashSet<Link>();
private final Set<Link> affectsRequirements = new HashSet<Link>();
private final Set<Link> affectsTestResults = new HashSet<Link>();
private final Set<Link> blocksTestExecutionRecords = new HashSet<Link>();
Further down are the primitive attributes of a Change Request:
private Boolean approved;
private Boolean closed;
private Date closeDate;
private Date created;
private String description;
Further down, each attribute has an associated getter method. For example, here’s the getIdentifier()
method:
@OslcDescription("A unique identifier for a resource. Assigned by the service provider when a resource is created. Not intended for end-user display.")
@OslcOccurs(Occurs.ExactlyOne)
@OslcPropertyDefinition(OslcConstants.DCTERMS_NAMESPACE + "identifier")
@OslcReadOnly
@OslcTitle("Identifier")
public String getIdentifier()
{
return identifier;
}
Note the OSLC-specific annotations before the method. These are used to not only automatically create OSLC resource shape documents, service provider documents, and service provider catalogs, but also assist with the serialization of Java objects to RDF or JSON:
-
@OslcOccurs
provides the cardinality of the attribute. -
@OslcPropertyDefinition
providers the namespace qualified attribute name -
@OslcReadOnly
indicates this attribute should appear in the resource shape as read only
Because the default type in OSLC4J is a string, there is no type annotation. Look for other attributes with the @OslcValueType
annotation for examples of attributes that are not strings.
Extending ChangeRequest with Bugzilla attributes
Open the file BugzillaChangeRequest.java
in the org.eclipse.lyo.oslc4j.bugzilla.resources package and explore the variables and methods for the Bugzilla-specific attributes.
As with the ChangeRequest class, the various getter methods (for example, getVersion()
) have OSLC annotations.
Mapping Bugzilla attributes to OSLC-CM properties
To represent a Bugzilla bug as an RDF/XML document for an OSLC Change Management resource, we must map Bugzilla bug attributes to OSLC-CM ChangeRequest properties. The following attributes line up fairly clearly:
Bugzilla Bug field | Maps to RDF predicate | Prefixed name* |
---|---|---|
id | http://purl.org/dc/terms/identifier | dcterms:identifier |
summary | http://purl.org/dc/terms/title | dcterms:title |
status | http://open-services.net//ns/cm#status | oslc_cm:status |
assigned_to | http://purl.org/dc/terms/contributor | dcterms:contributor |
creation_time | http://purl.org/dc/terms/created | dcterms:created |
last_change_time | http://purl.org/dc/terms/modified | dcterms:modified |
(* Prefix may be different depending on namespace prefix declaration in the XML)
In the BugzillaChangeRequest class, the fromBug()
method sets these properties. Near the top of the method, here is the code that sets the properties dcterms:identifier
, dcterms:title
, and oslc_cm:status
properties from (respectively) the ID, Summary, and Status of the Bugzilla bug:
BugzillaChangeRequest changeRequest = new BugzillaChangeRequest();
changeRequest.setIdentifier(bug.getID());
changeRequest.setTitle(bug.getSummary());
changeRequest.setStatus(bug.getStatus());
Bugzilla bugs also have attributes that do not map to any OSLC Change Management properties but that are required for Bugzilla. We should make these available in our RDF/XML representations by using the RDF predicates that Bugzilla defines for Bug lists, and we’ll use the unique namespace bugz
as a prefix (defined in Constants.java
as shorthand for http://www.bugzilla.org/rdf#):
Bugzilla Bug field | Maps to RDF predicate | Prefixed name* |
---|---|---|
product | http://www.bugzilla.org/rdf#product | bugz:product |
component | http://www.bugzilla.org/rdf#component | bugz:component |
version | http://www.bugzilla.org/rdf#version | bugz:version |
priority | http://www.bugzilla.org/rdf#priority | bugz:priority |
platform | http://www.bugzilla.org/rdf#platform | bugz:platform |
op_sys | http://www.bugzilla.org/rdf#op_sys | bugz:operatingSystem |
(* Prefix may be different depending on namespace prefix declaration in the XML)
We set these properties in the fromBug()
method in the BugzillaChangeRequest class. Here’s the code that sets bugz:product
and bugz:component
:
changeRequest.setProduct(bug.getProduct());
changeRequest.setComponent(bug.getComponent());
You can explore the fromBug()
method to see how the other properties are set.
Providing OSLC representations of Bugzilla bugs
Like with the ServiceProviderService and ServiceProviderCatalogService (discussed in in more detail in the previous section), the BugzillaChangeRequestService class has many JAX-RS methods to handle both collections of BugzillaChangeRequests and individual BugzillaChangeRequests with a a variety of HTTP requests and output formats.
Open BugzillaChangeRequestService.java
in the org.eclipse.lyo.oslc4j.bugzilla.services package.
Note the @Path
annotation near the top of the class:
@Path("{productId}/changeRequests")
Recall that in ServiceProviderCatalogSingleton.java
we registered a Service Provider for every Bugzilla product and used the product ID of the product in the URL for the Service Provider. So if the ID of a Bugzilla product is 2, our base URL for the BugzillaChangeRequestService methods will be:
http://hostname:8080/OSLC4JBugzilla/services/2/changeRequests
Providing representations of Bugzilla Bugs as RDF+XML or JSON
As with Service Providers and the Service Provider Catalog, with OSLC4J we do not have to write manually code the RDF or JSON representation of a bug; the message body writers in OSLC4J automatically serialize the Java object into the appropriate machine-readable format.
The output is handled by the following methods in the BugzillaChangeRequestService class:
-
getChangeRequests()
: RDF/XML, XML and JSON representation of a change request collection -
getChangeRequest()
: RDF/XML, XML, and JSON representation of a single change request
Without OSLC4J you could dispatch a JSP template, use an RDF API, or use an XML DOM API to generate the appropriate output format.
Viewing the RDF+XML or JSON representation of a collection of Bugzilla bugs
The following assumes the Bugzilla adapter is running at localhost:8080/OSLC4JBugzilla
In Firefox or Chrome, open the Poster plugin.
for the URL field, type the URL for a list of all the bugs for a product:
http://localhost:8080/OSLC4JBugzilla/services/{productId}/changeRequests
For example, with a product ID of 1:
http://localhost:8080/OSLC4JBugzilla/services/1/changeRequests
For the User Auth fields, type your Bugzilla username and password.
On the Headers tab, for the Name type Accept
and for the Value type any of the following:
-
application/rdf+xml
-
application/json
-
application/xml
Then, click Add/Change to add the Accept
header.
Click Get to execute the HTTP GET method and you should receive the collection of bugs in the format you requested via Accept
header. OSLC4J and JAX-RS produce the correct serialization based on the Accept
header.
Viewing the RDF+XML or JSON representation of a Bugzilla bug
Follow the procedure above for a collection of bugs, but for the URL field, type the URL for a single bug:
http://localhost:8080/OSLC4JBugzilla/services/{productId}/changeRequests/{bugId}
For example, with a Product ID of 1 and a Bug ID of 10:
http://localhost:8080/OSLC4JBugzilla/services/1/changeRequests/10
Click Get and you should receive the bug in the format you requested via Accept
header.
Displaying a collection of Bugzilla bugs as HTML
OSLC4J can simplify providing collections of bugs in machine-readable formats, but we should also provide a more human-friendly HTML listing of Bugzilla bugs.
In BugzillaChangeRequestService.java
in the org.eclipse.lyo.oslc4j.bugzilla.services package find the getHtmlCollection()
method.
@GET
@Produces({ MediaType.TEXT_HTML })
public Response getHtmlCollection( @PathParam("productId") final String productId, […] ) throws ServletException, IOException
{
/* [code for returning a list of bugs with HTML] */
}
This method’s basic activity is to retrieve a list of bugs for a Bugzilla product…
final List<BugzillaChangeRequest> results =
BugzillaManager.getBugsByProduct(
httpServletRequest,
productId,
page,
limit,
where,
prefixMap,
propMap,
orderBy,
searchTerms);
… and dispatch that list to a template (/cm/changerequest_collection_html.jsp
):
httpServletRequest.setAttribute("results", results);
/**
* …
*/
RequestDispatcher rd = httpServletRequest.getRequestDispatcher(
"/cm/changerequest_collection_html.jsp"
);
rd.forward(httpServletRequest,httpServletResponse);
There are multiple parameters for this function that allow you to filter the collection with queries, paginate the results, and change the sort order. The Bugzilla Adapter does not use all of these parameters; however they are necessary for full support of OSLC Queries.
Open the file /src/webapp/cm/changerequest_collection_html.jsp
in OSLC4JBugzilla. The HTML layout is nearly identical to that of the Service Providers and Catalog.
Towards the top, you’ll see that we receive the data:
<%
List<BugzillaChangeRequest> changeRequests = (List<BugzillaChangeRequest>) request.getAttribute("results");
ServiceProvider serviceProvider = (ServiceProvider) request.getAttribute("serviceProvider");
String bugzillaUri = (String) request.getAttribute("bugzillaUri");
String queryUri = (String)request.getAttribute("queryUri");
String nextPageUri = (String)request.getAttribute("nextPageUri");
%>
And towards the bottom of the file, we loop through the list of bugs and output the title/summary and a link as HTML:
<h1>Query Results</h1>
<% for (BugzillaChangeRequest changeRequest : changeRequests) { %>
<p>Summary: <%= changeRequest.getTitle() %><br /><a href="<%= changeRequest.getAbout() %>">
<%= changeRequest.getAbout() %></a></p>
<% } %>
Browsing all the bugs for a Bugzilla Product
Let’s try it out! From the Service Provider Catalog, you can navigate to a list of all bugs for a product.
- If you’re running the example applications, browse to http://localhost:8080/OSLC4JBugzilla/services/catalog/singleton.
- Click on the link for any Service Provider for a product (for example, if the product ID is “1”: http://localhost:8080/OSLC4JBugzilla/services/serviceProviders/1.
- Then click on the first link under the OSLC-CM Resource Query Capability and Resource Shape heading. For example, if the product ID is “1”: http://localhost:8080/OSLC4JBugzilla/services/1/changeRequests
You should see a page with links to the bugs, similar to this:
Forwarding HTML requests for single Bugzilla bugs
The Bugzilla application itself can create an HTML page with all the details about a bug – that’s one of its primary features – so why recreate the wheel?
In the BugzillaChangeRequestService class, note the getHtmlChangeRequest()
method:
@GET
@Path("{changeRequestId}")
@Produces({ MediaType.TEXT_HTML })
public Response getHtmlChangeRequest(@PathParam("productId") final String productId,
@PathParam("changeRequestId") final String changeRequestId) throws ServletException, IOException, URISyntaxException
{
String forwardUri = BugzillaManager.getBugzillaUri() + "show_bug.cgi?id=" + changeRequestId;
httpServletResponse.sendRedirect(forwardUri);
return Response.seeOther(new URI(forwardUri)).build();
}
Simple enough: given the ID number ({changeRequestId}
) for a particular bug, the OSLC Bugzilla adapter will forward you directly to the web page for the bug in Bugzilla (show_bug.cgi?id={changeRequestId}
). For example, a request from the adapter for bug 531 in Product 1 at the following URL…
http://localhost:8080/OSLC4JBugzilla/services/1/changeRequests/531
… will forward you to the Bugzilla page for the bug at this URL:
https://bugzilla-host.example.com/show_bug.cgi?id=531
That’s useful on its own, but OSLC also specifies a method called UI Preview for showing preview information about a resource in another tool. We’ll tackle these rich preview formats in the next section.