At the heart of many of our technology solutions is integration. How do we connect this web application to our accounting software to keep track of sales? How can I use my existing content to help build a mobile application? How do I create an application that brings together information in many systems in a single, unified way?
These problems are part of building any large system; there are no self-contained software applications.
In our recent work with a large client we created an application using PHP that leveraged all the following systems:
- LDAP – Corporate directory
- OpenAM – Single-sign on solution, used for authentication and access control
- Google Search Appliance – Basic document and people searching
- XMPP – Chat server used for chat and presence detection
This was an enterprise system that had to leverage a lot of important resources and pull them together into a coherent whole.
PHP generally runs as part of a LAMP stack, and many frameworks, including Laravel, expect the presence of a relational database. Due to client infrastructure, using a database to store any information was not part of the product launch.
We wrote an LDAP service class, handling communication between our application and the client’s LDAP server. This class had to handle all contact configuration and queries between the servers. We constructed custom objects to act as transforming agents for the data to be used by our controllers and views.
One big challenge was pagination of our search functions. Where pagination is relatively simple with a relational database and built in to most frameworks (including Laravel), in this case we had to create our own. This involved careful session coordination to retain state between consecutive posts.
Authentication is an extremely important and well-handled function built in to most PHP frameworks. The solution developed for this client allowed for routes to require authentication filters before rendering pages, which is a common use case for sites with secured content.
However, because we could not keep information server-side this became a challenge. We used a form for credential entry and this had to post to the client’s OpenAM server. Once authentication was granted, we had to keep the user’s logged-in status based on his/her company ID (which had to be retrieved via the LDAP functionality described earlier). Since there were many reasons for login failure (bad credentials, server inaccessibility, etc.) coordination of status codes between the servers became a priority for accurate and meaningful messaging on our application side to the user.
Google Search Appliance
The Search Appliance results were also transformed locally into search objects. While some of the challenges we ran into with LDAP were more easily addressed here (for example, the appliance searches were indexed, making pagination simple), the complexity of searches were limited. While looking for a document with a certain title or even containing certain text was fairly simple, the challenge was how to access some of the more custom elements such as how to search for a manager of employee X, or an employee with a nickname of Junior. In the end, our custom LDAP queries were preferable for some of these use cases.
Chat was very challenging, but an important need for the application from client’s viewpoint. When testing, we found many unexpected side-effects. For example, chat had different behavior internally to client network than when trying to contact from outside of their network. In addition, there was different behavior when running the chat on a VM, compared to running on the host machine. This involved extensive testing with the client, and configuration on the client side servers to handle the incoming IM traffic appropriately.
The use of VPN as an integral aspect of development presented some interesting challenges. We were not integrating with it in the code, but it was a core part of our development processes that we needed to make the project a success and it presented some interesting challenges. Our application had no access the client’s resources without a VPN connection.
This had some unforeseen side-effects. For example, as the VPN would not run inside of our VM’s, the VM would have to use the host VPN connection, requiring us to change the network connection on the VM.
Normally we would run our milestone and sprint testing on our test server, but that server could not maintain a VPN connection, so one of our VMs was designated as a test site, and had to have a static IP. It also became a challenge client-side to coordinate access and authentication for our local users on all client servers involved in the application functionality.