DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

How does AI transform chaos engineering from an experiment into a critical capability? Learn how to effectively operationalize the chaos.

Data quality isn't just a technical issue: It impacts an organization's compliance, operational efficiency, and customer satisfaction.

Are you a front-end or full-stack developer frustrated by front-end distractions? Learn to move forward with tooling and clear boundaries.

Developer Experience: Demand to support engineering teams has risen, and there is a shift from traditional DevOps to workflow improvements.

Related

  • Designing Scalable Multi-Agent AI Systems: Leveraging Domain-Driven Design and Event Storming
  • How Node.js Works Behind the Scenes (HTTP, Libuv, and Event Emitters)
  • Event Driven Architecture (EDA) - Optimizer or Complicator
  • Event-Driven Microservices: How Kafka and RabbitMQ Power Scalable Systems

Trending

  • Scrum Smarter, Not Louder: AI Prompts Every Developer Should Steal
  • Build Your Private Cloud at Home
  • Top Trends for Data Streaming With Apache Kafka and Flink
  • Complete Guide: Managing Multiple GitHub Accounts on One System

How to Create Event Interceptors in JSF Composite Components

JSF composite components can be a powerful weapon when wielded properly. Learn how to get started using this great piece of tech!

By 
Antonio Sánchez user avatar
Antonio Sánchez
·
Oct. 02, 18 · Tutorial
Likes (4)
Comment
Save
Tweet
Share
8.8K Views

Join the DZone community and get the full member experience.

Join For Free

JSF composite components are one of the most interesting features we find when using JSF. They allow us to create new components in our application providing cohesion, defining common behavior, styles, and a better structure. It is a perfect way to make better and bigger apps easier.

Components Interface — Events

One of the most important sections in the component definition is the interface section. Within this section, we will define the way the component is revealed to a host page, a template, or even other components. In this section we'll decide how we interact with it, modifying its aspect or behavior.

We can define properties or methods, inject into some of the pieces of our composite, or define other properties or methods we use to modify our component in a more general way.

In this article, it is explained how we can control the events and methods defined in our components with event interceptors, allowing or preventing their execution based in some logic, acting as prehooks or posthooks on it. The idea is to refine component behavior, exposing a complex interface which allows pages to use the component with a full range of possibilities.

As an example, let's see a component definition...

<composite:interface>
  <composite:attributename="name"/>
  <composite:attributename="value"/>
  <composite:attributename="textForSubmit"/>
  <composite:attributename="registerActionListener"
      method-signature="void action(javax.faces.event.ActionEvent)"/>
[...]
<composite:interface>

<composite:implementation>
[...]
  <h:commandButton value="test" 
     actionListener="#{cc.attrs.registerActionListener}">
[...]
<composite:implementation>

The interface defines an event which will be invoked when the  h:commandButton defined in the implementation section invokes the action. In particular, the action listener is used.

In this case, the event in the parameter, registerAction, is defined when the component is instantiated in a page and is directly invoked by the h:commandButton when the button is clicked.

What We Want

We want to intercept the event defined in the interface of the component, execute our own component code before the instance code and after the instance code if needed.

In this way, we can add functionality to the component not only related to the composite components but to our defined component itself.

Let’s See How We Do It

We define the event in the backing bean of the component and this event is invoked from the definition.

<composite:interface>
  <composite:attributename="name"/>
  <composite:attributename="value"/>
  <composite:attributename="textForSubmit"/>
  <composite:attributename="registerActionListener"
      method-signature="void action(javax.faces.event.ActionEvent)"/>
  […]
<composite:interface>

<composite:implementation>
[...]
  <h:commandButton value="test" 
     action="#{cc.ourComponentEventInterceptor}">
[...]
<composite:implementation>


@FacesComponent(value="myComponent")
public class MyComponent {
[...]
public void preValidateHandlerAndInvocation(ActionEvent ae) {

  try {
      // Get method and arguments for listener defined in component.
      ContextualCompositeMethodExpression meth = (ContextualCompositeMethodExpression) this.getAttributes().get("registerAction");

      // My code prehook.
      [...]

      // Listener invocation.
      meth.invoke(FacesContext.getCurrentInstance().getELContext(), objs);

      // My code after invocation
      [...]
  } catch (Exceptions e) {
  LOGGER.log(Level.SEVERE, "Error when processing.", e);
         FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR,"error Message",null);
  FacesContext.getCurrentInstance().addMessage(this.getClientId(), msg);
  }
}
[...]
}

The event defined by the user is caught in the variable meth and invoked dynamically after the component code. This method could be invoked under certain conditions, so we can make the invocation completely conditional.

How can we prevent the execution of the instance event? We use AbortProcessingException to abort execution in any circumstances, or if we want or only invoke under certain conditions, we can invoke after verifications.

To communicate with the component from the backing bean we can use FacesMessage in the current FacesContext attached to our component and allow the page to re-update.

<ui:fragment rendered="#{(not empty facesContext.getMessageList(cc.clientId) and 
not empty facesContext.getMessageList(cc.clientId).get(0).getSummary()}">
  [Renders error message]
</ui:fragment>

Why Don't We use an Action Listener to Hook an Event and Publish an Action to Instance Defined Events?

As per their definition, action events are used when the action on the component provokes navigation on the Faces navigation defined in the faces-config.xml file (or direct URL redirection). In so many cases, this is not the goal of a button in an AJAX application, where some actions only update some parts of the page as a result of an interaction. In this case, an action with an empty String is returned as result of an action.

The actionListener is used to prehook an event as we are doing here. But our goal is to allow the component actionlistener to be used in component instances.

This can happen, usually, if we use third party components where the actionListener has a special importance (by example the fileUpload event in a primefaces component). If we want to prehook those events as composite components and also be able to publish in the interface, we need an approach like this one.

Why Do We Not Use a Validator?

Validation is a specific functionality in JSF that can prevent an event execution or form submission based on data validation. These validators are executed in an earlier stage of the JSF lifecycle. So, it is something completely different and not related to our purpose. 

Conclusions

With the goal of obtaining better, complex ,and more specific components to our libraries or applications, this approach can help us to add some functionalities such as logging, audits, and behavior control, thus allowing us to adapt our components more precisely to our requirements, moving logic from the use of the component to the definition of the component itself. I think this can be useful in so many cases and, of course, if we use components for more than creating 'templates' to include in our pages.

Event

Opinions expressed by DZone contributors are their own.

Related

  • Designing Scalable Multi-Agent AI Systems: Leveraging Domain-Driven Design and Event Storming
  • How Node.js Works Behind the Scenes (HTTP, Libuv, and Event Emitters)
  • Event Driven Architecture (EDA) - Optimizer or Complicator
  • Event-Driven Microservices: How Kafka and RabbitMQ Power Scalable Systems

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • [email protected]

Let's be friends: