[CONF] Apache Tapestry Injection FAQ

2011-02-21 Thread confluence







Injection FAQ
Page edited by Howard M. Lewis Ship


 Changes (15)
 




...
Main article: [Injection]  
h3. Whats the difference between the {{@Component}} and {{@InjectComponent}} annotations? 
 
The {{@Component}} annotation is used to define the _type_ of component, and its parameter bindings. When using {{@Component}}, the template must not define the type, and any parameter bindings are merged in: 
 {code:controls=true|linenumbers=true} 
...
Here the type of component is defined by the field type. The field name is matched against the {{t:id}} in the template. The {{page}} parameter is set in the Java class, and the informal {{class}} parameter is set in the template.  If the tag in the template was {{t:pagelink}}, or if the template tag included the attribute {{t:type=pagelink}}, then you would see an exception.  
By contrast, {{@InjectComponent}} expects the component to be already defined, and doesnt allow any configuration of it: 
 {code:controls=true|linenumbers=true} 
...
Again, were matching the field name to the component id, and you would get an error if the component is not defined in the template.  
h3. Whats the difference between the {{@InjectPage}} and {{@InjectContainer}} annotations? 
 
The {{@InjectPage}} annotation is used to inject some page in the application into a field of some other page.  You often see it used from event handler methods: 
 {code:controls=true|linenumbers=true} 
...
This code pattern is used to configure peristent properties of a page before returning it; Tapestry will send a client redirect to the page to present the data.  
{{@InjectContainer}} can be used inside a component or a mixin.  In a component, it injects the immediate container of the component; this is often the top-level page object. 
 In a mixin, it injects the component to which the mixin is attached. 
...
{code}  
The two marker annotations, {{@Traditional}} and {{@Primary}}, ensure that only a single service matches. 
 
h3. Whats the difference between {{@Inject}} and {{@Environmental}}? 
 
{{@Inject}} is relatively general; it can be used to inject resources specific to a page or component (such as ComponentResources, Logger, or Messages), or it can inject services or other objects obtained from the Tapestry IoC container.  Once the page is loaded, the values for these injections never change. 
 
{{@Environmental}} is different; it exposes a request-scoped, dynamically bound value{footnote}. The term Environmental was chosen as the value comes from the environment, whatever that means. A name more evocative of its function still has not occurred to the Tapestry team!{footnote}. 
 * Request scoped: different threads (processing different requests) will see different values when reading the field. 
...
Environmentals are a form of loosely connected communication between an outer component (or even a service) and an inner component.  Example: the Form component places a {{FormSupport}} object into the environment.  Other components, such as TextField, use the {{FormSupport}} when rendering to perform functions such as allocate unique control names or register client-side validations.  The TextField doesnt require that the Form component be the immediate container component, or even an ancestor: a Form on one page may, indirectly, communicate with a TextField on some entirely different page. Neither component directly links to the other, the {{FormSupport}} is the conduit that connects them.  
h3. I use @Inject on a field to inject a service, but the field is still null, what happened? 
h3. But wait ... I see I used the {{@Inject}} annotation and it still worked. What gives? 
 
This can happen when you use the wrong @Inject annotation; for example, com.google.inject.Inject instead of org.apache.tapestry5.ioc.annotations.Inject.  This can occur when you have TestNG on the classpath, for example, and your IDE is too helpful.  Double check your imports when things seem weird. 
In certain cases, Tapestry exposes a service (which can be injected) that is a proxy to the environmental; this is primarily for common environmentals, such as [_javascript_Support|http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/_javascript_/_javascript_Support.html], that may be needed outside of component classes.  You can see this in TapestryModule: 
 
{code:Java|title=TapestryModule.java (partial)} /**  * 

[CONF] Apache Tapestry Injection FAQ

2010-11-26 Thread confluence







Injection FAQ
Page edited by Howard M. Lewis Ship


 Changes (1)
 



...
Environmentals are a form of loosely connected communication between an outer component (or even a service) and an inner component.  Example: the Form component places a {{FormSupport}} object into the environment.  Other components, such as TextField, use the {{FormSupport}} when rendering to perform functions such as allocate unique control names or register client-side validations.  The TextField doesnt require that the Form component be the immediate container component, or even an ancestor: a Form on one page may, indirectly, communicate with a TextField on some entirely different page. Neither component directly links to the other, the {{FormSupport}} is the conduit that connects them.  
h3. I use @Inject on a field to inject a service, but the field is still null, what happened?  This can happend when you use the wrong @Inject annotation; for example, com.google.inject.Inject instead of org.apache.tapestry5.ioc.annotations.Inject.  This may happen when you have TestNG on the classpath, for example, and your IDE is too helpful.  Double check your imports when things seem weird.  
 {display-footnotes}  

Full Content

Injection

What's the difference between the Component and InjectComponent annotations?

The Component annotation is used to define the type of component, and its parameter bindings. When using Component, the template must not define the type, and any parameter bindings are merged in:



  a t:id="home" class="nav"Back to home/a





  @Component(parameters={ "page=index" })
  private PageLink home;



Here the type of component is defined by the field type. The field name is matched against the t:id in the template. The page parameter is set in the Java class, and the informal class parameter is set in the template.  If the tag in the template was t:pagelink, or if the template tag included the attribute t:type="pagelink", then you would see an exception.

By contrast, InjectComponent expects the component to be already defined, and doesn't allow any configuration of it:



  t:form t:id="login"  /t:form





  @InjectComponent
  private Form login;



Again, we're matching the field name to the component id, and you would get an error if the component is not defined in the template.

What's the difference between the InjectPage and InjectContainer annotations?

The InjectPage annotation is used to inject some page in the application into a field of some other page.  You often see it used from event handler methods:



  @InjectPage
  private ConfirmRegistration confirmRegistration;

  Object onSuccessFromRegistrationForm()
  {
confirmRegistration.setStatus("Registration accepted");
confirmRegistration.setValidationCode(userRegistrationData.getValidationCode());

return confirmRegistration;
  }



This code pattern is used to configure peristent properties of a page before returning it; Tapestry will send a client redirect to the page to present the data.

InjectContainer can be used inside a component or a mixin.  In a component, it injects the immediate container of the component; this is often the top-level page object.

In a mixin, it injects the component to which the mixin is attached.

I get an exception because I have two services with the same interface, how do I handle this?

It's not uncommon to have two or more services that implement the exact same interface. When you inject, you might start by just identifying the type of service to inject:



	@Inject
	private ComponentEventResultProcessor processor;



Which results in the error: Service interface org.apache.tapestry5.services.ComponentEventResultProcessor is matched by 3 services: AjaxComponentEventResultProcessor, ComponentEventResultProcessor, ComponentInstanceResultProcessor. Automatic dependency resolution requires that exactly one service implement the interface.

We need more information than just the service interface type in order to identify which of the three services to inject. One possibility is to inject with the correct service id:



	@InjectService("ComponentEventResultProcessor")
	private ComponentEventResultProcessor processor;



This works ... but it is clumsy. If the service id, "ComponentEventResultProcessor", ever changes, this code will break. It's not refactoring safe.

Instead, we should use marker annotations.  If we look at TapestryModule, where the ComponentEventResultProcessor service is defined, we'll see it identifies the necessary markers:



@Marker(
{ Primary.class, Traditional.class })
public ComponentEventResultProcessor buildComponentEventResultProcessor(
MapClass, ComponentEventResultProcessor configuration)
{
return 

[CONF] Apache Tapestry Injection FAQ

2010-09-03 Thread confluence







Injection FAQ
Page edited by Howard M. Lewis Ship


 Changes (1)
 



...
 {code} 
t:form t:id=login  /t:form} 
{code}  
...

Full Content

Injection

What's the difference between the Component and InjectComponent annotations?

The Component annotation is used to define the type of component, and its parameter bindings. When using Component, the template
must not define the type, and any parameter bindings are merged in:



  a t:id="home" class="nav"Back to home/a





  @Component(parameters={ "page=index" })
  private PageLink home;



Here the type of component is defined by the field type. The field name is matched against the t:id in the template. The page parameter
is set in the Java class, and the informal class parameter is set in the template.  If the tag in the template was t:pagelink,
or if the template tag included the attribute t:type="pagelink", then you would see an exception.

By contrast, InjectComponent expects the component to be already defined, and doesn't allow any configuration of it:



  t:form t:id="login"  /t:form





  @InjectComponent
  private Form login;



Again, we're matching the field name to the component id, and you would get an error if the component is not defined in the template.

What's the difference between the InjectPage and InjectContainer annotations?

The InjectPage annotation is used to inject some page in the application into a field of some other page.  You often see it used from event handler methods:



  @InjectPage
  private ConfirmRegistration confirmRegistration;

  Object onSuccessFromRegistrationForm()
  {
confirmRegistration.setStatus("Registration accepted");
confirmRegistration.setValidationCode(userRegistrationData.getValidationCode());

return confirmRegistration;
  }



This code pattern is used to configure peristent properties of a page before returning it; Tapestry will send a client redirect to the page to present
the data.

InjectContainer can be used inside a component or a mixin.  In a component, it injects the immediate container of the component; this is often the top-level page object.

In a mixin, it injects the component to which the mixin is attached.

I get an exception because I have two services with the same interface, how do I handle this?

It's not uncommon to have two or more services that implement the exact same interface. When you inject, you might start by just identifying the
type of service to inject:



	@Inject
	private ComponentEventResultProcessor processor;



Which results in the error: Service interface org.apache.tapestry5.services.ComponentEventResultProcessor is matched by 3 services: AjaxComponentEventResultProcessor, ComponentEventResultProcessor, ComponentInstanceResultProcessor. Automatic dependency resolution requires that exactly one service implement the interface.

We need more information than just the service interface type in order to identify which of the three services to inject. One possibility is to inject with the correct service id:



	@InjectService("ComponentEventResultProcessor")
	private ComponentEventResultProcessor processor;



This works ... but it is clumsy. If the service id, "ComponentEventResultProcessor", ever changes, this code will break. It's not refactoring safe.

Instead, we should use marker annotations.  If we look at TapestryModule, where the ComponentEventResultProcessor service is defined, we'll see it identifies the necessary markers:



@Marker(
{ Primary.class, Traditional.class })
public ComponentEventResultProcessor buildComponentEventResultProcessor(
MapClass, ComponentEventResultProcessor configuration)
{
return constructComponentEventResultProcessor(configuration);
}



When a service has marker annotations, the annotations present at the point of injection (the field, method parameter, or constructor parameter) are used to select a matching service.  The list of services that match by type is then filtered to only include services that have all of the marker annotations present at the point of injection.



@Inject
	@Traditional @Primary
	private ComponentEventResultProcessor processor;



The two marker annotations, Traditional and Primary, ensure that only a single service matches.

What's the difference between Inject and Environmental?

Inject is relatively general; it can be used to inject resources specific to a page or component (such as ComponentResources, Logger, or Messages), or it can inject services or other objects obtained from the Tapestry IoC container.  Once the page is loaded, the values for these injections never change.

Environmental is different; it exposes a request-scoped, dynamically bound value




1


.  


	

[CONF] Apache Tapestry Injection FAQ

2010-08-17 Thread confluence







Injection FAQ
Page  added by Howard M. Lewis Ship

 

 Injection

What's the difference between the Component and InjectComponent annotations?

The Component annotation is used to define the type of component, and its parameter bindings. When using Component, the template
must not define the type, and any parameter bindings are merged in:



  a t:id="home" class="nav"Back to home/a





  @Component(parameters={ "page=index" })
  private PageLink home;



Here the type of component is defined by the field type. The field name is matched against the t:id in the template. The page parameter
is set in the Java class, and the informal class parameter is set in the template.  If the tag in the template was t:pagelink,
or if the template tag included the attribute t:type="pagelink", then you would see an exception.

By contrast, InjectComponent expects the component to be already defined, and doesn't allow any configuration of it:



  t:form t:id="login"  /t:form}





  @InjectComponent
  private Form login;



Again, we're matching field name to component id, and you would get an error if the component is not defined in the template.

What's the difference between the InjectPage and InjectContainer annotations?

I get an exception because I have two services with the same interface, how do I handle this?

It's not uncommon to have two or more services that implement the exact same interface. When you inject, you might start by just identifying the
type of service to inject:



	@Inject
	private ComponentEventResultProcessor processor;



Which results in the error: Service interface org.apache.tapestry5.services.ComponentEventResultProcessor is matched by 3 services: AjaxComponentEventResultProcessor, ComponentEventResultProcessor, ComponentInstanceResultProcessor. Automatic dependency resolution requires that exactly one service implement the interface.

We need more information than just the service interface type in order to identify which of the three services to inject. One possibility is to inject with the correct service id:



	@InjectService("ComponentEventResultProcessor")
	private ComponentEventResultProcessor processor;



This works ... but it is clumsy. If the service id, "ComponentEventResultProcessor", ever changes, this code will break. It's not refactoring safe.

Instead, we should use marker annotations.  If we look at TapestryModule, where the ComponentEventResultProcessor service is defined, we'll see it identifies the necessary markers:



@Marker(
{ Primary.class, Traditional.class })
public ComponentEventResultProcessor buildComponentEventResultProcessor(
MapClass, ComponentEventResultProcessor configuration)
{
return constructComponentEventResultProcessor(configuration);
}



When a service has marker annotations, the annotations present at the point of injection (the field, method parameter, or constructor parameter) are used to select a matching service.  The list of services that match by type is then filtered to only include services that have all of the marker annotations present at the point of injection.



@Inject
	@Traditional @Primary
	private ComponentEventResultProcessor processor;



The two marker annotations, Traditional and Primary, ensure that only a single service matches.




   
Change Notification Preferences
   
   View Online
   








[CONF] Apache Tapestry Injection FAQ

2010-08-17 Thread confluence







Injection FAQ
Page edited by Howard M. Lewis Ship


 Changes (2)
 



...
{code}  
Again, were matching the field name to the component id, and you would get an error if the component is not defined in the template. 
 h3. Whats the difference between the {{InjectPage}} and {{InjectContainer}} annotations?  
The {{InjectPage}} annotation is used to inject some page in the application into a field of some other page.  You often see it used from event handler methods:  {code}   @InjectPage   private ConfirmRegistration confirmRegistration;Object onSuccessFromRegistrationForm()   { confirmRegistration.setStatus(Registration accepted); confirmRegistration.setValidationCode(userRegistrationData.getValidationCode());  return confirmRegistration;   } {code}  This code pattern is used to configure peristent properties of a page before returning it; Tapestry will send a client redirect to the page to present the data.  {{InjectContainer}} can be used inside a component or a mixin.  In a component, it injects the immediate container of the component; this is often the top-level page object.  In a mixin, it injects the component to which the mixin is attached.  
h3. I get an exception because I have two services with the same interface, how do I handle this?  
...

Full Content

Injection

What's the difference between the Component and InjectComponent annotations?

The Component annotation is used to define the type of component, and its parameter bindings. When using Component, the template
must not define the type, and any parameter bindings are merged in:



  a t:id="home" class="nav"Back to home/a





  @Component(parameters={ "page=index" })
  private PageLink home;



Here the type of component is defined by the field type. The field name is matched against the t:id in the template. The page parameter
is set in the Java class, and the informal class parameter is set in the template.  If the tag in the template was t:pagelink,
or if the template tag included the attribute t:type="pagelink", then you would see an exception.

By contrast, InjectComponent expects the component to be already defined, and doesn't allow any configuration of it:



  t:form t:id="login"  /t:form}





  @InjectComponent
  private Form login;



Again, we're matching the field name to the component id, and you would get an error if the component is not defined in the template.

What's the difference between the InjectPage and InjectContainer annotations?

The InjectPage annotation is used to inject some page in the application into a field of some other page.  You often see it used from event handler methods:



  @InjectPage
  private ConfirmRegistration confirmRegistration;

  Object onSuccessFromRegistrationForm()
  {
confirmRegistration.setStatus("Registration accepted");
confirmRegistration.setValidationCode(userRegistrationData.getValidationCode());

return confirmRegistration;
  }



This code pattern is used to configure peristent properties of a page before returning it; Tapestry will send a client redirect to the page to present
the data.

InjectContainer can be used inside a component or a mixin.  In a component, it injects the immediate container of the component; this is often the top-level page object.

In a mixin, it injects the component to which the mixin is attached.

I get an exception because I have two services with the same interface, how do I handle this?

It's not uncommon to have two or more services that implement the exact same interface. When you inject, you might start by just identifying the
type of service to inject:



	@Inject
	private ComponentEventResultProcessor processor;



Which results in the error: Service interface org.apache.tapestry5.services.ComponentEventResultProcessor is matched by 3 services: AjaxComponentEventResultProcessor, ComponentEventResultProcessor, ComponentInstanceResultProcessor. Automatic dependency resolution requires that exactly one service implement the interface.

We need more information than just the service interface type in order to identify which of the three services to inject. One possibility is to inject with the correct service id:



	@InjectService("ComponentEventResultProcessor")
	private ComponentEventResultProcessor processor;



This works ... but it is clumsy. If the service id, "ComponentEventResultProcessor", ever changes, this code will break. It's not refactoring safe.

Instead, we should use marker annotations.  If we look at TapestryModule, where the ComponentEventResultProcessor service is defined, we'll see it identifies the necessary markers:



@Marker(
{ Primary.class, Traditional.class })
public ComponentEventResultProcessor 

[CONF] Apache Tapestry Injection FAQ

2010-08-17 Thread confluence







Injection FAQ
Page edited by Howard M. Lewis Ship


 Changes (1)
 



...
 The two marker annotations, {{Traditional}} and {{Primary}}, ensure that only a single service matches. 
 h3. Whats the difference between {{Inject}} and {{Environmental}}?  {{Inject}} is relatively general; it can be used to inject resources specific to a page or component (such as ComponentResources, Logger, or Messages), or it can inject services or other objects obtained from the Tapestry IoC container.  Once the page is loaded, the values for these injections never change.  {{Environmental}} is different; it exposes a request-scoped, dynamically bound value{footnote}Environmental was chosen as the value comes from the environment, whatever that means. A name more evocative of its function still has not occurred to the Tapestry team!{footnote}.* Request scoped: different threads (processing different requests) will see different values when reading the field. * Dynamically bound: the value is explicitly placed into the Environment, and can be overridden at any time.Environmentals are a form of loosely connected communication between an outer component (or even a service) and an inner component.  Example: the Form component places a {{FormSupport}} object into the environment.  Other components, such as TextField, use the {{FormSupport}} when rendering to perform functions such as allocate unique control names or register client-side validations.  The TextField doesnt require that the Form component be the immediate container component, or even an ancestor: a Form on one page may, indirectly, communicate with a TextField on some entirely different page. Neither component directly links to the other, the {{FormSupport}} is the conduit that connects them.   {display-footnotes}  

Full Content

Injection

What's the difference between the Component and InjectComponent annotations?

The Component annotation is used to define the type of component, and its parameter bindings. When using Component, the template
must not define the type, and any parameter bindings are merged in:



  a t:id="home" class="nav"Back to home/a





  @Component(parameters={ "page=index" })
  private PageLink home;



Here the type of component is defined by the field type. The field name is matched against the t:id in the template. The page parameter
is set in the Java class, and the informal class parameter is set in the template.  If the tag in the template was t:pagelink,
or if the template tag included the attribute t:type="pagelink", then you would see an exception.

By contrast, InjectComponent expects the component to be already defined, and doesn't allow any configuration of it:



  t:form t:id="login"  /t:form}





  @InjectComponent
  private Form login;



Again, we're matching the field name to the component id, and you would get an error if the component is not defined in the template.

What's the difference between the InjectPage and InjectContainer annotations?

The InjectPage annotation is used to inject some page in the application into a field of some other page.  You often see it used from event handler methods:



  @InjectPage
  private ConfirmRegistration confirmRegistration;

  Object onSuccessFromRegistrationForm()
  {
confirmRegistration.setStatus("Registration accepted");
confirmRegistration.setValidationCode(userRegistrationData.getValidationCode());

return confirmRegistration;
  }



This code pattern is used to configure peristent properties of a page before returning it; Tapestry will send a client redirect to the page to present
the data.

InjectContainer can be used inside a component or a mixin.  In a component, it injects the immediate container of the component; this is often the top-level page object.

In a mixin, it injects the component to which the mixin is attached.

I get an exception because I have two services with the same interface, how do I handle this?

It's not uncommon to have two or more services that implement the exact same interface. When you inject, you might start by just identifying the
type of service to inject:



	@Inject
	private ComponentEventResultProcessor processor;



Which results in the error: Service interface org.apache.tapestry5.services.ComponentEventResultProcessor is matched by 3 services: AjaxComponentEventResultProcessor, ComponentEventResultProcessor, ComponentInstanceResultProcessor. Automatic dependency resolution requires that exactly one service implement the interface.

We need more information than just the service interface type in order to identify which of the three services to inject. One possibility is to inject with the correct service id:



	@InjectService("ComponentEventResultProcessor")
	private ComponentEventResultProcessor