-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
INT-3297: Add @MessagingGateway
support
#1055
Closed
Closed
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
49 changes: 49 additions & 0 deletions
49
...egration-core/src/main/java/org/springframework/integration/annotation/GatewayHeader.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,49 @@ | |||
/* | |||
* Copyright 2014 the original author or authors. | |||
* | |||
* 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. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
|
|||
package org.springframework.integration.annotation; | |||
|
|||
import static java.lang.annotation.RetentionPolicy.RUNTIME; | |||
|
|||
import java.lang.annotation.Retention; | |||
import java.lang.annotation.Target; | |||
|
|||
/** | |||
* Provides the message header {@code value} or {@code expression}. | |||
* | |||
* @author Artem Bilan | |||
* @since 4.0 | |||
*/ | |||
@Target({ }) | |||
@Retention(RUNTIME) | |||
public @interface GatewayHeader { | |||
|
|||
/** | |||
* @return The name of the header. | |||
*/ | |||
String name(); | |||
|
|||
/** | |||
* @return The value for the header. | |||
*/ | |||
String value() default ""; | |||
|
|||
/** | |||
* @return The {@code Expression} to be evaluated to produce a value for the header. | |||
*/ | |||
String expression() default ""; | |||
|
|||
} |
64 changes: 64 additions & 0 deletions
64
...re/src/main/java/org/springframework/integration/annotation/IntegrationComponentScan.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,64 @@ | |||
/* | |||
* Copyright 2014 the original author or authors. | |||
* | |||
* 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. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
|
|||
package org.springframework.integration.annotation; | |||
|
|||
import java.lang.annotation.Documented; | |||
import java.lang.annotation.ElementType; | |||
import java.lang.annotation.Retention; | |||
import java.lang.annotation.RetentionPolicy; | |||
import java.lang.annotation.Target; | |||
|
|||
import org.springframework.context.annotation.Import; | |||
import org.springframework.integration.config.IntegrationComponentScanRegistrar; | |||
|
|||
/** | |||
* Configures component scanning directives for use with @{@link org.springframework.context.annotation.Configuration} classes. | |||
* Scan Spring Integration specific components. | |||
* | |||
* @author Artem Bilan | |||
* @since 4.0 | |||
*/ | |||
@Retention(RetentionPolicy.RUNTIME) | |||
@Target(ElementType.TYPE) | |||
@Documented | |||
@Import(IntegrationComponentScanRegistrar.class) | |||
public @interface IntegrationComponentScan { | |||
|
|||
/** | |||
* Alias for the {@link #basePackages()} attribute. | |||
* Allows for more concise annotation declarations e.g.: | |||
* {@code @ComponentScan("org.my.pkg")} instead of | |||
* {@code @ComponentScan(basePackages="org.my.pkg")}. | |||
*/ | |||
String[] value() default {}; | |||
|
|||
/** | |||
* Base packages to scan for annotated components. | |||
* <p>{@link #value()} is an alias for (and mutually exclusive with) this attribute. | |||
* <p>Use {@link #basePackageClasses()} for a type-safe alternative to String-based package names. | |||
*/ | |||
String[] basePackages() default {}; | |||
|
|||
/** | |||
* Type-safe alternative to {@link #basePackages()} for specifying the packages | |||
* to scan for annotated components. The package of each class specified will be scanned. | |||
* <p>Consider creating a special no-op marker class or interface in each package | |||
* that serves no purpose other than being referenced by this attribute. | |||
*/ | |||
Class<?>[] basePackageClasses() default {}; | |||
|
|||
} |
125 changes: 125 additions & 0 deletions
125
...ation-core/src/main/java/org/springframework/integration/annotation/MessagingGateway.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,125 @@ | |||
/* | |||
* Copyright 2014 the original author or authors. | |||
* | |||
* 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. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
|
|||
package org.springframework.integration.annotation; | |||
|
|||
import java.lang.annotation.Documented; | |||
import java.lang.annotation.ElementType; | |||
import java.lang.annotation.Retention; | |||
import java.lang.annotation.RetentionPolicy; | |||
import java.lang.annotation.Target; | |||
|
|||
/** | |||
* The stereotype annotation to provide the Integration Messaging Gateway Proxy ({@code <gateway/>}). | |||
* | |||
* @author Artem Bilan | |||
* @since 4.0 | |||
*/ | |||
@Target(ElementType.TYPE) | |||
@Retention(RetentionPolicy.RUNTIME) | |||
@Documented | |||
public @interface MessagingGateway { | |||
|
|||
/** | |||
* The value may indicate a suggestion for a logical component name, | |||
* to be turned into a Spring bean in case of an autodetected component. | |||
* | |||
* @return the suggested component name, if any | |||
*/ | |||
String name() default ""; | |||
|
|||
/** | |||
* Identifies default channel the messages will be sent to upon invocation of methods of the gateway proxy. | |||
* | |||
* @return the suggested channel name, if any | |||
*/ | |||
String defaultRequestChannel() default ""; | |||
|
|||
/** | |||
* Identifies default channel the gateway proxy will subscribe to to receive reply {@code Message}s, which will then be | |||
* converted to the return type of the method signature. | |||
* | |||
* @return the suggested channel name, if any | |||
*/ | |||
String defaultReplyChannel() default ""; | |||
|
|||
/** | |||
* Identifies a channel that error messages will be sent to if a failure occurs in the | |||
* gateway's proxy invocation. If no {@code errorChannel} reference is provided, the gateway will | |||
* propagate {@code Exception}s to the caller. To completely suppress {@code Exception}s, provide a | |||
* reference to the {@code nullChannel} here. | |||
* | |||
* @return the suggested channel name, if any | |||
*/ | |||
String errorChannel() default ""; | |||
|
|||
/** | |||
* Provides the amount of time dispatcher would wait to send a {@code Message}. | |||
* This timeout would only apply if there is a potential to block in the send call. | |||
* For example if this gateway is hooked up to a {@code QueueChannel}. | |||
* | |||
* @return the suggested timeout in milliseconds, if any | |||
*/ | |||
long defaultRequestTimeout() default Long.MIN_VALUE; | |||
|
|||
/** | |||
* Allows to specify how long this gateway will wait for the reply {@code Message} | |||
* before returning. By default it will wait indefinitely. {@code null} is returned | |||
if the gateway times out. | |||
* | |||
* @return the suggested timeout in milliseconds, if any | |||
*/ | |||
long defaultReplyTimeout() default Long.MIN_VALUE; | |||
|
|||
/** | |||
* Provide a reference to an implementation of {@link java.util.concurrent.Executor} | |||
* to use for any of the interface methods that have a {@link java.util.concurrent.Future} return type. | |||
* This {@code Executor} will only be used for those async methods; the sync methods | |||
* will be invoked in the caller's thread. | |||
* | |||
* @return the suggested executor bean name, if any | |||
*/ | |||
String asyncExecutor() default ""; | |||
|
|||
/** | |||
* An expression that will be used to generate the {@code payload} for all methods in the service interface | |||
* unless explicitly overridden by a method declaration. Variables include {@code #args}, {@code #methodName}, | |||
* {@code #methodString} and {@code #methodObject}; | |||
* a bean resolver is also available, enabling expressions like {@code @someBean(#args)}. | |||
* | |||
* @return the suggested payload expression, if any | |||
*/ | |||
String defaultPayloadExpression() default ""; | |||
|
|||
/** | |||
* Provides custom message headers. These default headers are created for | |||
* all methods on the service-interface (unless overridden by a specific method). | |||
* | |||
* @return the suggested payload expression, if any | |||
*/ | |||
GatewayHeader[] defaultHeaders() default {}; | |||
|
|||
/** | |||
* An {@link org.springframework.integration.gateway.MethodArgsMessageMapper} | |||
* to map the method arguments to a {@link org.springframework.messaging.Message}. When this | |||
* is provided, no {@code payload-expression}s or {@code header}s are allowed; the custom mapper is | |||
* responsible for creating the message. | |||
* | |||
* @return the suggested mapper bean name, if any | |||
*/ | |||
String mapper() default ""; | |||
|
|||
} |
108 changes: 108 additions & 0 deletions
108
...c/main/java/org/springframework/integration/config/IntegrationComponentScanRegistrar.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,108 @@ | |||
/* | |||
* Copyright 2014 the original author or authors. | |||
* | |||
* 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. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
|
|||
package org.springframework.integration.config; | |||
|
|||
import java.util.HashMap; | |||
import java.util.HashSet; | |||
import java.util.Map; | |||
import java.util.Set; | |||
|
|||
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; | |||
import org.springframework.beans.factory.config.BeanDefinition; | |||
import org.springframework.beans.factory.support.BeanDefinitionRegistry; | |||
import org.springframework.context.ResourceLoaderAware; | |||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; | |||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; | |||
import org.springframework.core.io.ResourceLoader; | |||
import org.springframework.core.type.AnnotationMetadata; | |||
import org.springframework.core.type.filter.AnnotationTypeFilter; | |||
import org.springframework.core.type.filter.TypeFilter; | |||
import org.springframework.integration.annotation.MessagingGateway; | |||
import org.springframework.util.ClassUtils; | |||
import org.springframework.util.StringUtils; | |||
|
|||
/** | |||
* {@link ImportBeanDefinitionRegistrar} implementation to scan and register Integration specific components. | |||
* | |||
* @author Artem Bilan | |||
* @since 4.0 | |||
*/ | |||
public class IntegrationComponentScanRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware { | |||
|
|||
private final Map<TypeFilter, ImportBeanDefinitionRegistrar> componentRegistrars = new HashMap<TypeFilter, ImportBeanDefinitionRegistrar>(); | |||
|
|||
private ResourceLoader resourceLoader; | |||
|
|||
public IntegrationComponentScanRegistrar() { | |||
this.componentRegistrars.put(new AnnotationTypeFilter(MessagingGateway.class), new MessagingGatewayRegistrar()); | |||
} | |||
|
|||
@Override | |||
public void setResourceLoader(ResourceLoader resourceLoader) { | |||
this.resourceLoader = resourceLoader; | |||
} | |||
|
|||
@Override | |||
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { | |||
Map<String, Object> componentScan = importingClassMetadata.getAnnotationAttributes("org.springframework.integration.annotation.IntegrationComponentScan"); | |||
|
|||
Set<String> basePackages = new HashSet<String>(); | |||
for (String pkg : (String[]) componentScan.get("value")) { | |||
if (StringUtils.hasText(pkg)) { | |||
basePackages.add(pkg); | |||
} | |||
} | |||
for (String pkg : (String[]) componentScan.get("basePackages")) { | |||
if (StringUtils.hasText(pkg)) { | |||
basePackages.add(pkg); | |||
} | |||
} | |||
for (Class<?> clazz : (Class[]) componentScan.get("basePackageClasses")) { | |||
basePackages.add(ClassUtils.getPackageName(clazz)); | |||
} | |||
|
|||
if (basePackages.isEmpty()) { | |||
basePackages.add(ClassUtils.getPackageName(importingClassMetadata.getClassName())); | |||
} | |||
|
|||
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false) { | |||
|
|||
@Override | |||
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { | |||
return beanDefinition.getMetadata().isIndependent(); | |||
} | |||
}; | |||
|
|||
for (TypeFilter typeFilter : componentRegistrars.keySet()) { | |||
scanner.addIncludeFilter(typeFilter); | |||
} | |||
|
|||
scanner.setResourceLoader(resourceLoader); | |||
|
|||
for (String basePackage : basePackages) { | |||
Set<BeanDefinition> candidateComponents = scanner.findCandidateComponents(basePackage); | |||
for (BeanDefinition candidateComponent : candidateComponents) { | |||
if (candidateComponent instanceof AnnotatedBeanDefinition) { | |||
for (ImportBeanDefinitionRegistrar importBeanDefinitionRegistrar : componentRegistrars.values()) { | |||
importBeanDefinitionRegistrar.registerBeanDefinitions(((AnnotatedBeanDefinition) candidateComponent).getMetadata(), registry); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
|
|||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM; except I wonder if we should add this...
...here. Without it, we get...
... which I suppose is fairly obvious, to those who understand what's happening, but perhaps the
Assert
would be more helpful to newbies?WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct. Thanks. Wouldn't you mind to do it on merge ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
However it should be in concrete
visitor
-MessagingGatewayRegistrar
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah - ok - will do during merge.