3

I have written a custom rest Service on an Xpage, which is tied to a bean. The Xpage is:

<xe:restService
    id="restServiceCustom"
    pathInfo="custom"
    ignoreRequestParams="false"
    state="false"
    preventDojoStore="true">
    <xe:this.service>
        <xe:customRestService
            contentType="application/json"
            serviceBean="XXXX.PCServiceBean">
        </xe:customRestService>
    </xe:this.service>
</xe:restService>

I cobbled together my java agent from some excellent posts around the net. I have just started on the GET. My code runs but I it seems pretty slow (on my dev server). I want to make it as fast as possible. I am using a ViewEntryCollection and I am "flushing" at each record which I assume is streaming.

I am putting my own "[" in the code, so I assume that I am not doing something right, as I never saw any examples of anyone else doing this.

Any suggestions would be greatly appreciated.

package com.XXXXX.bean;

import java.io.IOException;
import java.io.Writer;
import java.util.Vector;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.openntf.domino.Database;
import org.openntf.domino.Session;
import org.openntf.domino.View;
import org.openntf.domino.ViewEntry;
import org.openntf.domino.ViewEntryCollection;
import org.openntf.domino.utils.Factory;

import com.ibm.commons.util.io.json.JsonException;
import com.ibm.commons.util.io.json.util.JsonWriter;
import com.ibm.domino.services.ServiceException;
import com.ibm.domino.services.rest.RestServiceEngine;
import com.ibm.xsp.extlib.component.rest.CustomService;
import com.ibm.xsp.extlib.component.rest.CustomServiceBean;

public class PCServiceBean extends CustomServiceBean {

    @Override
    public void renderService(CustomService service, RestServiceEngine engine) throws ServiceException {
        try {
            HttpServletRequest request = engine.getHttpRequest();
            HttpServletResponse response = engine.getHttpResponse();

            response.setHeader("Content-Type", "application/json; charset=UTF-8");

            String method = request.getMethod();
            if (method.equals("GET")) {
                this.doGet(request, response);
            } else if (method.equals("POST")) {
                this.doPost(request, response);
            } else if (method.equals("PUT")) {
                this.doPut(request, response);
            } else if (method.equals("DELETE")) {
                this.doDelete(request, response);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    private void doDelete(HttpServletRequest request, HttpServletResponse response) {
        // TODO Auto-generated method stub

    }

    private void doPut(HttpServletRequest request, HttpServletResponse response) {
        // TODO Auto-generated method stub

    }

    private void doPost(HttpServletRequest request, HttpServletResponse response) {
        // TODO Auto-generated method stub

    }

    private void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, JsonException {

        Session session = Factory.getSession();
        Database DB = session.getDatabase(session.getCurrentDatabase().getServer(), "scoApps\\PC\\PCData.nsf");
        View pcView = DB.getView("viewAllByStatus");

        int i = 1;

        Writer out = response.getWriter();
        JsonWriter writer = new JsonWriter(out, false);

        writer.out("[");

        ViewEntryCollection vec = pcView.getAllEntries();
        int count = vec.getCount();

        for (ViewEntry entry : vec) {

            Vector<?> columnValues = entry.getColumnValues();

            writer.startObject();

            writer.startProperty("unid");
            writer.outStringLiteral(String.valueOf(columnValues.get(1)));
            writer.endProperty();

            writer.startProperty("status");
            writer.outStringLiteral(String.valueOf(columnValues.get(0)));
            writer.endProperty();

            writer.startProperty("assetTag");
            writer.outStringLiteral(String.valueOf(columnValues.get(2)));
            writer.endProperty();

            writer.startProperty("serialNumber");
            writer.outStringLiteral(String.valueOf(columnValues.get(3)));
            writer.endProperty();

            writer.startProperty("model");
            writer.outStringLiteral(String.valueOf(columnValues.get(4)));
            writer.endProperty();

            writer.startProperty("currentLocation");
            writer.outStringLiteral(String.valueOf(columnValues.get(5)));
            writer.endProperty();


            writer.endObject();

            if (i != count) {
                i = i + 1;
                writer.out(",");
                writer.flush();
            }

        }
        writer.out("]");
        writer.flush();
    }
}
Eric McCormick
  • 2,716
  • 2
  • 19
  • 37
Bryan Schmiedeler
  • 2,977
  • 6
  • 35
  • 74
  • Knut's answer is pretty spot on. You could also remove any unused methods (e.g.- requests other than `GET`), depending on your needs. You should also provide for "unhandled requests" if you're looking to be more compatible with other services to consume. Hit me up if you have any questions. – Eric McCormick Oct 25 '16 at 18:36

2 Answers2

6

Change your code to

    JsonWriter writer = new JsonWriter(out, false);

    writer.startArray();

    ViewEntryCollection vec = pcView.getAllEntries();
    int count = vec.getCount();

    for (ViewEntry entry : vec) {

        Vector<?> columnValues = entry.getColumnValues();

        writer.startArrayItem();
        writer.startObject();

        writer.startProperty("unid");
        writer.outStringLiteral(String.valueOf(columnValues.get(1)));
        writer.endProperty();

        ...

        writer.endObject();
        writer.endArrayItem();
    }
    writer.endArray();
    writer.flush();

It uses JsonWriter's

  • startArray() and endArray() instead of out("[") and out("]")
  • startArrayItem() and endArrayItem() instead of out(",") and flush()

The JSON response string gets shorter if you set JsonWriter's compact option to true:

JsonWriter writer = new JsonWriter(out, true);
Knut Herrmann
  • 30,880
  • 4
  • 31
  • 67
3

I see two problems.

First - use ViewNavigator. Here's good explanation of its performance gain.

https://www.mindoo.com/web/blog.nsf/dx/17.01.2013085308KLEB9S.htm

Second - prepare your JSON in advance. This is very good technique to avoid unnecessary code (and time to process it) to get JSON data from Domino documents.

https://quintessens.wordpress.com/2015/09/05/working-with-json-in-your-xpages-application/

Frantisek Kossuth
  • 3,524
  • 2
  • 23
  • 42