Example JSON Data Provider Using GSON and an XAgent

package com.eric.test;
 
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
import lotus.domino.*;
import com.ibm.xsp.model.domino.DominoUtils;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
 
/**
 * Data provider Class with a single, public, static method
 * to provide an XAgent micro-service, returning formatted
 * data as application/json.
 * 
 * @author Eric McCormick, @edm00se
 * src: http://edm00se.github.io/DevBlog/xpages/custom-JSON-with-Java-sized-XAgent
 * 
 */
public class DataProvider {
	
	/**
	 * This method performs some sample actions against
	 * a Domino View's Documents, reads them into a
	 * JsonArray, attaches it to the JsonObject response
	 * and returns it as a data response via FacesContext.
	 * This should be invoked as part of an XAgent.
	 * 
	 * @return JsonObject sample response
	 * @throws IOException 
	 */
	public static void GetMyDataAsJson() throws IOException{
		//initialize the main JsonObject for the response
		JsonObject myData = new JsonObject();
		/*
		 * Here we're establishing our external context handle,
                 * where we get our response writer from.
		 */
		FacesContext ctx = FacesContext.getCurrentInstance();
		ExternalContext exCon = ctx.getExternalContext();
		/*
		 * Using a response writer is one way of directly dumping into the response.
		 * Instead, I'm returning the JsonObject.
		 */
		ResponseWriter writer = ctx.getResponseWriter();
		HttpServletResponse response = (HttpServletResponse) exCon.getResponse();
		
		//set my content type, use a robust character encoding, and don't cache my response
		response.setContentType("application/json");
		response.setHeader("Cache-Control", "no-cache");
		response.setCharacterEncoding("utf-8");
		try {
			
			/*
			 * This is how we can get a handle on and use any URL parameters
			 * instead of the Domino SSJS param handle. Note that I check
			 * for the existence of the the parameter of myKey before assigning
			 * it, via ternary operator.
			 */
			Map<String,Object> exConP = exCon.getRequestParameterMap();
			String myParam = (exConP.containsKey("myKey")) ? exConP.get("myKey").toString() : null;
			
			/*
			 * Using the Domino Session class, we can get a handle on our current
			 * session and interact with anything via the Java NotesDomino API.
			 */
			Session s = DominoUtils.getCurrentSession();
			Database db = s.getCurrentDatabase();
			View vw = db.getView("GoTCharFlat");
			
			/*
			 * perform any necessary business logic with the data
			 */
			 
			//creating an array of objects
			JsonArray dataAr = new JsonArray();
			
			/*
			 * This is an example only as there are easier ways to 
			 * get a JSON response of a View; e.g.- Domino Data/Access Services.
			 */
			Document first = vw.getFirstDocument();
			//simple View iteration of documents and adding of a given value
			while(first!=null){
				//creates current object
				JsonObject curOb = new JsonObject();
				String name = first.getItemValueString("CharFullName_FL");
				String title = first.getItemValueString("Title");
				curOb.addProperty("name", name);
				curOb.addProperty("title", title);
				//adds current object into JsonArray
				dataAr.add(curOb);
				
				//no OpenNTF Domino API implemented, ham fist away!
				Document tmpDoc = vw.getNextDocument(first);
				first.recycle();
				first = tmpDoc;
			}
			//wrap it up and add the JsonArray of JsonObjects to the main object
			myData.add("data", dataAr);
			
			/*
			 * Business logic done, setting error to false last, so
			 * if anything errors out, we'll catch it.
			 */
			myData.addProperty("error", false);
			
		}catch(Exception e){
			/*
			 * On error, sets a boolean error value of true
			 * and adds the message into the errorMessage
			 * property.
			 */
			myData.addProperty("error", true);
			myData.addProperty("errorMessage", e.toString());
			System.out.println("Error with data provision method:");
			System.out.println(e.toString());
		}
		/*
		 * This will always return a fully formed JsonObject response.
		 * Meaning that if there's an error, we hear about it and can
		 * handle that on the client side for display while developing,
		 * or logging when in production.
		 * 
		 * Note: since we're hijacking the FacesContext response, we're
		 * returning a string (not data object) into the ResponseWriter.
		 * This is why the method is void. Don't worry, it's application/json.
		 */
		writer.write(myData.toString());
	}
	
}





This is a demonstration Java class with single method to generate an application/json data response. It builds from a Notes View and shows how to do so from an XAgent.

Implementation is to include the fully qualified package.class.method() in the afterRenderResponse event of the XPage, with rendering set to false.

This method depends on Google GSON, which can be found at: https://code.google.com/p/google-gson/.

For further explanation, please see my blog post on the subject: http://edm00se.github.io/DevBlog/xpages/custom-JSON-with-Java-sized-XAgent

Java
Eric McCormick
October 22, 2014 10:57 AM
Rating
76

All code submitted to OpenNTF XSnippets, whether submitted as a "Snippet" or in the body of a Comment, is provided under the Apache License Version 2.0. See Terms of Use for full details.



No comments yetLogin first to comment...