Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

basic REST service for my xpage application

Tags:

java

rest

xpages

I want to set up some basic REST services for my XPage application. So I added the xe:restService control on an xpage and choose the xe:customRestService where I refer to a Java class:

<xe:restService id="restService1" pathInfo="json" state="false">
        <xe:this.service>
            <xe:customRestService contentType="application/json"
                serviceBean="se.banking.desk.CustomSearchHelper">
            </xe:customRestService>
        </xe:this.service>
    </xe:restService>

The CustomSearchHelper class it self is still pretty empty but I am wondering if I am on the right track?

Here is the code for the class:

package se.banking.desk;

import java.io.IOException;
import java.util.Map;

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

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 CustomSearchHelper extends CustomServiceBean {

    @Override
    public void renderService(CustomService service, RestServiceEngine engine) throws ServiceException {

        HttpServletRequest request = engine.getHttpRequest();           
        String method = request.getMethod();

        HttpServletResponse response = engine.getHttpResponse();        
        response.setHeader("Content-Type", "text/javascript; charset=UTF-8");        

        if(method.equals("GET")){
            this.get(engine);
        }
        else if(method.equals("POST")){
            this.post(engine,request);
        }
        else{
            this.other(engine);
        }

    }

    public void get(RestServiceEngine engine){
        HttpServletResponse response = engine.getHttpResponse();
        try {
            response.getWriter().write("get()");
            response.getWriter().close();
            return;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void post(RestServiceEngine engine,HttpServletRequest request){
      HttpServletResponse response = engine.getHttpResponse();
      Map parameters = request.getParameterMap();
      try {
          response.getWriter().write("post()");
          response.getWriter().write( request.getParameter("form"));
          String[] form = (String[])parameters.get("form");
          String val = form[0];
          response.getWriter().write(val);
        response.getWriter().close();
    } catch (Exception e) {
        // TODO: handle exception
    }     

  }

    public void other(RestServiceEngine engine){
       HttpServletResponse response = engine.getHttpResponse();
        try {
            response.getWriter().write("other()");
            response.getWriter().close();
            return;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

Questions I have: Is this a good way to write a custom REST service? Are there alternatives? Where can I find more examples/information that start at the starter level?

like image 487
Malin Avatar asked Mar 17 '16 13:03

Malin


People also ask

How to use XPages controls for rest?

way of using the XPages controls for REST. There are also two other ways Data Service and creating a custom servlet). Database Collection Service (xe:databaseCollectionJsonService): read database list on the server View Collection ervice (xe:viewCollectionJsonService): read list of views and folders in a database

What is the purpose of this XPage?

The purpose of this XPage is to store some basic configuration information that is used when creating View Definitions. Rest Service Path – this is the path (<dir>/<database.nsf>) where you will create rest services to retrieve data. If you leave it blank then the control will look in the current database to find rest services.

What is the best way to consume XPages data?

REST services and JSON have become more and more popular. Providing REST/JSON services opens up new capabilities to consume XPages application functionality in other types of applications. Additionally existing Dojo UI controls can be used and data can easily be bound to them.

What is a REST web service?

REST stands for REpresentational State Transfer. REST Web services have really come a long way since its inception. In 2002, the Web consortium had released the definition of WSDL and SOAP web services. This formed the standard of how web services are implemented.


Video Answer


2 Answers

You've asked a rather complex question, one which has been on my mind for the last couple of years. My assessment is that finding the "good way" comes down to the developer(s) and conventions used within the app. I've included links to sources of the alternatives I see available, a few mine, those of which attempted to tackle some of the concepts from the ground up, like my series on http servlets.

[Update]I've edited this answer to include some code examples, as there is always the possibility of links eventually not working; which should preserve the intent of the answer.[/Update]

Your implementation is a great example of how the xe:restService control can be easily bound to an XPage, with the wide variety of options available to use within the XPages runtime and Domino server.

So far as I can tell, there are about 5 unique(-ish) ways of implementing a RESTful API/endpoint for operation within an XPages context. In general order of ease of implementation (depending on the person):

  1. XAgent (this could be swapped with the next one; benefits in being easy to start with, lots of examples available, and less daunting to those not experienced with Java, can be done in SSJS or Java)
<?xml version="1.0" encoding="UTF-8"?>
<xp:view
    xmlns:xp="http://www.ibm.com/xsp/core"
    rendered="false"
    viewState="nostate">
    <xp:this.afterRenderResponse>
        <![CDATA[#{javascript:com.demo.DataProvider.myCustomDataServiceAsJson();}]]>
    </xp:this.afterRenderResponse>

    XAgent. This will not render as a page, but as application/json data.
</xp:view>
  1. the best part about the xe:restService is the out-of-the-box options for things like xe:viewJsonService (Domino devs already think in terms of Views and Documents, which are somewhat analogous to a RESTful API's mechanics of collections and records), as Mark pointed out in the comments; these are rather easy to get into and convenient (many people have blogged about these, Brad has covered some of these rather extensively in his data grids series) available options, complete with pretty picker
  2. xe:restService, either as a CustomServiceBean as you've shown above 👍 or as another flavor of xe:customRestService with its xe:this.doGet, etc. methods (which can be done by invoking a class's method or by SSJS; I recommend the former)
<?xml version="1.0" encoding="UTF-8"?>
<xp:view
    xmlns:xp="http://www.ibm.com/xsp/core"
    xmlns:xe="http://www.ibm.com/xsp/coreex">
    <xe:restService
        id="restService1"
        pathInfo="beers">
        <xe:this.service>
            <xe:customRestService
                contentType="application/json"
                requestContentType="application/json">
                <xe:this.doGet><![CDATA[${javascript:var resp = {
    "data": [
        { "key": "value" }
    ],
    "error": false
};
return toJson(resp);}]]></xe:this.doGet>
            </xe:customRestService>
        </xe:this.service>
    </xe:restService>
</xp:view>
  1. implementing a DesignerFacesServlet, which has some requirements (benefits from many of the non-Domino/XPages specific industry conventions, doesn't require knowledge/experience/ability to deploy an OSGi plugin, keeps your application code contained within the NSF container); a demo app I wrote follows this implementation, a modified version (in that repo's current bluemix branch) can be seen running on Bluemix; the sample here follows Jesse's blog post
public class SampleServlet extends DesignerFacesServlet implements Serializable {
    private static final long serialVersionUID = 1L;

    @SuppressWarnings("unchecked")
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        // Set up handy environment variables
        HttpServletRequest req = (HttpServletRequest)servletRequest;
        HttpServletResponse res = (HttpServletResponse)servletResponse;
        ServletOutputStream out = res.getOutputStream();
        FacesContext facesContext = this.getFacesContext(req, res);

        try {
            res.setContentType("text/plain");

            // write some amazing code!

            out.println("done");

        } catch(Exception e) {
            e.printStackTrace(new PrintStream(out));
        } finally {
            out.close();

            // It shouldn't be null if things are going well, but a check never hurt
            if(facesContext != null) {
                facesContext.responseComplete();
                facesContext.release();
            }
        }
    }
}
  1. creating "true" JEE styled OSGi plugin that drives HttpServlets, can use things like JAX-RS to speed things up (has none of the fiddling with getting the Class Loader like with DesignerFacesServlets inside an NSF, just to get it to play nice with your NSF contained Code, but the hurdle of achieving OSGi plugin development, which has been covered nicely by multiple excellent developers)

As for what is a "good way", I think they all have their use, especially when factoring in the concerning developer's skill level. For those looking to get started with such a thing in an XPages app, I recommend what you're doing, an xe:restService with either a CustomServiceBean extending class, or a simple class or bean which has its one-off methods

[Update]

Shean P. McManus and I gave a session for the ICONUS (fka- IamLug) two day virtual event on "Normalizing XPages Development". Much of the subject of what options are available when creating a RESTful API for use with an XPages application were covered. Slides are available both from Shean's blog and the git project repository on GitHub; the latter contains the application code, as well as a pre-built, stand alone NSF.

[/Update]

like image 103
Eric McCormick Avatar answered Oct 21 '22 03:10

Eric McCormick


As Eric pointed out there a different ways how to implement a REST service in XPages. Here is the link to my presentation about REST services from IBM Connect 2016. http://www.assono.de/blog/d6plinks/ibmconnect2016-ad1238

The presentation covers all the different ways except the OSGi plugin because this technique was a little bit heavy for a 1 hour session.

In the sample database all other ways are used. Just download the sample and open it in the Notes client. There is a welcome page to guide you to the code and the samples.

You are already on a good way.

like image 2
Bernd Hort Avatar answered Oct 21 '22 02:10

Bernd Hort