@Override public <T> T createDynamicProxy(Class<T> type, Supplier<T> targetSupplier, String descriptionPattern, Object... descriptionParams) { final String description = String.format(descriptionPattern, descriptionParams); final Enhancer enhancer = new Enhancer(); enhancer.setClassLoader(new DelegatingClassLoader(type.getClassLoader(), Enhancer.class.getClassLoader())); enhancer.setInterfaces(new Class[]{type}); enhancer.setSuperclass(Object.class); enhancer.setCallbackFilter(FILTER); enhancer.setCallbacks(new Callback[]{ (Dispatcher) targetSupplier::get, (MethodInterceptor) (proxy, method, params, methodProxy) -> proxy == params[0], (MethodInterceptor) (proxy, method, params, methodProxy) -> System.identityHashCode(proxy), (MethodInterceptor) (proxy, method, params, methodProxy) -> description }); return type.cast(enhancer.create()); }
@Override public Supplier<Object> scope(Supplier<Object> supplier, Binding binding, CoreDependencyKey<?> requestedKey) { // create the proxy right away, such that it can be reused // afterwards Object proxy = Enhancer.create(requestedKey.getRawType(), new Dispatcher() { @Override public Object loadObject() throws Exception { Map<Binding, Object> scopedObjects = tryGetValueMap().orElseThrow( () -> new RuntimeException("Cannot access " + requestedKey + " outside of scope " + scopeName)); return scopedObjects.computeIfAbsent(binding, b -> supplier.get()); } }); return () -> proxy; }
private <T> T createProxy(final Class<T> clazz) { if (invocationsMap == null) { invocationsMap = new HashMap<>(); } try { final FeatureResolver resolver = FeatureResolver.newFeatureResolver(clazz).build(); final TestInvocation invocation = new TestInvocationImpl(clazz, resolver); invocationsMap.put(clazz, invocation); executor.processBeforeAll(invocation); } catch (final Exception e) { throw new JpaUnitException("Could not execute beforeAll hook", e); } final T bean = createBean(clazz); final CallbackHelper helper = new CallbackHelper(clazz, new Class[0]) { @Override protected Object getCallback(final Method method) { if (hasCucumberAnnotations(method)) { return new CucumberInterceptor(executor, bean); } else if (method.getName().equals("equals")) { return new EqualsInterceptor(bean); } else { return (Dispatcher) () -> bean; } } }; return clazz.cast(Enhancer.create(clazz, new Class[0], helper, helper.getCallbacks())); }
@Override public Supplier<Object> scope(Supplier<Object> supplier, Binding binding, CoreDependencyKey<?> requestedKey) { // create the proxy right away, such that it can be reused // afterwards Object proxy = Enhancer.create(requestedKey.getRawType(), new Dispatcher() { @Override public Object loadObject() throws Exception { State state = currentState.get(); Preconditions.checkState(state != null, "Access to session scoped proxy without active session scope"); Map<Binding, Object> sessionDataMap = state.getSessionData().sessionDataMap; synchronized (sessionDataMap) { return sessionDataMap.computeIfAbsent(binding, b -> supplier.get()); } } }); return new Supplier<Object>() { @Override public Object get() { return proxy; } @Override public String toString() { return "SessionScopeProxy[" + requestedKey + "]"; } }; }
@Override protected void configure() throws Exception { // register DBLinks DataBaseLinkRegistry registry = permanentInjector.getInstance(DataBaseLinkRegistry.class); for (DataBaseLink link : registry.getLinks()) { Class<? extends Annotation> requiredQualifier = link.getQualifier(); // bind data source bind(DataSource.class).annotatedWith(requiredQualifier) .toProvider(() -> link.getDataSourceManager().getDataSource()).in(Singleton.class); // bind EMF to registry { bind(EntityManagerFactory.class).annotatedWith(link.getQualifier()) .toProvider(new Provider<EntityManagerFactory>() { @Inject PersisteUnitRegistry registry; @Override public EntityManagerFactory get() { return registry.getUnit(requiredQualifier).orElseThrow(() -> new RuntimeException( "no persistence unit registered for " + requiredQualifier)); } }); } // bind EM to proxy bind(EntityManager.class).annotatedWith(requiredQualifier).toProvider(new Provider<EntityManager>() { @Inject EntityManagerHolder holder; @Override public EntityManager get() { return (EntityManager) Enhancer.create(EntityManager.class, new Dispatcher() { @Override public Object loadObject() throws Exception { return holder.getEntityManager(requiredQualifier); } }); } }).in(Singleton.class); } registerOwnEntityManagersAdvice(); registerTransactionalAdvice(); }