Skip to content

Commit

Permalink
Merge pull request #99 from siglocpp/24671
Browse files Browse the repository at this point in the history
Adds support for multiple @RequestHandler
  • Loading branch information
hoegertn authored Jan 31, 2022
2 parents 6aa0151 + 6a382a5 commit d3436b1
Show file tree
Hide file tree
Showing 10 changed files with 327 additions and 108 deletions.
4 changes: 1 addition & 3 deletions interconnect/core/dvalin-interconnect-core.iml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
<component name="FacetManager">
<facet type="Spring" name="Spring">
<configuration>
<fileset id="fileset" name="Spring Application Context" removed="false">
<file>file://$MODULE_DIR$/src/main/resources/spring/messaging.xml</file>
</fileset>
<fileset id="fileset" name="Spring Application Context" removed="false" />
<fileset id="fileset2" name="Spring Application Context (2)" removed="false">
<file>file://$MODULE_DIR$/src/main/java/de/taimos/dvalin/interconnect/core/config/JMSConfig.java</file>
</fileset>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,14 @@
import de.taimos.dvalin.interconnect.core.daemon.DaemonRequestResponse;
import de.taimos.dvalin.interconnect.core.daemon.IDaemonRequestResponse;
import de.taimos.dvalin.interconnect.core.spring.DaemonMessageListener;
import de.taimos.dvalin.interconnect.core.spring.IDaemonMessageHandlerFactory;
import de.taimos.dvalin.interconnect.core.spring.IDaemonMessageSender;
import de.taimos.dvalin.interconnect.core.spring.SingleDaemonMessageHandler;
import de.taimos.dvalin.interconnect.model.service.ADaemonHandler;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.jms.pool.PooledConnectionFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
Expand Down Expand Up @@ -94,6 +99,13 @@ public IDaemonRequestResponse requestResponse() {
return new DaemonRequestResponse();
}

@Bean
public IDaemonMessageHandlerFactory createDaemonMessageHandlerFactory(BeanFactory beanFactory, IDaemonMessageSender messageSender) {
return logger -> {
final ADaemonHandler rh = (ADaemonHandler) beanFactory.getBean("requestHandler");
return new SingleDaemonMessageHandler(logger, rh.getClass(), messageSender, beanFactory);
};
}

@Bean
public DefaultMessageListenerContainer jmsListenerContainer(PooledConnectionFactory jmsFactory, DaemonMessageListener messageListener) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package de.taimos.dvalin.interconnect.core.config;

import de.taimos.daemon.spring.conditional.OnSystemProperty;
import de.taimos.dvalin.interconnect.core.spring.IDaemonMessageHandlerFactory;
import de.taimos.dvalin.interconnect.core.spring.IDaemonMessageSender;
import de.taimos.dvalin.interconnect.core.spring.MultiDaemonMessageHandler;
import de.taimos.dvalin.interconnect.core.spring.RequestHandler;
import de.taimos.dvalin.interconnect.model.service.IDaemonHandler;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import java.util.HashSet;
import java.util.Set;

/**
* Copyright 2022 Taimos GmbH<br>
* <br>
*
* @author psigloch
*/
@Configuration
@OnSystemProperty(propertyName = "interconnect.requesthandler.mode", propertyValue = "multi")
public class MultiRequestHandlerConfig {

@Bean
@Primary
public IDaemonMessageHandlerFactory createDaemonMessageHandlerFactory(ApplicationContext applicationContext, IDaemonMessageSender messageSender) {
return logger -> {
Set<Class<? extends IDaemonHandler>> handlers = new HashSet<>();
for (Object o : applicationContext.getBeansWithAnnotation(RequestHandler.class).values()) {
if (o instanceof IDaemonHandler) {
handlers.add(((IDaemonHandler) o).getClass());
}
}
return new MultiDaemonMessageHandler(logger, handlers, messageSender, applicationContext.getAutowireCapableBeanFactory());
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,9 @@
* #L%
*/

import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import javax.jms.Message;
import javax.jms.TextMessage;

import org.slf4j.Logger;

import de.taimos.dvalin.interconnect.core.InterconnectConnector;
import de.taimos.dvalin.interconnect.core.MessageConnector;
import de.taimos.dvalin.interconnect.core.daemon.DaemonMethodRegistry.RegistryEntry;
import de.taimos.dvalin.interconnect.model.InterconnectContext;
import de.taimos.dvalin.interconnect.model.InterconnectMapper;
import de.taimos.dvalin.interconnect.model.InterconnectObject;
Expand All @@ -45,47 +35,41 @@
import de.taimos.dvalin.interconnect.model.service.DaemonErrorNumber;
import de.taimos.dvalin.interconnect.model.service.DaemonScanner;
import de.taimos.dvalin.interconnect.model.service.IDaemonHandler;
import org.slf4j.Logger;

import javax.jms.Message;
import javax.jms.TextMessage;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.UUID;

/**
* Copyright 2015 Taimos GmbH<br>
* <br>
*
* @author Thorsten Hoeger
*/
public abstract class ADaemonMessageHandler {

final Map<Class<? extends InterconnectObject>, DaemonScanner.DaemonMethod> registry;
protected final DaemonMethodRegistry registry;

private final boolean throwExceptionOnTimeout;


/**
* @param aHandlerClazz Handler class
* @param aThrowExceptionOnTimeout if true throw Exception if timeout is reached
*/
public ADaemonMessageHandler(final Class<? extends IDaemonHandler> aHandlerClazz, final boolean aThrowExceptionOnTimeout) {
final Map<Class<? extends InterconnectObject>, DaemonScanner.DaemonMethod> reg = new HashMap<>();
for (final DaemonScanner.DaemonMethod re : DaemonScanner.scan(aHandlerClazz)) {
reg.put(re.getRequest(), re);
}
this.registry = Collections.unmodifiableMap(reg);
protected ADaemonMessageHandler(final Class<? extends IDaemonHandler> aHandlerClazz, final boolean aThrowExceptionOnTimeout) {
this.registry = new DaemonMethodRegistry(aHandlerClazz);
this.throwExceptionOnTimeout = aThrowExceptionOnTimeout;
}

/**
* @param aHandlerClazz Handler class
* @param aCatchExceptionsInRequestHandler if true Exceptions during execution are catched and returned as a DaemonError
* @param aThrowExceptionOnTimeout if true throw Exception if timeout is reached
* @deprecated use ADaemonMessageHandler(aHandlerClazz, aThrowExceptionOnTimeout) instead
*/
@Deprecated
public ADaemonMessageHandler(final Class<? extends IDaemonHandler> aHandlerClazz, @SuppressWarnings("unused") final boolean aCatchExceptionsInRequestHandler, final boolean aThrowExceptionOnTimeout) {
this(aHandlerClazz, aThrowExceptionOnTimeout);
}

/**
* @param aRegistry Registry
* @param aCatchExceptionsInRequestHandler if true Exceptions during execution are catched and returned as a DaemonError
* @param aThrowExceptionOnTimeout if true throw Exception if timeout is reached
* @deprecated use ADaemonMessageHandler(aHandlerClazz, aThrowExceptionOnTimeout) instead
* @param aHandlerClazzes Handler classes
* @param aThrowExceptionOnTimeout if true throw Exception if timeout is reached
*/
@Deprecated
public ADaemonMessageHandler(final Map<Class<? extends InterconnectObject>, DaemonScanner.DaemonMethod> aRegistry, @SuppressWarnings("unused") final boolean aCatchExceptionsInRequestHandler, final boolean aThrowExceptionOnTimeout) {
this.registry = Collections.unmodifiableMap(new HashMap<Class<? extends InterconnectObject>, DaemonScanner.DaemonMethod>(aRegistry));
protected ADaemonMessageHandler(final Collection<Class<? extends IDaemonHandler>> aHandlerClazzes, final boolean aThrowExceptionOnTimeout) {
this.registry = new DaemonMethodRegistry(aHandlerClazzes);
this.throwExceptionOnTimeout = aThrowExceptionOnTimeout;
}

Expand All @@ -102,8 +86,9 @@ public ADaemonMessageHandler(final Map<Class<? extends InterconnectObject>, Daem
* Create a new request handler.
*
* @return ADaemonHandler
* @param registryEntry
*/
protected abstract IDaemonHandler createRequestHandler();
protected abstract IDaemonHandler createRequestHandler(RegistryEntry registryEntry);

protected abstract Logger getLogger();

Expand All @@ -130,10 +115,11 @@ public final void onMessage(final Message message) throws Exception {
this.reply(new DaemonResponse(request, new PongIVO.PongIVOBuilder().build()), secure);
return;
}
final DaemonScanner.DaemonMethod method = this.registry.get(icoClass);
if (method == null) {
final RegistryEntry registryEntry = this.registry.get(icoClass);
if (registryEntry == null) {
throw new Exception("No registered method found for " + icoClass.getSimpleName() + " from " + message.getJMSReplyTo());
}
final DaemonScanner.DaemonMethod method = registryEntry.getMethod();
if (method.isSecure() != secure) {
throw new Exception("Insecure call (is " + secure + " should be " + method.isSecure() + ") for " + icoClass.getSimpleName() + " from " + message.getJMSReplyTo());
}
Expand Down Expand Up @@ -166,7 +152,7 @@ public final void onMessage(final Message message) throws Exception {
ivoClass = (Class<? extends IVO>) ivoIn.getClass();
InterconnectContext.setRequestClass(ivoClass);
}
final IDaemonHandler handler = this.createRequestHandler();
final IDaemonHandler handler = this.createRequestHandler(registryEntry);
final StringBuilder sbInvokeLog = new StringBuilder();
sbInvokeLog.append("Invoke ").append(method.getMethod().getName()).append("(").append(icoClass.getSimpleName()).append(")");
if (ivoIn instanceof IPageable) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Expand All @@ -20,13 +20,6 @@
* #L%
*/

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import de.taimos.dvalin.interconnect.model.InterconnectContext;
import de.taimos.dvalin.interconnect.model.InterconnectObject;
import de.taimos.dvalin.interconnect.model.ivo.daemon.VoidIVO;
Expand All @@ -35,6 +28,19 @@
import de.taimos.dvalin.interconnect.model.service.DaemonScanner;
import de.taimos.dvalin.interconnect.model.service.IDaemon;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
* Copyright 2015 Taimos GmbH<br>
* <br>
*
* @author Thorsten Hoeger
*/
public abstract class ADaemonProxyFactory implements IDaemonProxyFactory {

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package de.taimos.dvalin.interconnect.core.daemon;

import de.taimos.dvalin.interconnect.model.InterconnectObject;
import de.taimos.dvalin.interconnect.model.service.DaemonScanner;
import de.taimos.dvalin.interconnect.model.service.DaemonScanner.DaemonMethod;
import de.taimos.dvalin.interconnect.model.service.IDaemonHandler;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
* Copyright 2022 Taimos GmbH<br>
* <br>
*
* @author psigloch
*/
public class DaemonMethodRegistry {

private final Map<Class<? extends InterconnectObject>, RegistryEntry> registry;

/**
* @param aHandlerClazz the handler class
*/
public DaemonMethodRegistry(final Class<? extends IDaemonHandler> aHandlerClazz) {
final Map<Class<? extends InterconnectObject>, RegistryEntry> reg = new HashMap<>();
for (final DaemonScanner.DaemonMethod re : DaemonScanner.scan(aHandlerClazz)) {
reg.put(re.getRequest(), new RegistryEntry(aHandlerClazz, re));
}
this.registry = Collections.unmodifiableMap(reg);
}

/**
* @param aHandlerClazzes all handler classes
*/
public DaemonMethodRegistry(final Collection<Class<? extends IDaemonHandler>> aHandlerClazzes) {
final Map<Class<? extends InterconnectObject>, RegistryEntry> reg = new HashMap<>();
for (Class<? extends IDaemonHandler> aHandlerClazz : aHandlerClazzes) {
for (final DaemonScanner.DaemonMethod re : DaemonScanner.scan(aHandlerClazz)) {
reg.put(re.getRequest(), new RegistryEntry(aHandlerClazz, re));
}
}
this.registry = Collections.unmodifiableMap(reg);
}

/**
* @param icoClass the interconnect object class
* @return the registry entry
*/
public RegistryEntry get(Class<? extends InterconnectObject> icoClass) {
return this.registry.get(icoClass);
}

/**
* @param icoClass the interconnect object class
* @return the daemon method
*/
public DaemonMethod getMethod(Class<? extends InterconnectObject> icoClass) {
RegistryEntry registryEntry = this.registry.get(icoClass);
if (registryEntry == null) {
return null;
}
return registryEntry.getMethod();
}

public static class RegistryEntry {
private final Class<? extends IDaemonHandler> aHandlerClazz;
private final DaemonMethod method;

RegistryEntry(Class<? extends IDaemonHandler> aHandlerClazz, DaemonMethod method) {
this.aHandlerClazz = aHandlerClazz;
this.method = method;
}

/**
* @return the aHandlerClazz
*/
public Class<? extends IDaemonHandler> getHandlerClazz() {
return this.aHandlerClazz;
}

/**
* @return the method
*/
public DaemonMethod getMethod() {
return this.method;
}
}
}
Loading

0 comments on commit d3436b1

Please sign in to comment.