Skip to main content

Access Other Beans

In some cases, you may need to access other beans from within your current bean to perform actions or retrieve information. For example, consider a bean that implements a good-night routine, which closes covers, turns off all lights, and performs other tasks. If you want to trigger this routine by pressing a hardware button next to your bed, you would typically create a separate bean for the button and invoke the good-night routine from the original bean.

First, take a look at the good-night routine bean. It defines the method triggerRoutine(), which we want to invoke from the hardware button bean.

public class GoodNightRoutine implements SmartBean {

public void triggerRoutine() {
closeAllCovers();
turnOffAllLights();
}
}

Bean Proxy

You can access other bean instances through the SmartBeans API, which can be injected into your bean by declaring a field of type SmartBeans. This API provides the getBean() method in two variants. The first can be used when there is only one instance of the target bean by simply passing the Java class as a parameter. The second variant accepts the bean name as an additional parameter, as defined by the @SmartBeanDef annotation.

This method does not return the bean instance directly, but a BeanProxy object, which can be used to invoke methods on the target bean. The proxy is necessary because each bean runs in its own thread. To call a method of another bean, the execution must occur in the target bean's thread rather than in the calling bean's thread.

The BeanProxy handles this by executing the requested method in the target bean's thread and, if needed, returning the result to the calling bean's thread. Because of this threading model, you can invoke methods either synchronously or asynchronously. Synchronous calls block the calling bean's thread until the method completes, while asynchronous calls return immediately, with the method execution occurring shortly thereafter in the target bean's thread.

In our example, the good-night routine can be invoked asynchronously, which is preferred whenever possible to avoid unnecessary blocking. For synchronous execution, you can use the invokeSync() method as an alternative to invoke().

public class HardwareButton implements SmartBean {

private SmartBeans sb;

public void onButtonPressed() {
sb.getBean(GoodNightRoutine.class)
.invoke(GoodNightRoutine::triggerRoutine);
}
}

Returned Values

The invoke() method is used to call methods that do not return a value. If the method you want to call has a return value, use call() or callSync() instead. While callSync() returns the value directly, call() returns it as a BeanFuture object, similar to the standard Future in the Java core library.