Search in sources :

Example 21 with Parameter

use of org.apache.tapestry5.annotations.Parameter in project tapestry-5 by apache.

the class TapestryModule method provideTransformWorkers.

/**
 * Adds a number of standard component class transform workers:
 * <dl>
 * <dt>Parameter</dt>
 * <dd>Identifies parameters based on the {@link org.apache.tapestry5.annotations.Parameter} annotation</dd>
 * <dt>BindParameter</dt>
 * <dd>Support for the {@link BindParameter} annotation</dd>
 * <dt>Property</dt>
 * <dd>Generates accessor methods if {@link org.apache.tapestry5.annotations.Property} annotation is present</dd>
 * <dt>Import</dt>
 * <dd>Supports the {@link Import} annotation</dd>
 * <dt>UnclaimedField</dt>
 * <dd>Manages unclaimed fields, storing their value in a {@link PerThreadValue}</dd>
 * <dt>OnEvent</dt>
 * <dd>Handle the @OnEvent annotation, and related naming convention</dd>
 * <dt>RenderCommand</dt>
 * <dd>Ensures all components also implement {@link org.apache.tapestry5.runtime.RenderCommand}</dd>
 * <dt>SupportsInformalParameters</dt>
 * <dd>Checks for the annotation</dd>
 * <dt>RenderPhase</dt>
 * <dd>Link in render phase methods</dd>
 * <dt>Retain</dt>
 * <dd>Allows fields to retain their values between requests</dd>
 * <dt>Meta</dt>
 * <dd>Checks for meta data annotations and adds it to the component model</dd>
 * <dt>PageActivationContext</dt> <dd>Support for {@link PageActivationContext} annotation</dd>
 * <dt>DiscardAfter</dt> <dd>Support for {@link DiscardAfter} method annotation </dd>
 * <dt>MixinAfter</dt> <dd>Support for the {@link MixinAfter} mixin class annotation</dd>
 * <dt>PageReset</dt>
 * <dd>Checks for the {@link PageReset} annotation</dd>
 * <dt>Mixin</dt>
 * <dd>Adds a mixin as part of a component's implementation</dd>
 * <dt>Cached</dt>
 * <dd>Checks for the {@link org.apache.tapestry5.annotations.Cached} annotation</dd>
 * <dt>ActivationRequestParameter</dt>
 * <dd>Support for the {@link ActivationRequestParameter} annotation</dd>
 * <dt>PageLoaded, PageAttached, PageDetached</dt>
 * <dd>Support for annotations {@link PageLoaded}, {@link PageAttached}, {@link PageDetached}</dd>
 * <dt>InjectService</dt>
 * <dd>Handles the {@link org.apache.tapestry5.ioc.annotations.InjectService} annotation</dd>
 * <dt>Component</dt>
 * <dd>Defines embedded components based on the {@link org.apache.tapestry5.annotations.Component} annotation</dd>
 * <dt>Environment</dt>
 * <dd>Allows fields to contain values extracted from the {@link org.apache.tapestry5.services.Environment} service</dd>
 * <dt>ApplicationState</dt>
 * <dd>Converts fields that reference application state objects</dd>
 * <dt>Persist</dt>
 * <dd>Allows fields to store their their value persistently between requests via {@link Persist}</dd>
 * <dt>SessionAttribute</dt>
 * <dd>Support for the {@link SessionAttribute}</dd>
 * <dt>Log</dt>
 * <dd>Checks for the {@link org.apache.tapestry5.annotations.Log} annotation</dd>
 * <dt>HeartbeatDeferred
 * <dd>Support for the {@link HeartbeatDeferred} annotation, which defers method invocation to the end of the {@link Heartbeat}
 * <dt>Inject</dt>
 * <dd>Used with the {@link org.apache.tapestry5.ioc.annotations.Inject} annotation, when a value is supplied</dd>
 * <dt>Operation</dt> <dd>Support for the {@link Operation} method annotation</dd>
 * </dl>
 */
@Contribute(ComponentClassTransformWorker2.class)
@Primary
public static void provideTransformWorkers(OrderedConfiguration<ComponentClassTransformWorker2> configuration, MetaWorker metaWorker, ComponentClassResolver resolver) {
    configuration.add("Property", new PropertyWorker());
    // Order this one pretty early:
    configuration.addInstance("Operation", OperationWorker.class);
    configuration.add("RenderCommand", new RenderCommandWorker());
    configuration.addInstance("OnEvent", OnEventWorker.class);
    configuration.add("MixinAfter", new MixinAfterWorker());
    // These must come after Property, since they actually delete fields
    // that may still have the annotation
    configuration.addInstance("ApplicationState", ApplicationStateWorker.class);
    configuration.addInstance("Environment", EnvironmentalWorker.class);
    configuration.add("Component", new ComponentWorker(resolver));
    configuration.add("Mixin", new MixinWorker(resolver));
    configuration.addInstance("InjectPage", InjectPageWorker.class);
    configuration.addInstance("InjectComponent", InjectComponentWorker.class);
    configuration.addInstance("InjectContainer", InjectContainerWorker.class);
    // Default values for parameters are often some form of injection, so
    // make sure that Parameter fields are processed after injections.
    configuration.addInstance("Parameter", ParameterWorker.class);
    // bind parameter should always go after parameter to make sure all
    // parameters have been properly setup.
    configuration.addInstance("BindParameter", BindParameterWorker.class);
    configuration.add("SupportsInformalParameters", new SupportsInformalParametersWorker());
    configuration.addInstance("RenderPhase", RenderPhaseMethodWorker.class);
    // Import advises methods, usually render phase methods, so it must come after RenderPhase.
    configuration.addInstance("Import", ImportWorker.class);
    configuration.add("Meta", metaWorker.getWorker());
    configuration.add("Retain", new RetainWorker());
    configuration.add("PageActivationContext", new PageActivationContextWorker());
    configuration.addInstance("ActivationRequestParameter", ActivationRequestParameterWorker.class);
    configuration.addInstance("Cached", CachedWorker.class);
    configuration.addInstance("DiscardAfter", DiscardAfterWorker.class);
    add(configuration, PageLoaded.class, TransformConstants.CONTAINING_PAGE_DID_LOAD_DESCRIPTION);
    add(configuration, PageAttached.class, TransformConstants.CONTAINING_PAGE_DID_ATTACH_DESCRIPTION);
    add(configuration, PageDetached.class, TransformConstants.CONTAINING_PAGE_DID_DETACH_DESCRIPTION);
    configuration.addInstance("PageReset", PageResetAnnotationWorker.class);
    configuration.addInstance("InjectService", InjectServiceWorker.class);
    configuration.addInstance("Inject", InjectWorker.class);
    configuration.addInstance("Persist", PersistWorker.class);
    configuration.addInstance("SessionAttribute", SessionAttributeWorker.class);
    configuration.addInstance("Log", LogWorker.class);
    configuration.addInstance("HeartbeatDeferred", HeartbeatDeferredWorker.class);
    // This one is always last. Any additional private fields that aren't
    // annotated will
    // be converted to clear out at the end of the request.
    configuration.addInstance("UnclaimedField", UnclaimedFieldWorker.class, "after:*");
}
Also used : PageActivationContextWorker(org.apache.tapestry5.internal.transform.PageActivationContextWorker) PropertyWorker(org.apache.tapestry5.internal.transform.PropertyWorker) MixinWorker(org.apache.tapestry5.internal.transform.MixinWorker) RetainWorker(org.apache.tapestry5.internal.transform.RetainWorker) ComponentWorker(org.apache.tapestry5.internal.transform.ComponentWorker) InjectComponentWorker(org.apache.tapestry5.internal.transform.InjectComponentWorker) RenderCommandWorker(org.apache.tapestry5.internal.transform.RenderCommandWorker) SupportsInformalParametersWorker(org.apache.tapestry5.internal.transform.SupportsInformalParametersWorker) MixinAfterWorker(org.apache.tapestry5.internal.transform.MixinAfterWorker) Primary(org.apache.tapestry5.ioc.annotations.Primary) Contribute(org.apache.tapestry5.ioc.annotations.Contribute)

Example 22 with Parameter

use of org.apache.tapestry5.annotations.Parameter in project tapestry-5 by apache.

the class StrategyBuilderImpl method createProxy.

private <S> S createProxy(final Class<S> interfaceType, final StrategyRegistry<S> registry) {
    ClassInstantiator instantiator = proxyFactory.createProxy(interfaceType, new PlasticClassTransformer() {

        @Override
        public void transform(PlasticClass plasticClass) {
            final PlasticField registryField = plasticClass.introduceField(StrategyRegistry.class, "registry").inject(registry);
            Class<?> interfaceSelectorType = null;
            for (final Method method : interfaceType.getMethods()) {
                Class<?>[] parameterTypes = method.getParameterTypes();
                if (parameterTypes.length == 0) {
                    throw new IllegalArgumentException("Invalid method " + method + ", when using the strategy pattern, every method must take at least the selector as its parameter");
                }
                Class<?> methodSelectorType = parameterTypes[0];
                if (interfaceSelectorType == null) {
                    interfaceSelectorType = methodSelectorType;
                } else if (!interfaceSelectorType.equals(methodSelectorType)) {
                    throw new IllegalArgumentException("Conflicting method definitions," + " expecting the first argument of every method to have the same type");
                }
                plasticClass.introduceMethod(new MethodDescription(method), new InstructionBuilderCallback() {

                    @Override
                    public void doBuild(InstructionBuilder builder) {
                        Class returnType = method.getReturnType();
                        builder.loadThis().getField(registryField);
                        // Argument 0 is the selector used to find the adapter and should be an object reference,
                        // not a primitive.
                        builder.loadArgument(0);
                        // Use the StrategyRegistry to get the adapter to re-invoke the method on
                        builder.invoke(StrategyRegistry.class, Object.class, "getByInstance", Object.class).checkcast(interfaceType);
                        // That leaves the correct adapter on top of the stack. Get the
                        // selector and the rest of the arguments in place and invoke the method.
                        builder.loadArguments().invoke(interfaceType, returnType, method.getName(), method.getParameterTypes());
                        builder.returnResult();
                    }
                });
            }
            plasticClass.addToString(String.format("<Strategy for %s>", interfaceType.getName()));
        }
    });
    return interfaceType.cast(instantiator.newInstance());
}
Also used : PlasticClass(org.apache.tapestry5.plastic.PlasticClass) InstructionBuilder(org.apache.tapestry5.plastic.InstructionBuilder) ClassInstantiator(org.apache.tapestry5.plastic.ClassInstantiator) StrategyRegistry(org.apache.tapestry5.commons.util.StrategyRegistry) MethodDescription(org.apache.tapestry5.plastic.MethodDescription) Method(java.lang.reflect.Method) PlasticClassTransformer(org.apache.tapestry5.plastic.PlasticClassTransformer) PlasticField(org.apache.tapestry5.plastic.PlasticField) PlasticClass(org.apache.tapestry5.plastic.PlasticClass) InstructionBuilderCallback(org.apache.tapestry5.plastic.InstructionBuilderCallback)

Example 23 with Parameter

use of org.apache.tapestry5.annotations.Parameter in project tapestry-5 by apache.

the class ComponentAssemblerImpl method createEmbeddedAssembler.

public EmbeddedComponentAssembler createEmbeddedAssembler(String embeddedId, String componentClassName, EmbeddedComponentModel embeddedModel, String mixins, Location location) {
    try {
        if (InternalUtils.isBlank(componentClassName)) {
            throw new TapestryException("You must specify the type via t:type, the element, or @Component annotation.", location, null);
        }
        EmbeddedComponentAssemblerImpl embedded = new EmbeddedComponentAssemblerImpl(assemblerSource, instantiatorSource, componentClassResolver, componentClassName, getSelector(), embeddedModel, mixins, location, strictMixinParameters);
        if (embeddedIdToAssembler == null)
            embeddedIdToAssembler = CollectionFactory.newMap();
        embeddedIdToAssembler.put(embeddedId, embedded);
        if (embeddedModel != null) {
            for (String publishedParameterName : embeddedModel.getPublishedParameters()) {
                if (publishedParameterToEmbeddedId == null)
                    publishedParameterToEmbeddedId = CollectionFactory.newCaseInsensitiveMap();
                String existingEmbeddedId = publishedParameterToEmbeddedId.get(publishedParameterName);
                if (existingEmbeddedId != null) {
                    throw new TapestryException(String.format("Parameter '%s' of embedded component '%s' can not be published as a parameter of component %s, as it has previously been published by embedded component '%s'.", publishedParameterName, embeddedId, instantiator.getModel().getComponentClassName(), existingEmbeddedId), location, null);
                }
                publishedParameterToEmbeddedId.put(publishedParameterName, embeddedId);
            }
        }
        return embedded;
    } catch (Exception ex) {
        throw new TapestryException(String.format("Failure creating embedded component '%s' of %s: %s", embeddedId, instantiator.getModel().getComponentClassName(), ExceptionUtils.toMessage(ex)), location, ex);
    }
}
Also used : TapestryException(org.apache.tapestry5.commons.internal.util.TapestryException) TapestryException(org.apache.tapestry5.commons.internal.util.TapestryException)

Example 24 with Parameter

use of org.apache.tapestry5.annotations.Parameter in project tapestry-5 by apache.

the class EmbeddedComponentAssemblerImpl method createParameterBinderFromQualifiedParameterName.

private ParameterBinder createParameterBinderFromQualifiedParameterName(String qualifiedParameterName, String mixinId, String parameterName) {
    if (mixinId.equalsIgnoreCase(componentPsuedoMixinId)) {
        return createParameterBinderForComponent(qualifiedParameterName, parameterName);
    }
    if (!mixinIdToInstantiator.containsKey(mixinId)) {
        throw new TapestryException(String.format("Mixin id for parameter '%s' not found. Attached mixins: %s.", qualifiedParameterName, InternalUtils.joinSorted(mixinIdToInstantiator.keySet())), location, null);
    }
    ParameterBinder binder = parameterNameToBinder.get(qualifiedParameterName);
    if (binder != null) {
        return binder;
    }
    // Ok, so perhaps this is a qualified name for an informal parameter of the mixin.
    Instantiator instantiator = mixinIdToInstantiator.get(mixinId);
    assert instantiator != null;
    return bindInformalParameter(qualifiedParameterName, mixinId, parameterName, instantiator.getModel());
}
Also used : Instantiator(org.apache.tapestry5.internal.services.Instantiator) TapestryException(org.apache.tapestry5.commons.internal.util.TapestryException)

Example 25 with Parameter

use of org.apache.tapestry5.annotations.Parameter in project tapestry-5 by apache.

the class ComponentEventImplTest method unable_to_coerce.

@Test
public void unable_to_coerce() {
    ComponentEventCallback handler = mockComponentEventHandler();
    EventContext context = mockEventContext();
    ComponentPageElementResources resources = mockComponentPageElementResources();
    Logger logger = mockLogger();
    ComponentModel model = mockComponentModel();
    train_isDebugEnabled(logger, true);
    logger.debug(eq(TapestryMarkers.EVENT_HANDLER_METHOD), isA(String.class));
    train_toClass(resources, Integer.class.getName(), Integer.class);
    train_getCount(context, 1);
    expect(context.get(Integer.class, 0)).andThrow(new NumberFormatException("Not so easy, is it?"));
    replay();
    ComponentEvent event = new ComponentEventImpl("eventType", "someId", context, handler, resources, false, model, logger);
    event.setMethodDescription("foo.Bar.baz()");
    try {
        event.coerceContext(0, "java.lang.Integer");
        unreachable();
    } catch (IllegalArgumentException ex) {
        // Different JVMs will report the conversion error slightly differently,
        // so we don't try to check that part of the error message.
        assertTrue(ex.getMessage().startsWith("Exception in method foo.Bar.baz(), parameter #1:"));
    }
    verify();
}
Also used : EventContext(org.apache.tapestry5.EventContext) ComponentModel(org.apache.tapestry5.model.ComponentModel) ComponentPageElementResources(org.apache.tapestry5.internal.structure.ComponentPageElementResources) ComponentEvent(org.apache.tapestry5.runtime.ComponentEvent) Logger(org.slf4j.Logger) ComponentEventCallback(org.apache.tapestry5.ComponentEventCallback) Test(org.testng.annotations.Test)

Aggregations

TapestryException (org.apache.tapestry5.commons.internal.util.TapestryException)12 UnknownValueException (org.apache.tapestry5.commons.util.UnknownValueException)6 MutableComponentModel (org.apache.tapestry5.model.MutableComponentModel)6 RequestParameter (org.apache.tapestry5.annotations.RequestParameter)5 JSONObject (org.apache.tapestry5.json.JSONObject)5 ComponentEvent (org.apache.tapestry5.runtime.ComponentEvent)5 InternalComponentResources (org.apache.tapestry5.internal.InternalComponentResources)4 Test (org.testng.annotations.Test)4 Binding (org.apache.tapestry5.Binding)3 ComponentResources (org.apache.tapestry5.ComponentResources)3 ActivationContextParameter (org.apache.tapestry5.annotations.ActivationContextParameter)3 Location (org.apache.tapestry5.commons.Location)3 Resource (org.apache.tapestry5.commons.Resource)3 AvailableValues (org.apache.tapestry5.commons.util.AvailableValues)3 LiteralBinding (org.apache.tapestry5.internal.bindings.LiteralBinding)3 Logger (org.slf4j.Logger)3 Method (java.lang.reflect.Method)2 Parameter (java.lang.reflect.Parameter)2 EventContext (org.apache.tapestry5.EventContext)2 ValueEncoder (org.apache.tapestry5.ValueEncoder)2