Wednesday, September 29, 2010

Mashing up Google Map with realtime BART schedules

Here is the website that I created that mashes Google Maps with BART schedules.
Click on a station on the map and see the arrival time of the next trains leaving from that station.

http://pluralconcepts.com/nextBart

The technologies used:

Google Map API - surprisingly easy to learn and use
Yahoo Query Language (YQL) - very nice tool that lets you perform SQL-like queries on XML
JQuery - my swiss army knife for all things UI-related

Monday, July 12, 2010

Paginating SOAP Response Data

Paginating Records Returned By SOAP-based Web Services

Whenever you invoke a web service to retrieve a list of records, the returned list may be long and contain more records than you would want to display. What is called for is usually a pagination mechanism to control which chunk of the returned records to display.

Many front-end UI components such as Data Grids and Pagination controls exist to allow the user to page forwards, backwards or jump to specific pages within a long list. Server-side support for pagination however is not as prevalent and often painstaking to implement, especially in the context of XML records returned by a web service.

The following is a server-side pagination framework for SOAP responses, built in Java.
The framework transforms a SOAP response into a paged-list of records and returns a requested page to the client. For example, if we have a SOAP response which returns a list of employee records such as:

<Soap:Envelope>
<Soap:Body>
<GetEmployeeResponse xmlns="http://www.aWebService.com/services">
<employees>
<employee>
<employeeid>1234</employeeid>
<name>John Smith</name>
</employee>
<employee>
<employeeid>1235</employeeid>
<name>Joe Turner</name>
</employee>
....
<employee>
<employeeid>1250</employeeid>
<name>Kim Jones</name>
</employee>
</employees>
</GetEmployeeResponse>
</Soap:Body>
</Soap:Envelope>

Let's say that 250 employee records are returned in the above SOAP response.
When the response is submitted to the pagination framework with a specified page size of 10 and page number of 1, the following is returned by the framework:

<PaginatorResult>
<PageNumber>1</PageNumber>
<PageSize>10</PageSize>
<RecordsReturned>10</RecordsReturned>
<TotalRecords>250</TotalRecords>
<TotalPages>25</TotalPages>
<employees>
<employee>
<employeeid>1234</employeeid>
<name>John Smith</name>
</employee>
<employee>
<employeeid>1235</employeeid>
<name>Joe Turner</name>
</employee>
....
<employee>
<employeeid>1244</employeeid>
<name>Jim Howard</name>
</employee>
</employees>
</PaginatorResult>

The result returned is in an easily-consumable format by UI components.


Using the SOAP Response Pagination framework

The framework is simple to use. It consists of one class, SoapResponsePaginator and one method, paginate.

public class SoapResponsePaginator {

public String paginate (String soapResponse, String namespace, String xpathExpression,
int pageNumber, pageSize) {
.......
}
}

The paginate method takes 5 parameters:
  • soapResponse - returned by the web service
  • namespace - the namespace of the web service
  • xpathExpression - the XPath for extracting the data record from the soapResponse
  • pageNumber - the page number
  • pageSize - the number of records per page

In the example above, you make the following calls:

String soapResponse = ..... // Invoke the web service using JAXP, Axis or a SOAP toolkit
SoapResponsePaginator paginator = new SOAPResponsePaginator();
String paginatedResult = paginator.paginate(soapResponse, "http://www.aWebService.com/services",
"//employees/employee", 1, 10);


Thursday, June 17, 2010

Integrating a portal with CAS and LDAP

I hope this blog sheds some light for those who are trying to understand how a portal might integrate with a single sign on solution, such as, in this case, CAS (http://www.jasig.org/cas) and LDAP (http://directory.apache.org). The following diagram outlines the architecture and the event flows.

The flow arrows are numbered and annotated below.
These are the URLs used for illustration purposes:

Portal: http://localhost/portal
CAS: https://localhost:8443/cas
External Application: http://externalApp1

I have included just one external application in the scenario below just to keep things simple. In reality, portal would be talking to multiple external applications (for each app, flows 8 - 13 are repeated).




  1. The user accesses the portal at for example, http://localhost/portal
  2. The Web Browser is redirected to the CAS server at: https://localhost:8443/cas/login
  3. CAS obtains the userID/password from the user via a login form and authenticates with LDAP.
  4. If authentication passes, CAS appends a login ticket to the URL like so: http://localhost/portal?ticket=xxx
  5. The browser is redirected to http://localhost/portal?ticket=xxx
  6. The portal validates the login ticket with CAS by doing a GET on https://localhost:8443/cas/serviceValidate?ticket=xxx&service=http://localhost/portal&pgtUrl=https://localhost/portal/proxyTicketReceptor
  7. On successful validation, CAS sends back the user ID and a ticket granting ticket called a PGTIOU.
  8. Using the PGTIOU, the portal requests a proxy ticket from CAS for the External App using the URL: https://localhost:8443/cas/proxy?pgt=[PGTIOU]&service=http://externalApp1
  9. CAS creates a proxy ticket and returns it to the portal.
  10. The portal appends the proxy ticket to the URL of the External App, for example: http://ExternalApp/ticket=[proxy ticket]
  11. The External App validates the proxy ticket with CAS using the URL: https://localhost:8443/cas/proxyValidate?ticket=[proxy ticket]&service=http://externalApp1
  12. If validation passes, CAS returns the user ID to the External App.
  13. The user is now logged into the External App which returns the page to the portal.
  14. The portal renders the final page and returns it to the browser.