All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.juneau.rest.remote.RemoteInterfaceServlet Maven / Gradle / Ivy

There is a newer version: 9.0.1
Show newest version
// ***************************************************************************************************************************
// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
// * with the License.  You may obtain a copy of the License at                                                              *
// *                                                                                                                         *
// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
// *                                                                                                                         *
// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
// * specific language governing permissions and limitations under the License.                                              *
// ***************************************************************************************************************************
package org.apache.juneau.rest.remote;

import static org.apache.juneau.dto.html5.HtmlBuilder.*;
import static org.apache.juneau.http.HttpMethodName.*;
import static org.apache.juneau.internal.StringUtils.*;

import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import java.util.Map;
import java.util.concurrent.*;

import org.apache.juneau.dto.*;
import org.apache.juneau.dto.html5.*;
import org.apache.juneau.http.*;
import org.apache.juneau.http.annotation.*;
import org.apache.juneau.http.annotation.Header;
import org.apache.juneau.internal.*;
import org.apache.juneau.parser.*;
import org.apache.juneau.remote.*;
import org.apache.juneau.rest.*;
import org.apache.juneau.rest.annotation.*;
import org.apache.juneau.rest.exception.*;

/**
 * Abstract class for defining Remote Interface Services.
 *
 * 

* Remote Interface Services are POJOs whose methods can be invoked remotely through proxy interfaces. * *

* To implement a remote interface service, developers must simply subclass from this class and implement the * {@link #getServiceMap()} method that maps java interfaces to POJO instances. * *

See Also:
*
    *
*/ @SuppressWarnings({"serial","javadoc"}) public abstract class RemoteInterfaceServlet extends BasicRestServlet { private final Map serviceMap = new ConcurrentHashMap<>(); //----------------------------------------------------------------------------------------------------------------- // Abstract methods //----------------------------------------------------------------------------------------------------------------- /** * Returns the list of interfaces to their implementation objects. * *

* This class is called often and not cached, so any caching should occur in the subclass if necessary. * * @return The service map. * @throws Exception */ protected abstract Map,Object> getServiceMap() throws Exception; //----------------------------------------------------------------------------------------------------------------- // REST methods //----------------------------------------------------------------------------------------------------------------- @RestMethod( name=GET, path="/", summary="List of available remote interfaces", description="Shows a list of the interfaces registered with this remote interface servlet." ) public List getInterfaces() throws Exception { List l = new LinkedList<>(); for (Class c : getServiceMap().keySet()) l.add(new LinkString(c.getName(), "servlet:/{0}", urlEncode(c.getName()))); return l; } @RestMethod( name=GET, path="/{javaInterface}", summary="List of available methods on interface", description="Shows a list of all the exposed methods on an interface.", htmldoc=@HtmlDoc( nav="

Interface: $RP{javaInterface}
" ) ) public Collection listMethods( @Path(name="javaInterface", description="Java interface name", example="com.foo.MyInterface") String javaInterface ) throws Exception { List l = new ArrayList<>(); for (String s : getMethods(javaInterface).keySet()) l.add(new LinkString(s, "servlet:/{0}/{1}", urlEncode(javaInterface), urlEncode(s))); return l; } @RestMethod( name=GET, path="/{javaInterface}/{javaMethod}", summary="Form entry for interface method call", description="Shows a form entry page for executing a remote interface method.", htmldoc=@HtmlDoc( nav={ "
Interface: $RP{javaInterface}
", "
Method: $RP{javaMethod}
" } ) ) public Div showEntryForm( @Path(name="javaInterface", description="Java interface name", example="com.foo.MyInterface") String javaInterface, @Path(name="javaMethod", description="Java method name", example="myMethod") String javaMethod ) throws NotFound, Exception { // Find the method. RemoteInterfaceMethod rmm = getMethods(javaInterface).get(javaMethod); if (rmm == null) throw new NotFound("Method not found"); Table t = table(); Type[] types = rmm.getJavaMethod().getGenericParameterTypes(); if (types.length == 0) { t.child(tr(td("No arguments").colspan(3).style("text-align:center"))); } else { t.child(tr(th("Index"),th("Type"),th("Value"))); for (int i = 0; i < types.length; i++) { String type = ClassUtils.toString(types[i]); t.child(tr(td(i), td(type), td(input().name(String.valueOf(i)).type("text")))); } } t.child( tr( td().colspan(3).style("text-align:right").children( types.length == 0 ? null : button("reset", "Reset"), button("button","Cancel").onclick("window.location.href='/'"), button("submit", "Submit") ) ) ); return div(form().id("form").action("request:/").method(POST).children(t)); } @RestMethod( name=POST, path="/{javaInterface}/{javaMethod}", summary="Invoke an interface method", description="Invoke a Java method by passing in the arguments as an array of serialized objects.\nThe returned object is then serialized to the response.", htmldoc=@HtmlDoc( nav= { "
Interface: $RP{javaInterface}
", "
Method: $RP{javaMethod}
" } ), swagger=@MethodSwagger( parameters= { "{", "in: 'body',", "description: 'Serialized array of Java objects',", "schema: {", "type': 'array'", "},", "x-examples: {", "'application/json+lax': '[\\'foo\\', 123, true]'", "}", "}" }, responses= { "200:{ description:'The return object serialized', schema:{type:'any'},'x-example':{foo:123} }", } ) ) public Object invoke( Reader r, ReaderParser p, @Header("Content-Type") ContentType contentType, @Path(name="javaInterface", description="Java interface name", example="com.foo.MyInterface") String javaInterface, @Path(name="javaMethod", description="Java method name", example="myMethod") String javaMethod ) throws UnsupportedMediaType, NotFound, Exception { // Find the parser. if (p == null) throw new UnsupportedMediaType("Could not find parser for media type ''{0}''", contentType); RemoteInterfaceMeta rim = getInterfaceClass(javaInterface); // Find the service. Object service = getServiceMap().get(rim.getJavaClass()); if (service == null) throw new NotFound("Service not found"); // Find the method. RemoteInterfaceMethod rmm = getMethods(javaInterface).get(javaMethod); if (rmm == null) throw new NotFound("Method not found"); // Parse the args and invoke the method. java.lang.reflect.Method m = rmm.getJavaMethod(); Object[] params = p.parseArgs(r, m.getGenericParameterTypes()); return m.invoke(service, params); } //----------------------------------------------------------------------------------------------------------------- // Other methods //----------------------------------------------------------------------------------------------------------------- private Map getMethods(String javaInterface) throws Exception { return getInterfaceClass(javaInterface).getMethodsByPath(); } /** * Return the Class given it's name if it exists in the services map. */ private RemoteInterfaceMeta getInterfaceClass(String javaInterface) throws NotFound, Exception { RemoteInterfaceMeta rm = serviceMap.get(javaInterface); if (rm == null) { for (Class c : getServiceMap().keySet()) { if (c.getName().equals(javaInterface)) { rm = new RemoteInterfaceMeta(c, null); serviceMap.put(javaInterface, rm); return rm; } } throw new NotFound("Interface class not found"); } return rm; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy