Errai 2.2.0.Final + Spring (RCP service example)
wendro Feb 7, 2013 5:40 PMIm used to spring over server side and I was unable to rewrite my apps to guice. I made myself a helper class which registers rcp services which are spring (3.1.3) beans to errai bus (2.2.0.Final).
@Component
public class ErraiApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
@InjectLogger
Logger logger;
boolean initialized = false;
public void onApplicationEvent(ContextRefreshedEvent event) {
if(!initialized) {
logger.info("Collecting beans...");
final List<Pair<Class<?>, Object>> beans = new ArrayList<Pair<Class<?>, Object>>();
for(Object type : event.getApplicationContext().getBeansWithAnnotation(org.jboss.errai.bus.server.annotations.Service.class).values()) {
for(Class<?> intf : type.getClass().getInterfaces()) {
if(intf.isAnnotationPresent(org.jboss.errai.bus.server.annotations.Remote.class)) {
logger.info("Found " + type.getClass().getName() + " bean with remote " + intf.getName() + ".");
beans.add(new Pair<Class<?>, Object>(intf, type));
}
}
}
logger.info("Collected " + beans.size() + " beans.");
ErraiServiceSingleton.registerInitCallback(new ErraiServiceSingleton.ErraiInitCallback() {
@Override
public void onInit(ErraiService service) {
logger.info("Registering " + beans.size() + " beans.");
for(Pair<Class<?>, Object> pair : beans) {
logger.info("Registering " + pair.getSecond().getClass().getName() + " bean with remote " + pair.getFirst().getName() + ".");
register(service, pair.getFirst(), pair.getSecond());
}
logger.info("Registered.");
}
});
}
}
/**
* Method produced based on @link{org.jboss.errai.bus.server.service.ServiceProcessor}.
*
* @param service
* @param remoteIntf
* @param type
*/
private void register(ErraiService service, final Class<?> remoteIntf, final Object svc) {
final ServerMessageBus bus = ErraiServiceSingleton.getService().getBus();
final ErraiServiceConfiguratorImpl config = (ErraiServiceConfiguratorImpl) ErraiServiceSingleton.getService().getConfiguration();
final Map<String, MessageCallback> epts = new HashMap<String, MessageCallback>();
// beware of classloading issues. better reflect on the actual instance
for (Class<?> intf : svc.getClass().getInterfaces()) {
for (final Method method : intf.getMethods()) {
if (RebindUtils.isMethodInInterface(remoteIntf, method)) {
epts.put(RebindUtils.createCallSignature(intf, method),
new ConversationalEndpointCallback(
new ServiceInstanceProvider() {
@Override
public Object get(Message message) {
return svc;
}
}, method, bus));
}
}
}
bus.subscribe(remoteIntf.getName() + ":RPC", new RemoteServiceCallback(epts));
// note: this method just exists because we want
// AbstractRemoteCallBuilder to be package private.
DefaultRemoteCallBuilder.setProxyFactory(Assert.notNull(new ProxyFactory() {
@Override
public <T> T getRemoteProxy(Class<T> proxyType) {
throw new RuntimeException("There is not yet an available Errai RPC implementation for the server-side environment.");
}
}));
}
}
Add this class to project where component scan will catch it. Then just add interface and service bean as you would with regular errai.
import org.jboss.errai.bus.server.annotations.Remote;
@Remote
public interface WorkflowService {
// ...
}
import org.jboss.errai.bus.server.annotations.Service;
@Component
@Service
public class WorkflowServiceImpl implements WorkflowService {
@Autowired
InternalCommonBean common;
// ...
}
Maybe someone will enjoy cheers...
If u leave me some I will start participating more.