/** * Attempts to determine the service interface class of the provided proxy * object. * * @since 0.5 * @return the base service interface class * @throws ClassNotFoundException * if attempt to find base interface from class ending in * "Async" fails */ protected static Class<?> determineProxyServiceBaseInterface(Object proxy) throws ClassNotFoundException { for (Class<?> clazz : proxy.getClass().getInterfaces()) { if (RemoteService.class.isAssignableFrom(clazz)) { return clazz; } if (clazz.getName().endsWith(SyncProxy.ASYNC_POSTFIX)) { return Class.forName(clazz.getName().replace( SyncProxy.ASYNC_POSTFIX, "")); } // if (!ServiceDefTarget.class.equals(clazz) // && !HasRpcToken.class.equals(clazz) // && !SerializationStreamFactory.class.equals(clazz)) { // srvcIntf = Class.forName(clazz.getName().replace("Async", // "")); // } } return null; }
/** * Similar action to Gwt.create(). This method assumes your service is * annotated with {@link RemoteServiceRelativePath} and that you have * appropriately set the base url: {@link #setBaseURL(String)}. See * {@link #suppressRelativePathWarning(boolean)} in the event your service * is not annotated with {@link RemoteServiceRelativePath}. * * @since 0.5 * @param serviceIntf * @return */ @SuppressWarnings("unchecked") public static <ServiceIntfAsync, ServiceIntf extends RemoteService> ServiceIntfAsync create( Class<ServiceIntf> serviceIntf) { logger.config("Create service: " + serviceIntf.getName()); Class<ServiceIntfAsync> asyncServiceIntf; try { asyncServiceIntf = (Class<ServiceIntfAsync>) Class .forName(serviceIntf.getName() + ASYNC_POSTFIX); } catch (ClassNotFoundException e) { throw new SyncProxyException(serviceIntf, InfoType.SERVICE_BASE); } logger.config("Creating Async Service: " + asyncServiceIntf.getName()); return createProxy(asyncServiceIntf, new ProxySettings()); }
private RPCServiceExporter initServiceInstance(RPCServiceExporter exporter, Object service, Class<RemoteService>[] serviceInterfaces) { try { exporter.setResponseCachingDisabled(disableResponseCaching); exporter.setServletContext(getServletContext()); exporter.setServletConfig(servletConfig); exporter.setService(service); exporter.setServiceInterfaces(serviceInterfaces); exporter .setThrowUndeclaredExceptionToServletContainer(throwUndeclaredExceptionToServletContainer); if (shouldCheckPermutationStrongName) exporter.setShouldCheckPermutationStrongName(true); exporter.afterPropertiesSet(); return exporter; } catch (Exception e) { throw new RuntimeException(e); } }
@Override public String processCall(String payload) throws SerializationException { try { RPCRequest req = RPC.decodeRequest(payload, null, this); RemoteService service = getServiceInstance(req.getMethod().getDeclaringClass()); return RPC.invokeAndEncodeResponse(service, req.getMethod(), req.getParameters(), req.getSerializationPolicy()); } catch (IncompatibleRemoteServiceException ex) { log("IncompatibleRemoteServiceException in the processCall(String) method.", ex); return RPC.encodeResponseForFailure(null, ex); } }
/** * Scans the application context and its parents for service beans that implement the {@link * com.google.gwt.user.client.rpc.RemoteService} * * @param appContext Application context * * @return Map<String, Object> A map of RemoteServiceRelativePath annotation values vs the RPC service instances */ private Map<String, Object> initGwtRpcServiceMap(final ApplicationContext appContext) { // Create a map of rpc services keyed against the RemoteServiceRelativePath annotation value Map<String, Object> rpcServiceMap = new HashMap<String, Object>(); // If Gwt RPC service beans exist already (may be explicitly configured through spring config xml file) // then add them first. Map<String, Object> existingGwtRpcServiceMap = getGwtRpcServiceMap(); if (existingGwtRpcServiceMap != null) { rpcServiceMap.putAll(existingGwtRpcServiceMap); } if (appContext != null) { //Find the beans of type RemoteService String[] remoteServiceBeans = appContext.getBeanNamesForType(RemoteService.class); if (!ArrayUtils.isEmpty(remoteServiceBeans)) { // If remoteServiceBeans are found then scan for Gwt Rpc beans scanForGwtRpcBeans(appContext, rpcServiceMap, remoteServiceBeans); } } return rpcServiceMap; }
@Override public Set<JType> findStorageTypes() throws UnableToCompleteException{ Set<JType> serializables = new HashSet<>(); JClassType remoteSvcIntf = typeOracle.findType(RemoteService.class.getName()); JClassType[] remoteSvcTypes = remoteSvcIntf.getSubtypes(); for(JClassType remoteSvcType : remoteSvcTypes){ for(JMethod method : remoteSvcType.getMethods()){ JType type = method.getReturnType(); if(JPrimitiveType.VOID != type){ addIfIsValidType(serializables, type); } for(JType param : method.getParameterTypes()){ addIfIsValidType(serializables, param); } } } return serializables; }
@Override @SuppressWarnings("unchecked") // safe since we check whether the type is assignable public <T> T create(Class<?> createdType) { // If we're creating a RemoteService, assume that the result of GWT.create is being assigned // to the async version of that service. Otherwise, assume it's being assigned to the same // type we're creating. Class<?> assignedType = RemoteService.class.isAssignableFrom(createdType) ? getAsyncType((Class<? extends RemoteService>) createdType) : createdType; // First check if we have a GwtMock for this exact being assigned to and use it if so. if (registeredMocks.containsKey(assignedType)) { return (T) registeredMocks.get(assignedType); } // Next check if we have a fake provider that can provide a fake for the type being created. T fake = (T) getFakeFromProviderMap(createdType, registeredProviders); if (fake != null) { return fake; } // If nothing has been registered, just return a new mock for the type being assigned. return (T) mock(assignedType, new ReturnsCustomMocks()); }
/** * Determine Spring bean to handle request based on request URL, e.g. a * request ending in /myService will be handled by bean with name * "myService". * * @param request * @return handler bean */ protected Object getBean(HttpServletRequest request) { String service = getService(request); Object bean = getBean(service); if (!(bean instanceof RemoteService)) { throw new IllegalArgumentException("Spring bean is not a GWT RemoteService: " + service + " (" + bean + ")"); } if (logger.isDebugEnabled()) { logger.debug("Bean for service " + service + " is " + bean); } return bean; }
@Override public String processCall(final String payload) throws SerializationException { try { Object presentationService = applicationContext.getBean(serviceName .get()); if (!(presentationService instanceof RemoteService)) { throw new IllegalArgumentException( "Requested Spring Bean is not a GWT RemoteService Presentation Service: " + payload + " (" + presentationService + ")"); } RPCRequest rpcRequest = RPC.decodeRequest(payload, presentationService.getClass(), this); if (presentationService instanceof AuthenticationServiceFacade && rpcRequest.getMethod().equals( AuthenticationServiceFacade.class .getMethod("getXSRFSessionToken"))) { return RPC.encodeResponseForSuccess(rpcRequest.getMethod(), SecurityHelper.createXSRFToken(getThreadLocalRequest())); } return RPC.invokeAndEncodeResponse(presentationService, rpcRequest.getMethod(), rpcRequest.getParameters(), rpcRequest.getSerializationPolicy(), rpcRequest.getFlags()); } catch (Exception e) { GWTPresentationException pex = new GWTPresentationException( e.getMessage()); return RPC.encodeResponseForFailure(null, pex); } }
@Test public void testGetInterfaces() { MyAbstractTestClass instance = CGLibProxy.newInstance(MyTestClass.class); assertTrue(instance instanceof RemoteService); assertTrue(ReflectionUtils.getExposedInterfaces(instance.getClass()).length == 1); }
/** * Scans the application context and its parents for service beans that * implement the {@link GWTRequestMapping} * * @param appContext * Application context */ private void scanForAnnotatedBeans(final ApplicationContext appContext) { if (appContext == null) { return; } for (String beanName : appContext .getBeanNamesForType(RemoteService.class)) { Object service = appContext.getBean(beanName); if (service == null) continue; final Class<?> beanClass = service.getClass(); final RemoteServiceRelativePath requestMapping = ReflectionUtils .findAnnotation(beanClass, RemoteServiceRelativePath.class); if (requestMapping == null) { continue; } // Create serviceExporter to bind to String mapping = requestMapping.value(); if (mapping.contains("/")){ mapping = mapping.substring(mapping.lastIndexOf("/")); } if (getMappings().containsKey(mapping)) logger.warn("Bean '" + mapping + "' already in mapping, skipping."); else getMappings().put(mapping, service); } if (scanParentApplicationContext) scanForAnnotatedBeans(appContext.getParent()); }
/** * Return array of all interfaces that are implemented by clazz and extend * {@link RemoteService}. * * @param clazz Class to scan for interfaces * @return Array of interfaces. May be empty but never null. */ @SuppressWarnings("unchecked") public static Class<RemoteService>[] getExposedInterfaces(Class<?> clazz) { Set<Class<?>> interfaces = getInterfaces(clazz); for (Iterator<Class<?>> ite = interfaces.iterator(); ite.hasNext();) { Class<?> c = ite.next(); if (!isExposed(c)) ite.remove(); } return interfaces.toArray(new Class[interfaces.size()]); }
/** * Determine Spring bean to handle request based on request URL, e.g. a * request ending in /myService will be handled by bean with name * "myService". * * @param request * @return handler bean */ protected Object getBean(HttpServletRequest request) { String service = getService(request); Object bean = getBean(service); if (!(bean instanceof RemoteService)) { throw new IllegalArgumentException("Spring bean is not a GWT RemoteService: " + service + " (" + bean + ")"); } if (LOG.isDebugEnabled()) { LOG.debug("Bean for service " + service + " is " + bean); } return bean; }
/** * Determine Spring bean to handle request based on request URL, e.g. a * request ending in /myService will be handled by bean with name * "myService". * * @param request the request * @return handler bean */ protected Object getBean(HttpServletRequest request) { String service = getService(request); Object bean = getBean(service); if (!(bean instanceof RemoteService)) { throw new IllegalArgumentException("Spring bean is not a GWT RemoteService: " + service + " (" + bean + ")"); } if (LOG.isDebugEnabled()) { LOG.debug("Bean for service " + service + " is " + bean); } return bean; }
/** Returns the corresponding async service type for the given remote service type. */ private Class<?> getAsyncType(Class<? extends RemoteService> type) { Class<?> asyncType; try { asyncType = Class.forName(type.getCanonicalName() + "Async"); } catch (ClassNotFoundException e) { throw new IllegalArgumentException( type.getCanonicalName() + " does not have a corresponding async interface", e); } return asyncType; }
private static boolean hasSynchronousServiceInterface(TypeLiteral<?> type) { Class<?> synchronousType = getSynchronousServiceClass(type); return synchronousType != null && RemoteService.class.isAssignableFrom(synchronousType); }
private static boolean isExposed(Class<?> c) { return RemoteService.class.isAssignableFrom(c); }
public void setRemoteService(RemoteService remoteService) { this.remoteService = remoteService; this.remoteServiceClass = this.remoteService.getClass(); }
@SuppressWarnings({"unchecked"}) private RemoteService getServiceInstance(Class serviceClass) { return (RemoteService) injector.get().getInstance(serviceClass); }
/** * Similar action to Gwt.create() except that this creates a sync'ed proxy. * This method assumes your service is annotated with * {@link RemoteServiceRelativePath} and that you have appropriately set the * base url: {@link #setBaseURL(String)}. See * {@link #suppressRelativePathWarning(boolean)} in the event your service * is not annotated with {@link RemoteServiceRelativePath}. * * @since 0.5 * @param serviceIntf * @return */ public static <ServiceIntf extends RemoteService> ServiceIntf createSync( Class<ServiceIntf> serviceIntf) { logger.config("Create Sync Service: " + serviceIntf.getName()); return createProxy(serviceIntf, new ProxySettings()); }
/** * Specifies the interfaces which must be implemented by the service bean. * If not specified then any interface extending {@link RemoteService} which * is implemented by the service bean is assumed. Implementation note: * as methods are only lazily bound to the service implementation you may get * away with mismatches between the specified interfaces and the actual implementation * as long as no method is invoked which has a different/missing signature in the interface * and the service implementation. * * @param serviceInterfaces List of interfaces */ public void setServiceInterfaces(Class<RemoteService>[] serviceInterfaces) { this.serviceInterfaces = serviceInterfaces; }
/** * Declare Interfaces that will be bound to RPC * @param interfaces Array of Interfaces */ void setServiceInterfaces(Class<RemoteService>[] interfaces);