Page 1 of 2 12 LastLast
Results 1 to 10 of 14

Thread: ServiceActivator and SpEL to determine if endpoint should be handled

  1. #1

    Default ServiceActivator and SpEL to determine if endpoint should be handled

    My scenario is having a channel that puts through several types of events. Many of the events are different by class type of the event object, some have event type enums inside of them. I would like to have a "service activator allowing" capability that allows me to use ServiceActivator but attach a SpEL expression to determine if that annotated method should fire for a specific message.

    Is there an easy-to-configure way to allow message endpoints to be conditionally activated based on a spring expression (that access the payload and headers)?

    Sort of like.... @ServiceActivator(inputChannel="myEventChannel" allowExpression="#{payload instanceof T(myapp.EventType1)}")

    or

    allowExpression="#{payload.myEventTypeProperty == MyEventType.EVENT_TYPE_ENUM_RESET}".

    Anyway to do this easily?

    I see I can filter using a SpEL but then I have to dump the message to a channel and have a service activator listen on that channel which is alot more configuration work.

  2. #2

    Default

    As an added note, I realize that I could create another channel and use an expression router or an ExpressionSelectingSelector to create the channel in configuration. Then just subscribe to that channel using @ServiceActivator or outbound-channel-adapter. I am looking for an annotation driven expression on @SerivceActivator that creates such a channel like the input-channel then really subscribes to that secretly derived channel. That new channel would be shared between all activators that use the exact same expression e.g. the new channel name is a hash of the expression.

    Anything like this already exist or is there a better way?

  3. #3
    Join Date
    Jan 2008
    Location
    Mohnton, PA USA (that's near Philadelphia)
    Posts
    2,148

    Default

    Selector/Filter/Router should be the approach.
    Remember, channel is just a connector (pipe) between two endpoints (Filters) and gives you that loosely coupled assembly model that other frameworks do not provide.
    Routing, filtering etc., is an integration concern which you are trying to mix with a business component (SA). It would make your SA somewhat dependent on that channel. We certainly don't want o go that route

  4. #4

    Default

    Okay. I think that makes sense. I'll create another channel say myMainChannel.valueOfEventTypeEnum and filter/route events into it.

    I guess the only other comment I had while working through this issue is that @ServiceActivator does not issue an event if the return value is void.

    Can there be another attribute that forces a return value from the value attribute even if there is a void return type form a method with @ServiceActivator attribute? You can do this with aop but I think (but don't know) the annotation should support it.

    e.g.

    @ServiceActivator(value="null" channel="myOutputChannel" always-send="true")
    public void reset() {
    // do things related to resetting in this object.
    }

    I want to broadcast simple events over a channel and just the presence of a message indicates that a reset should occur. Or am I not thinking correctly again (because I am mixing an integration concern with a business component) and should always send an event object for the payload?

  5. #5
    Join Date
    Jan 2008
    Location
    Mohnton, PA USA (that's near Philadelphia)
    Posts
    2,148

    Default

    Yes you can. And yes it is done via AOP but SI provides a convenient configuration with Message Publisher. It is available with SI 2.0.x
    What version of SI are you using?
    If 2.0, look at the documentation for Message Publishing and let me know if you have any questions

  6. #6

    Default

    My fault. I meant @Publisher of course. Yes through AOP I think you can (but have not tried it yet).

    But I don't think you can force a method with the @Publisher annotation to create a null event if it has a void return value....at least my sandbox test did not seem to send a message. The void return value is documented to not send a message on an @SerivceActivator.

    2.0.0.M3

    @Publisher(channel = "eventChannel")
    public void reset() {
    log.debug("Resetting the search component...");
    // Handle local object specific reset behavior.
    textField.setText(null);
    }

    even using value="#return" or value="null" did not force it to create an event.

  7. #7

    Wink

    Oleg,

    Just to let you know what I am trying to do. I am trying to fire events from a UI. The SeachEvent object carries an enum saying whether the user action was a reset-filter or a filter-text change event type. Here's the two implementations I was playing with.

    Code:
            @Publisher(value = "#return", channel = "eventChannel")
    	public SearchEvent reset() {
    		log.debug("Resetting the search component...");
    		// Handle local object specific reset behavior.
    		textField.setText(null);
    		// Issue the event object as the return value.
    		return new SearchEvent(this);
    	}
    
    	@Publisher(channel = "eventChannel.reset")
    	public void reset2() {
    		log.debug("Resetting the search component...");
    		// Handle local object specific reset behavior.
    		textField.setText(null);
    	}
    I get an event fired on the first but not on the second I think because of the void returning behavior. The idea is to not only have a handler that is simply defined as
    Code:
    public void reset() {...}
    in another class that should handle the event but also to issue it simply as well.

    On the message endpoint side and based on your previous response, it is clear that I can simply define a channel with a specific naming scheme to make this easily happen. I am comparing this to eventbus.org's library for swing applications. There, you can subscribe by event object type or a "string". In SI, it looks like could define an easy router to route from the main channel to a channel whose name is derived from the event object type or an enum (or whatever) and subscribe to it that way. That parts looks straight forward now. Just having problems issuing events in the way I would like.

  8. #8
    Join Date
    Jan 2008
    Location
    Mohnton, PA USA (that's near Philadelphia)
    Posts
    2,148

    Default

    I am not sure what null event is in your case, but I am sure it could be anything as long as you know that that 'anything' means null so value="'null'" as literal null could be treated by you as null event

  9. #9
    Join Date
    Oct 2005
    Location
    Boston, MA
    Posts
    2,853

    Default

    You could use:
    Code:
    @Publisher(value="'whatever-you-want'", channel="eventChannel")
    ...
    However, I think it's a good question... it is counter-intuitive right now that we allow @Publisher on a void-returning method but don't actually produce a result unless a 'value' attribute is provided. What should the default be?... I've avoided this whole idea of NullMessage for a while, but I think this is one more case where we need to face it

  10. #10
    Join Date
    Jan 2008
    Location
    Mohnton, PA USA (that's near Philadelphia)
    Posts
    2,148

    Default

    Hmm. . . I don't think it is counter-intuitive. Publisher is a by-product of method invocation so I don't think return value plays any role here other then maybe create some type of empty message when value="#return" (instead of faking it with 'null') if the return is void. If I remember correctly this did came up a few times.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •