@Override protected void configureServlets() { install(new JpaPersistModule("transactions-optional")); filterRegex("^/(?!_ah/(upload|admin)).*$").through(PersistFilter.class); MethodInterceptor finderInterceptor = new JpaFinderProxy(); requestInjection(finderInterceptor); bindInterceptor(Matchers.any(), Matchers.annotatedWith(Finder.class), finderInterceptor); filter(ProxyFilter.PROXY_PATH + "*").through(ProxyFilter.class); if (SystemProperty.environment.value() == SystemProperty.Environment.Value.Development) { filter("/_ah/api/" + "*").through(LocalDevServerFilter.class); } Set<Class<?>> serviceClasses = new HashSet<Class<?>>(); serviceClasses.add(DeviceEndpoint.class); serviceClasses.add(AccountEndpoint.class); serviceClasses.add(PresenceEndpoint.class); serviceClasses.add(AppEngineChannelService.class); serviceClasses.add(GoogleCloudMessaging.class); serviceClasses.add(ApplePushNotification.class); this.serveGuiceSystemServiceServlet("/_ah/spi/*", serviceClasses); }
private JpaFinderProxy.FinderDescriptor getFinderDescriptor(MethodInvocation invocation) { Method method = invocation.getMethod(); JpaFinderProxy.FinderDescriptor finderDescriptor = finderCache.get(method); if (null != finderDescriptor) { return finderDescriptor; } //otherwise reflect and cache finder info... finderDescriptor = new JpaFinderProxy.FinderDescriptor(); //determine return type finderDescriptor.returnClass = invocation.getMethod().getReturnType(); finderDescriptor.returnType = determineReturnType(finderDescriptor.returnClass); //determine finder query characteristics Finder finder = invocation.getMethod().getAnnotation(Finder.class); String query = finder.query(); if (!"".equals(query.trim())) { finderDescriptor.setQuery(query); } else { finderDescriptor.setNamedQuery(finder.namedQuery()); } //determine parameter annotations Annotation[][] parameterAnnotations = method.getParameterAnnotations(); Object[] discoveredAnnotations = new Object[parameterAnnotations.length]; for (int i = 0; i < parameterAnnotations.length; i++) { Annotation[] annotations = parameterAnnotations[i]; //each annotation per param for (Annotation annotation : annotations) { //discover the named, first or max annotations then break out Class<? extends Annotation> annotationType = annotation.annotationType(); if (Named.class.equals(annotationType) || javax.inject.Named.class.equals(annotationType)) { discoveredAnnotations[i] = annotation; finderDescriptor.isBindAsRawParameters = false; break; } else if (FirstResult.class.equals(annotationType)) { discoveredAnnotations[i] = annotation; break; } else if (MaxResults.class.equals(annotationType)) { discoveredAnnotations[i] = annotation; break; } //leave as null for no binding } } //set the discovered set to our finder cache object finderDescriptor.parameterAnnotations = discoveredAnnotations; //discover the returned collection implementation if this finder returns a collection if (JpaFinderProxy.ReturnType.COLLECTION.equals(finderDescriptor.returnType) && finderDescriptor.returnClass != Collection.class) { finderDescriptor.returnCollectionType = finder.returnAs(); try { finderDescriptor.returnCollectionTypeConstructor = finderDescriptor.returnCollectionType.getConstructor(); finderDescriptor.returnCollectionTypeConstructor.setAccessible(true); //UGH! } catch (NoSuchMethodException e) { throw new RuntimeException( "Finder's collection return type specified has no default constructor! returnAs: " + finderDescriptor.returnCollectionType, e); } } //cache it cacheFinderDescriptor(method, finderDescriptor); return finderDescriptor; }
private <T> void bindFinder(Class<T> iface) { if (!isDynamicFinderValid(iface)) { return; } InvocationHandler finderInvoker = new InvocationHandler() { @Inject JpaFinderProxy finderProxy; @Override public Object invoke(final Object thisObject, final Method method, final Object[] args) throws Throwable { // Don't intercept non-finder methods like equals and hashcode. if (!method.isAnnotationPresent(Finder.class)) { // NOTE(dhanji): This is not ideal, we are using the invocation handler's equals // and hashcode as a proxy (!) for the proxy's equals and hashcode. return method.invoke(this, args); } return finderProxy.invoke( new MethodInvocation() { @Override public Method getMethod() { return method; } @Override public Object[] getArguments() { return null == args ? new Object[0] : args; } @Override public Object proceed() throws Throwable { return method.invoke(thisObject, args); } @Override public Object getThis() { throw new UnsupportedOperationException( "Bottomless proxies don't expose a this."); } @Override public AccessibleObject getStaticPart() { throw new UnsupportedOperationException(); } }); } }; requestInjection(finderInvoker); @SuppressWarnings("unchecked") // Proxy must produce instance of type given. T proxy = (T) Proxy.newProxyInstance( Thread.currentThread().getContextClassLoader(), new Class<?>[] {iface}, finderInvoker); bind(iface).toInstance(proxy); }
@Finder(query = "from JpaTestEntity where text = :text") public JpaTestEntity find(@Named("text") String text) { return null; }
@Finder(query = "from JpaTestEntity", returnAs = ArrayList.class) public List<JpaTestEntity> listAll();
private JpaFinderProxy.FinderDescriptor getFinderDescriptor(MethodInvocation invocation) { Method method = invocation.getMethod(); JpaFinderProxy.FinderDescriptor finderDescriptor = finderCache.get(method); if (null != finderDescriptor) { return finderDescriptor; } //otherwise reflect and cache finder info... finderDescriptor = new JpaFinderProxy.FinderDescriptor(); //determine return type finderDescriptor.returnClass = invocation.getMethod().getReturnType(); finderDescriptor.returnType = determineReturnType(finderDescriptor.returnClass); //determine finder query characteristics Finder finder = invocation.getMethod().getAnnotation(Finder.class); String query = finder.query(); if (!"".equals(query.trim())) { finderDescriptor.setQuery(query); } else { finderDescriptor.setNamedQuery(finder.namedQuery()); } //determine parameter annotations Annotation[][] parameterAnnotations = method.getParameterAnnotations(); Object[] discoveredAnnotations = new Object[parameterAnnotations.length]; for (int i = 0; i < parameterAnnotations.length; i++) { Annotation[] annotations = parameterAnnotations[i]; //each annotation per param for (Annotation annotation : annotations) { //discover the named, first or max annotations then break out Class<? extends Annotation> annotationType = annotation.annotationType(); if (Named.class.equals(annotationType) || javax.inject.Named.class.equals(annotationType)) { discoveredAnnotations[i] = annotation; finderDescriptor.isBindAsRawParameters = false; break; } else if (FirstResult.class.equals(annotationType)) { discoveredAnnotations[i] = annotation; break; } else if (MaxResults.class.equals(annotationType)) { discoveredAnnotations[i] = annotation; break; } //leave as null for no binding } } //set the discovered set to our finder cache object finderDescriptor.parameterAnnotations = discoveredAnnotations; //discover the returned collection implementation if this finder returns a collection if (JpaFinderProxy.ReturnType.COLLECTION.equals(finderDescriptor.returnType) && finderDescriptor.returnClass != Collection.class) { finderDescriptor.returnCollectionType = finder.returnAs(); try { finderDescriptor.returnCollectionTypeConstructor = finderDescriptor.returnCollectionType .getConstructor(); finderDescriptor.returnCollectionTypeConstructor.setAccessible(true); //UGH! } catch (NoSuchMethodException e) { throw new RuntimeException( "Finder's collection return type specified has no default constructor! returnAs: " + finderDescriptor.returnCollectionType, e); } } //cache it cacheFinderDescriptor(method, finderDescriptor); return finderDescriptor; }
private <T> void bindFinder(Class<T> iface) { if (!isDynamicFinderValid(iface)) { return; } InvocationHandler finderInvoker = new InvocationHandler() { @Inject JpaFinderProxy finderProxy; public Object invoke(final Object thisObject, final Method method, final Object[] args) throws Throwable { // Don't intercept non-finder methods like equals and hashcode. if (!method.isAnnotationPresent(Finder.class)) { // NOTE(dhanji): This is not ideal, we are using the invocation handler's equals // and hashcode as a proxy (!) for the proxy's equals and hashcode. return method.invoke(this, args); } return finderProxy.invoke(new MethodInvocation() { public Method getMethod() { return method; } public Object[] getArguments() { return null == args ? new Object[0] : args; } public Object proceed() throws Throwable { return method.invoke(thisObject, args); } public Object getThis() { throw new UnsupportedOperationException("Bottomless proxies don't expose a this."); } public AccessibleObject getStaticPart() { throw new UnsupportedOperationException(); } }); } }; requestInjection(finderInvoker); @SuppressWarnings("unchecked") // Proxy must produce instance of type given. T proxy = (T) Proxy .newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[] { iface }, finderInvoker); bind(iface).toInstance(proxy); }
private JpaFinderProxy.FinderDescriptor getFinderDescriptor(MethodInvocation invocation) { Method method = invocation.getMethod(); JpaFinderProxy.FinderDescriptor finderDescriptor = finderCache.get(method); if (null != finderDescriptor) { return finderDescriptor; } // otherwise reflect and cache finder info... finderDescriptor = new JpaFinderProxy.FinderDescriptor(); // determine return type finderDescriptor.returnClass = invocation.getMethod().getReturnType(); finderDescriptor.returnType = determineReturnType(finderDescriptor.returnClass); // determine finder query characteristics Finder finder = invocation.getMethod().getAnnotation(Finder.class); String query = finder.query(); if (!"".equals(query.trim())) { finderDescriptor.setQuery(query); } else { finderDescriptor.setNamedQuery(finder.namedQuery()); } // determine parameter annotations Annotation[][] parameterAnnotations = method.getParameterAnnotations(); Object[] discoveredAnnotations = new Object[parameterAnnotations.length]; for (int i = 0; i < parameterAnnotations.length; i++) { Annotation[] annotations = parameterAnnotations[i]; // each annotation per param for (Annotation annotation : annotations) { // discover the named, first or max annotations then break out Class<? extends Annotation> annotationType = annotation.annotationType(); if (Named.class.equals(annotationType) || javax.inject.Named.class.equals(annotationType)) { discoveredAnnotations[i] = annotation; finderDescriptor.isBindAsRawParameters = false; break; } else if (FirstResult.class.equals(annotationType)) { discoveredAnnotations[i] = annotation; break; } else if (MaxResults.class.equals(annotationType)) { discoveredAnnotations[i] = annotation; break; } // leave as null for no binding } } // set the discovered set to our finder cache object finderDescriptor.parameterAnnotations = discoveredAnnotations; // discover the returned collection implementation if this finder returns a collection if (JpaFinderProxy.ReturnType.COLLECTION.equals(finderDescriptor.returnType) && finderDescriptor.returnClass != Collection.class) { finderDescriptor.returnCollectionType = finder.returnAs(); try { finderDescriptor.returnCollectionTypeConstructor = finderDescriptor.returnCollectionType.getConstructor(); finderDescriptor.returnCollectionTypeConstructor.setAccessible(true); // UGH! } catch (NoSuchMethodException e) { throw new RuntimeException( "Finder's collection return type specified has no default constructor! returnAs: " + finderDescriptor.returnCollectionType, e); } } // cache it cacheFinderDescriptor(method, finderDescriptor); return finderDescriptor; }