use of org.apache.tapestry5.ioc.Invokable in project tapestry-5 by apache.
the class ModuleImpl method create.
/**
* Creates the service and updates the cache of created services.
*
* @param eagerLoadProxies a list into which any eager loaded proxies should be added
*/
private Object create(final ServiceDef3 def, final Collection<EagerLoadServiceProxy> eagerLoadProxies) {
final String serviceId = def.getServiceId();
final Logger logger = registry.getServiceLogger(serviceId);
final Class serviceInterface = def.getServiceInterface();
final boolean canBeProxied = canBeProxiedPredicate.test(serviceInterface);
String description = String.format("Creating %s service %s", canBeProxied ? "proxy for" : "non-proxied instance of", serviceId);
if (logger.isDebugEnabled())
logger.debug(description);
final Module module = this;
Invokable operation = new Invokable() {
@Override
public Object invoke() {
try {
ServiceBuilderResources resources = new ServiceResourcesImpl(registry, module, def, proxyFactory, logger);
// Build up a stack of operations that will be needed to realize the service
// (by the proxy, at a later date).
ObjectCreator creator = def.createServiceCreator(resources);
// For non-proxyable services, we immediately create the service implementation
// and return it. There's no interface to proxy, which throws out the possibility of
// deferred instantiation, service lifecycles, and decorators.
ServiceLifecycle2 lifecycle = registry.getServiceLifecycle(def.getServiceScope());
if (!canBeProxied) {
if (lifecycle.requiresProxy())
throw new IllegalArgumentException(String.format("Service scope '%s' requires a proxy, but the service does not have a service interface (necessary to create a proxy). Provide a service interface or select a different service scope.", def.getServiceScope()));
return creator.createObject();
}
creator = new OperationTrackingObjectCreator(registry, String.format("Instantiating service %s implementation via %s", serviceId, creator), creator);
creator = new LifecycleWrappedServiceCreator(lifecycle, resources, creator);
// Marked services (or services inside marked modules) are not decorated.
// TapestryIOCModule prevents decoration of its services. Note that all decorators will decorate
// around the aspect interceptor, which wraps around the core service implementation.
boolean allowDecoration = !def.isPreventDecoration();
if (allowDecoration) {
creator = new AdvisorStackBuilder(def, creator, getAspectDecorator(), registry);
creator = new InterceptorStackBuilder(def, creator, registry);
}
// Add a wrapper that checks for recursion.
creator = new RecursiveServiceCreationCheckWrapper(def, creator, logger);
creator = new OperationTrackingObjectCreator(registry, "Realizing service " + serviceId, creator);
JustInTimeObjectCreator delegate = new JustInTimeObjectCreator(tracker, creator, serviceId);
Object proxy = createProxy(resources, delegate, def.isPreventDecoration());
registry.addRegistryShutdownListener(delegate);
if (def.isEagerLoad() && eagerLoadProxies != null)
eagerLoadProxies.add(delegate);
tracker.setStatus(serviceId, Status.VIRTUAL);
return proxy;
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException(IOCMessages.errorBuildingService(serviceId, def, ex), ex);
}
}
};
return registry.invoke(description, operation);
}
use of org.apache.tapestry5.ioc.Invokable in project tapestry-5 by apache.
the class OnEventWorker method createRequestBodyProvider.
@SuppressWarnings({ "unchecked", "rawtypes" })
private EventHandlerMethodParameterProvider createRequestBodyProvider(PlasticMethod method, final int parameterIndex, final String parameterTypeName, final boolean allowEmpty) {
final String methodIdentifier = method.getMethodIdentifier();
return (event) -> {
Invokable<Object> operation = () -> {
Class parameterType = classCache.forName(parameterTypeName);
Optional result = restSupport.getRequestBodyAs(parameterType);
if (!allowEmpty && !result.isPresent()) {
throw new RuntimeException(String.format("The request has an empty body and %s has one parameter with @RequestBody(allowEmpty=false)", methodIdentifier));
}
return result.orElse(null);
};
return operationTracker.invoke("Converting HTTP request body for @RequestBody parameter", operation);
};
}
use of org.apache.tapestry5.ioc.Invokable in project tapestry-5 by apache.
the class PersistenceContextSpecificEntityTransactionManager method invokeInTransaction.
public <T> T invokeInTransaction(Invokable<T> invokable) {
if (transactionBeingCommitted) {
// to be executed later
if (invokable instanceof VoidInvokable) {
invokableUnitsForSequentialTransactions.push(invokable);
return null;
} else {
rollbackTransaction(getTransaction());
throw new RuntimeException("Current transaction is already being committed. Transactions started @PostCommit are not allowed to return a value");
}
}
final boolean topLevel = invokableUnits.isEmpty();
invokableUnits.push(invokable);
if (!topLevel) {
if (logger.isWarnEnabled()) {
logger.warn("Nested transaction detected, current depth = " + invokableUnits.size());
}
}
final EntityTransaction transaction = getTransaction();
try {
T result = invokable.invoke();
if (topLevel && invokableUnits.peek().equals(invokable)) {
if (transaction.isActive()) {
invokeBeforeCommit(transaction);
}
if (transaction.isActive()) {
transactionBeingCommitted = true;
transaction.commit();
transactionBeingCommitted = false;
invokableUnits.clear();
invokeAfterCommit();
if (invokableUnitsForSequentialTransactions.size() > 0)
invokeInTransaction(invokableUnitsForSequentialTransactions.pop());
}
}
return result;
} catch (final RuntimeException e) {
if (transaction != null && transaction.isActive()) {
rollbackTransaction(transaction);
}
throw e;
} finally {
invokableUnits.remove(invokable);
}
}
use of org.apache.tapestry5.ioc.Invokable in project tapestry-5 by apache.
the class SpringModuleDef method createContributionToMasterObjectProvider.
private ContributionDef createContributionToMasterObjectProvider() {
ContributionDef def = new AbstractContributionDef() {
@Override
public String getServiceId() {
return "MasterObjectProvider";
}
@Override
public void contribute(ModuleBuilderSource moduleSource, ServiceResources resources, OrderedConfiguration configuration) {
final OperationTracker tracker = resources.getTracker();
final ApplicationContext context = resources.getService(SERVICE_ID, ApplicationContext.class);
final ObjectProvider springBeanProvider = new ObjectProvider() {
@Override
public <T> T provide(Class<T> objectType, AnnotationProvider annotationProvider, ObjectLocator locator) {
Map beanMap = context.getBeansOfType(objectType);
switch(beanMap.size()) {
case 0:
return null;
case 1:
Object bean = beanMap.values().iterator().next();
return objectType.cast(bean);
default:
String message = String.format("Spring context contains %d beans assignable to type %s: %s.", beanMap.size(), PlasticUtils.toTypeName(objectType), InternalUtils.joinSorted(beanMap.keySet()));
throw new IllegalArgumentException(message);
}
}
};
final ObjectProvider springBeanProviderInvoker = new ObjectProvider() {
@Override
public <T> T provide(final Class<T> objectType, final AnnotationProvider annotationProvider, final ObjectLocator locator) {
return tracker.invoke("Resolving dependency by searching Spring ApplicationContext", new Invokable<T>() {
@Override
public T invoke() {
return springBeanProvider.provide(objectType, annotationProvider, locator);
}
});
}
};
ObjectProvider outerCheck = new ObjectProvider() {
@Override
public <T> T provide(Class<T> objectType, AnnotationProvider annotationProvider, ObjectLocator locator) {
if (!applicationContextCreated.get())
return null;
return springBeanProviderInvoker.provide(objectType, annotationProvider, locator);
}
};
configuration.add("SpringBean", outerCheck, "after:AnnotationBasedContributions", "after:ServiceOverride");
}
};
return def;
}
Aggregations