Trace:
Differences
This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
|
jvx:communication:rest_customservice [2022/11/17 11:16] admin created |
jvx:communication:rest_customservice [2022/11/22 10:06] (current) admin |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ~~NOTRANS~~ | ~~NOTRANS~~ | ||
| ~~Title: Custom REST service registration~~ | ~~Title: Custom REST service registration~~ | ||
| - | JVx already has REST services. | + | |
| + | JVx already has [[jvx:common:util:rest|REST services]] for action calls, data access an administration. Sometimes it's necessary to offer custom REST services for an application. Sure, you could create a simple action in your application and an action can be called with standard REST services, but this requires application authentication. If you have a different use-case for your REST service it's also possible to create your own REST service without using different libraries. | ||
| + | |||
| + | The easiest solution is to create a service class which is a servlet context listener. Why a listener? because we need an entry point to register our custom service. If you don't prefer a listener, it would also be possible to create a [[jvx:common:setup:plugins|server plugin]] for JVx' server. But in this article, we use a servlet context listener. | ||
| + | |||
| + | Our class looks like: | ||
| + | |||
| + | <file java> | ||
| + | package com.sibvisions.jvx; | ||
| + | |||
| + | import java.util.List; | ||
| + | import java.util.Map; | ||
| + | |||
| + | import javax.servlet.ServletContextEvent; | ||
| + | import javax.servlet.ServletContextListener; | ||
| + | |||
| + | import com.sibvisions.rad.server.config.Configuration; | ||
| + | import com.sibvisions.rad.server.config.Configuration.ApplicationListOption; | ||
| + | import com.sibvisions.rad.server.http.rest.service.AbstractCustomService; | ||
| + | import com.sibvisions.rad.server.http.rest.service.ICustomServiceGetDelegate; | ||
| + | import com.sibvisions.rad.server.http.rest.service.ICustomServicePostDelegate; | ||
| + | import com.sibvisions.rad.server.http.rest.service.UserService; | ||
| + | import com.sibvisions.util.OrderedHashtable; | ||
| + | |||
| + | @WebListener | ||
| + | public class CustomRESTServices implements ServletContextListener, | ||
| + | ICustomServiceGetDelegate, | ||
| + | ICustomServicePostDelegate | ||
| + | { | ||
| + | /** the health check command. */ | ||
| + | private static final String CMD_HEALTHCHECK = "healthCheck"; | ||
| + | |||
| + | |||
| + | public void contextInitialized(ServletContextEvent pEvent) | ||
| + | { | ||
| + | UserService.register(getApplicationName(), CMD_HEALTHCHECK, this); | ||
| + | } | ||
| + | |||
| + | public void contextDestroyed(ServletContextEvent pEvent) | ||
| + | { | ||
| + | UserService.unregister(getApplicationName(), CMD_HEALTHCHECK, this); | ||
| + | } | ||
| + | |||
| + | public Object call(AbstractCustomService pService, String pApplicationName, String pAction, String pParameter)throws Throwable | ||
| + | { | ||
| + | //GET request | ||
| + | |||
| + | OrderedHashtable<String, String> ohtResult = new OrderedHashtable<String, String>(); | ||
| + | |||
| + | ohtResult.put("code", "SUCCESS"); | ||
| + | ohtResult.put("message", "GET is working!"); | ||
| + | |||
| + | return ohtResult; | ||
| + | } | ||
| + | |||
| + | public Object call(AbstractCustomService pService, String pApplicationName, String pAction, String pParameter, Map<String, Object> pInput) throws Throwable | ||
| + | { | ||
| + | //POST request | ||
| + | |||
| + | OrderedHashtable<String, Object> ohtResult = new OrderedHashtable<String, Object>(); | ||
| + | |||
| + | ohtResult.put("code", "SUCCESS"); | ||
| + | ohtResult.put("message", "POST is working!"); | ||
| + | |||
| + | if (pInput != null) | ||
| + | { | ||
| + | //adds the input to the output | ||
| + | ohtResult.putAll(pInput); | ||
| + | } | ||
| + | |||
| + | return ohtResult; | ||
| + | } | ||
| + | |||
| + | private String getApplicationName() | ||
| + | { | ||
| + | List<String> list = Configuration.listApplicationNames(ApplicationListOption.All); | ||
| + | |||
| + | if (list.size() == 1) | ||
| + | { | ||
| + | return list.get(0); | ||
| + | } | ||
| + | else | ||
| + | { | ||
| + | return "demo"; | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | </file> | ||
| + | If you won't define the context listener as ''@WebListener'', simply add: | ||
| + | |||
| + | <file xml> | ||
| + | <listener> | ||
| + | <listener-class>com.sibvisions.jvx.CustomRESTServices</listener-class> | ||
| + | </listener> | ||
| + | </file> | ||
| + | to your deployment descriptor (web.xml). | ||
| + | |||
| + | To use your services, simply send ''GET'' or ''POST'' requests, e.g. | ||
| + | |||
| + | <file java> | ||
| + | @Test | ||
| + | public void testGet() throws Exception | ||
| + | { | ||
| + | ClientResource cres = new ClientResource(getBaseURL() + "_user/healthCheck"); | ||
| + | cres.get(); | ||
| + | |||
| + | HashMap<String, Object> hmpResult = (HashMap<String, Object>)JSONUtil.getObject(cres.getResponse().getEntity()); | ||
| + | |||
| + | Assert.assertEquals(200, cres.getStatus().getCode()); | ||
| + | Assert.assertEquals("SUCCESS", hmpResult.get("code")); | ||
| + | Assert.assertEquals("GET is working!", hmpResult.get("message")); | ||
| + | Assert.assertEquals(2, hmpResult.size()); | ||
| + | } | ||
| + | |||
| + | @Test | ||
| + | public void testPost() throws Exception | ||
| + | { | ||
| + | IBean bean = new Bean(); | ||
| + | bean.put("username", "@john.doe"); | ||
| + | bean.put("firstName", "John"); | ||
| + | bean.put("lastName", "Doe"); | ||
| + | |||
| + | ClientResource cres = new ClientResource(getBaseURL() + "_user/healthCheck"); | ||
| + | cres.post(bean); | ||
| + | |||
| + | HashMap<String, Object> hmpResult = (HashMap<String, Object>)JSONUtil.getObject(cres.getResponse().getEntity()); | ||
| + | |||
| + | Assert.assertEquals(200, cres.getStatus().getCode()); | ||
| + | Assert.assertEquals("SUCCESS", hmpResult.get("code")); | ||
| + | Assert.assertEquals("POST is working!", hmpResult.get("message")); | ||
| + | Assert.assertEquals(5, hmpResult.size()); | ||
| + | Assert.assertEquals(bean.get("username"), hmpResult.get("username")); | ||
| + | } | ||
| + | </file> | ||
| + | |||
| + | The user-zone is per default ''_zone'' (e.g. **http://localhost/AppContext/services/rest/_user/healthCheck**). If you want another zone name, simply add a parameter to the servlet mapping in deployment descriptor (web.xml): | ||
| + | |||
| + | <file xml> | ||
| + | <servlet> | ||
| + | <servlet-name>RestletServlet</servlet-name> | ||
| + | <servlet-class>com.sibvisions.rad.server.http.rest.RESTServlet</servlet-class> | ||
| + | |||
| + | <init-param> | ||
| + | <param-name>zone.user</param-name> | ||
| + | <param-value>uzone</param-value> | ||
| + | </init-param> | ||
| + | </servlet> | ||
| + | </file> | ||
| + | |||
| + | The zone name is now ''uzone'' (e.g. **http://localhost/AppContext/services/rest/uzone/healthCheck**). | ||
| + | |||
| + | The complete source code is available [[https://sourceforge.net/p/jvx/code/HEAD/tree/trunk/java/server/tomcat/|here]]. | ||
| + | |||
| + | In this document, we registered User services. It's also possible to register custom services as [[jvx:common:util:rest#administration|Admin services]]. The difference is that it's possible to [[jvx:server:security:rest_services_disable|en/disable admin services]] by name. | ||
