Making a RemoteCommand programmatically

What is RemoteCommand

You can find a usage for PrimeFaces RemoteCommand on client side here. RemoteCommand is an implementation of UICommand in PrimeFaces library.

With RemoteCommand you can call a bean method as an ajax call from a client side component callback, for example onChange, onHide, onClick etc.

And in the following it is shown that how you can generate a RemoteCommand and join it to a component programmatically.



Required libraries

import java.util.Map;

import javax.el.MethodExpression;
import javax.faces.application.Application;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.event.MethodExpressionActionListener;

import org.primefaces.component.outputlabel.OutputLabel;
import org.primefaces.component.outputpanel.OutputPanel;
import org.primefaces.component.remotecommand.RemoteCommand;
import org.primefaces.component.selectcheckboxmenu.SelectCheckboxMenu;


RemoteCommand example

FacesContext fc = FacesContext.getCurrentInstance();
Application app = FacesContext.getCurrentInstance().getApplication();

// generate a SelectCheckboxMenu
SelectCheckboxMenu scm = (SelectCheckboxMenu) app.createComponent(SelectCheckboxMenu.COMPONENT_TYPE);
String scmId = "scmId";
scm.setId(scmId);
scm.setLabel("a caption..");
// call remote command named populateLabel from callback method 
// send the component id as a parameter to find the component at back-end 
scm.setOnHide("populateLabel([{name:'scmId', value:'" + scmId + "'}]);");

// prepare a remote command
RemoteCommand remoteCommand = new RemoteCommand();
remoteCommand.setName("populateLabel");
MethodExpression methodExpression = app.getExpressionFactory().createMethodExpression(
  fc.getELContext(), "#{myBean.populateLabelOnHide}", null, new Class<?>[]{Object.class});
remoteCommand.addActionListener(new MethodExpressionActionListener(methodExpression));
remoteCommand.setUpdate(":form:" + scmId);
remoteCommand.setProcess("@this form:" + scmId);

// make output label
OutputLabel outputLabel = (OutputLabel) app.createComponent(OutputLabel.COMPONENT_TYPE);
outputLabel.setValue("SCM label");
outputLabel.setFor(scmId);

// make an output panel and add components into it
OutputPanel panel = (OutputPanel) app.createComponent(OutputPanel.COMPONENT_TYPE);
panel.getChildren().add(scm);
panel.getChildren().add(remoteCommand);


Bean method

public void populateLabelOnHide(Object actionEvent) {
 // find select checkbox menu component id parameter
 FacesContext context = FacesContext.getCurrentInstance();
 Map<String, String> params = context.getExternalContext().getRequestParameterMap();
 String selectCheckboxMenuId = params.get("scmId");

 // find SelectCheckboxMenu component
 SelectCheckboxMenu scm = (SelectCheckboxMenu) findComponentRecursivelyById(selectCheckboxMenuId);

 // make an action on it
 scm.setLabel("Change the caption..");
}

You can findComponentRecursivelyById method here

Please check this also

Finding a jsf component in a FacesContext

Finding jsf components recursively by id



public UIComponent findComponentRecursivelyById(String id) {

 UIComponent result = null;
 UIComponent root = FacesContext.getCurrentInstance().getViewRoot();
 if (root != null) {
  result = findComponent(root, id);
 }

 return result;

}

private UIComponent findComponent(UIComponent root, String id) {

 UIComponent result = null;
 if (root.getId().equals(id))
  return root;

 for (UIComponent child : root.getChildren()) {
  if (child.getId().equals(id)) {
   result = child;
   break;
  }

  result = findComponent(child, id);

  if (result != null)
   break;
 }

 return result;
}

Programmatically add ajax behavior to SelectCheckboxMenu

How to add an ajax behavior to PrimeFaces SelectCheckboxMenu programmatically

You can find a simple example for SelectCheckboxMenu here and see how it looks like

Import required libraries

import javax.el.MethodExpression;
import javax.el.ValueExpression;
import javax.faces.application.Application;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.component.html.HtmlPanelGrid;
import javax.faces.context.FacesContext;
import javax.faces.event.AjaxBehaviorEvent;
import javax.faces.event.BehaviorEvent;

import org.primefaces.component.behavior.ajax.AjaxBehavior;
import org.primefaces.component.behavior.ajax.AjaxBehaviorListenerImpl;
import org.primefaces.component.message.Message;
import org.primefaces.component.outputlabel.OutputLabel;
import org.primefaces.component.outputpanel.OutputPanel;
import org.primefaces.component.selectcheckboxmenu.SelectCheckboxMenu;
import org.primefaces.event.ToggleSelectEvent;

Generate SelectCheckboxMenu and AjaxBehaviors dynamically

in the following code snippet you can find code examples regarding :

  • getting a component from xhtml page 
  • making a new jsf component
  • adding value expression into a component
  • generating method expression and join an ajax behavior to a component
  • adding a new component into the page


..
FacesContext facesContext = FacesContext.getCurrentInstance();
Application app = FacesContext.getCurrentInstance().getApplication();

// find a panel grid in xhtml file  
UIViewRoot root = facesContext.getViewRoot();
HtmlPanelGrid panelGrid = (HtmlPanelGrid) root.findComponent("form:myPanel");

// create HtmlSelectManyCheckbox
// in PrimeFaces there is an implementation for this component, SelectCheckboxMenu
SelectCheckboxMenu scm = (SelectCheckboxMenu) app
  .createComponent(SelectCheckboxMenu.COMPONENT_TYPE);
String scmId = "scmId";
scm.setId(scmId);

// add a value expression into SelectCheckboxMenu
String valueExpressionParamater = "test value";
ValueExpression valueExForScm = app.getExpressionFactory().createValueExpression(
  facesContext.getELContext(), "#{myBean.myMethod('" + valueExpressionParamater + "')}",
  Object.class);
scm.setValueExpression("value", valueExForScm);

// filtered mode
scm.setFilter(true);
scm.setFilterMatchMode("startsWith");
scm.setLabel("You can change label initially");

// prepare and add a method expression for toggleSelect method
MethodExpression methodExpression = app.getExpressionFactory().createMethodExpression(
  facesContext.getELContext(), "#{myBean.populateLabelOnToggleSelect}", null,
  new Class<?>[] { BehaviorEvent.class });
AjaxBehavior ajaxBehavior = (AjaxBehavior) facesContext.getApplication().createBehavior(
  AjaxBehavior.BEHAVIOR_ID);
ajaxBehavior.setUpdate("@this");
ajaxBehavior.setProcess("@this");
ajaxBehavior.addAjaxBehaviorListener(new AjaxBehaviorListenerImpl(methodExpression,
  methodExpression));
scm.addClientBehavior("toggleSelect", ajaxBehavior);

// prepare and add a method expression for change method
methodExpression = app.getExpressionFactory().createMethodExpression(facesContext.getELContext(), "#{myBean.populateLabelOnChange}", null,
  new Class<?>[] { BehaviorEvent.class });
ajaxBehavior = (AjaxBehavior) facesContext.getApplication().createBehavior(
  AjaxBehavior.BEHAVIOR_ID);
ajaxBehavior.setUpdate("@this");
ajaxBehavior.setProcess("@this");
ajaxBehavior.addAjaxBehaviorListener(new AjaxBehaviorListenerImpl(methodExpression,
  methodExpression));
scm.addClientBehavior("toggleSelect", ajaxBehavior);

// make an output label
OutputLabel outputLabel = (OutputLabel) app.createComponent(OutputLabel.COMPONENT_TYPE);
outputLabel.setValue("this caption initially overrides scm caption");
outputLabel.setFor(scmId);

// generate panel add components into it
OutputPanel panel = (OutputPanel) app.createComponent(OutputPanel.COMPONENT_TYPE);
Message message = (Message) app.createComponent(Message.COMPONENT_TYPE);
message.setFor(scmId);
panel.getChildren().add(scm);
panel.getChildren().add(message);

// add components into panel grid
panelGrid.getChildren().add(outputLabel);
panelGrid.getChildren().add(panel);

..

The following are bean methods called from ajax behaviors


public void populateLabelOnChange(AjaxBehaviorEvent event) {
 SelectCheckboxMenu scm = (SelectCheckboxMenu) event.getComponent();
 scm.setLabel("A new label set on change method");
}

public void populateLabelOnToggleSelect(ToggleSelectEvent event) {
 SelectCheckboxMenu scm = (SelectCheckboxMenu) event.getComponent();
 Object[] values = (Object[]) scm.getSubmittedValue();
 scm.setLabel(values.length + " items selected");
}

You can check this also to see making a remote command programmatically

Custom aspect with AspectJ


A simple custom @Around example   

Let's say that you want to catch exceptions and log some details or just swallow it. Also you don't want to touch classes and their structure in your project. So you need to write an around aspect. Just follow the following steps.

In this example, supposed that there is no spring configuration you have and your project as a maven project.

1) Add the following dependencies to your pom.xml

  <dependency>
   <groupId>com.jcabi</groupId>
   <artifactId>jcabi-aspects</artifactId>
   <version>0.20.1</version>
  </dependency>

  <dependency>
   <groupId>org.aspectj</groupId>
   <artifactId>aspectjrt</artifactId>
   <version>1.8.0</version>
  </dependency>  

2) Use the following maven plugin in your "pom.xml". This plugin executed at compile time and generate proxy classes into which your aspects injected. So class files generated with your advices.

<build>
  ..
  <plugins>
   <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>aspectj-maven-plugin</artifactId>
    <version>1.7</version>
    <configuration>
     <complianceLevel>1.6</complianceLevel>
     <encoding>${project.build.sourceEncoding}</encoding>
     <showWeaveInfo>true</showWeaveInfo>
     <source>1.6</source>
     <target>1.6</target>
     <verbose>true</verbose>
     <aspectLibraries>
      <aspectLibrary>
       <groupId>com.jcabi</groupId>
       <artifactId>jcabi-aspects</artifactId>
      </aspectLibrary>
     </aspectLibraries>
    </configuration>
    <executions>
     <execution>
      <id>weave-classes</id>
      <phase>process-classes</phase>
      <goals>
       <goal>compile</goal>
      </goals>
     </execution>
    </executions>
   </plugin>
  </plugins>
  ..
</build>


3) This is your exception handler with @Around annotation to swallow your exceptions


import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class MethodExceptionHandler {
 
 // "execution(* *(..))" means apply it for any modifier, any name, any arguments
 // "@annotation(Catchable)" means annotated with @Catchable
 @Around("execution(* *(..)) &amp;&amp; @annotation(Catchable)") 
 public void around(ProceedingJoinPoint point) {
  try {
   // do something here just before invoking
   point.proceed(); // invoke it
   // do something here just after invoking
  } catch (Throwable e) {
   // log exception details and swallow it
  }
 }
}

4) Use the following custom method level annotation

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Catchable {

}

5) Custom annotation in action


@Catchable
private void doSomething() {
   // do something here
}

That's all.


Notes

- You should prefer proxy or decorator pattern if it can be applied, it is a more efficient way 
- Also see here for already implemented useful aspects


@Async
@Cacheable
@Immutable
@LogExceptions
@Loggable
@Quietly
@Parallel
@RetryOnFailure
@ScheduleWithFixedDelay
@Timeable
@UnitedThrow