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

fish.payara.ejb.http.client.EjbHttpProxyHandler Maven / Gradle / Ivy

Go to download

Module providing support for the EJB HTTP Client. This contains an InitialContext based lookup mechanism that uses HTTP calls back to Payara to lookup EJB beans, as well as a proxy mechanism to invoke methods on an EJB, which will be sent via HTTP to Payara.

The newest version!
package fish.payara.ejb.http.client;

import static javax.naming.Context.SECURITY_CREDENTIALS;
import static javax.naming.Context.SECURITY_PRINCIPAL;
import static jakarta.ws.rs.HttpMethod.POST;
import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.Future;

import jakarta.ws.rs.client.Entity;
import jakarta.ws.rs.client.Invocation;
import jakarta.ws.rs.client.WebTarget;
import jakarta.ws.rs.core.Cookie;
import jakarta.ws.rs.core.GenericType;
import jakarta.ws.rs.core.MultivaluedHashMap;
import jakarta.ws.rs.core.MultivaluedMap;

/**
 * This class handles invocations (method calls) on a proxy generated by {@link EjbRestProxyFactory}.
 * 
 * 

* This proxy uses REST calls to an endpoint in a given remote Payara server. * * @author Arjan Tijms * @since Payara 5.191 * */ class EjbHttpProxyHandler implements InvocationHandler { private final WebTarget target; private final MultivaluedMap headers; private final List cookies; private final String lookup; private final Map jndiOptions; EjbHttpProxyHandler(WebTarget target, MultivaluedMap headers, List cookies, String lookup, Map jndiOptions) { this.target = target; this.headers = headers; this.cookies = cookies; this.lookup = lookup; this.jndiOptions = jndiOptions; } @Override public Object invoke(Object proxy, Method method, Object[] argValues) throws Throwable { // Check for methods we should not proxy first if (argValues == null && method.getName().equals("toString")) { return toString(); } if (argValues == null && method.getName().equals("hashCode")) { // unique instance in the JVM, and no need to override return hashCode(); } if (argValues != null && argValues.length == 1 && method.getName().equals("equals")) { // unique instance in the JVM, and no need to override return equals(argValues[0]); } // Valid method, do invoke it remotely return doRemoteInvoke(proxy, method, argValues); } public Object doRemoteInvoke(Object proxy, Method method, Object[] argValues) throws Throwable { // HTTP method name; we're always using POST to invoke remote EJBs String httpMethod = POST; // The bare payload being sent Map payload = new HashMap<>(); payload.put("lookup", lookup); payload.put("method", method.getName()); payload.put("argTypes", Arrays.stream(method.getParameterTypes()).map(Class::getName).toArray()); payload.put("argValues", argValues == null? new Object[0] : argValues); if (jndiOptions.containsKey(SECURITY_PRINCIPAL)) { payload.put(SECURITY_PRINCIPAL, Lookup.base64Encode(jndiOptions.get(SECURITY_PRINCIPAL))); } if (jndiOptions.containsKey(SECURITY_CREDENTIALS)) { payload.put(SECURITY_CREDENTIALS, Lookup.base64Encode(jndiOptions.get(SECURITY_CREDENTIALS))); } // Payload wrapped as entity so it'll be encoded in JSON Entity entity = Entity.entity(payload, APPLICATION_JSON); // Response type Class responseType = method.getReturnType(); GenericType responseGenericType = new GenericType<>(method.getGenericReturnType()); // Create a new UriBuilder appending the name from the method WebTarget newTarget = addPathFromMethod(method, target); // Start request Invocation.Builder builder = newTarget.request(); // Set optional headers and cookies builder.headers(new MultivaluedHashMap(this.headers)); for (Cookie cookie : new LinkedList<>(this.cookies)) { builder = builder.cookie(cookie); } // Call remote server if (responseType.isAssignableFrom(CompletionStage.class)) { // Reactive call - the actual response type is T from CompletionStage return builder.rx().method(httpMethod, entity, getResponseParameterizedType(method, responseGenericType)); } else if (responseType.isAssignableFrom(Future.class)) { // Asynchronous call - the actual response type is T from Future return builder.async().method(httpMethod, entity, getResponseParameterizedType(method, responseGenericType)); } // Synchronous call return builder.method(httpMethod, entity, responseGenericType); } private GenericType getResponseParameterizedType(Method method, GenericType responseGenericType) { if (method.getGenericReturnType() instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) method.getGenericReturnType(); return new GenericType<>(parameterizedType.getActualTypeArguments()[0]); } return responseGenericType; } private static WebTarget addPathFromMethod(Method method, WebTarget target) { return target.path(method.getName()); } @Override public String toString() { return target.toString(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy