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

Thread: jdbc inbound channel adapter for doing only a single query at runtime

  1. #1
    Join Date
    Nov 2009
    Location
    Montreal, Quebec
    Posts
    398

    Question jdbc inbound channel adapter for doing only a single query at runtime

    Upon startup, my app needs to quickly query an MS SQL database for records in 2 tables from the previous day. It's a fairly quick operation. I'm trying to figure out how I might do this with Spring Integration. I'm using an int-jdbc:inbound-channel-adapter to query my table and pass the message on to a channel to which I have a service-activator listening on. Whenever I run my app, it throws an exception that a poller has not been defined for my channel adapter. I understand the poller will do recursive queries to the database, but I'm only interested in making one initial query. How can I accomplish that? Should I just use JdbcTemplate directly? Thanks.

    Code:
    <beans:bean id="pfMessageHandler"
    	class="com.mycompany.phones.trace.PFTraceMessageHandler"/>
    
    <int-jdbc:inbound-channel-adapter query="select top 10 * from tblData_OutboundTrace"
    	channel="outboundTraceResults"
    	data-source="pfDataSource"/>
    		
    <channel id="outboundTraceResults"/>
    	
    <service-activator id="outboundTraceProcessor" input-channel="outboundTraceResults"
    	ref="pfMessageHandler" method="processOutboundTraceResults"/>

  2. #2
    Join Date
    Jan 2009
    Location
    Ukraine, Kharkov
    Posts
    632

    Default

    Hello.
    Yes, in this case you must use JdbcTemplate directly by implementation something like service who reads your DB and sends a message to the channel via gateway.

    But there is some trick. You must define bean of type
    org.springframework.beans.factory.config.MethodInv okingFactoryBean
    who invokes a method of your service who reads DB.
    And when the spring container is starting the method will be invoked once and only once.

    Good luck!
    Artem

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

    Default

    Actually, poller had two predefined triggers (interval based and Cron). Obviously for your case, non would work which means you have to implement your own.
    The Trigger interface is quite simple as you can see:
    Code:
    public interface Trigger {
    
    	Date nextExecutionTime(TriggerContext triggerContext);
    
    }
    All you need to do in the implementation is something like this:
    Code:
    public class MyTrigger implements Trigger {
    	private volatile boolean initiaized = false;
    	
    	public Date nextExecutionTime(TriggerContext triggerContext) {
    		if (!initiaized){
                            initialized = true;
    			return new Date(System.currentTimeMillis());
    		}
    		return null;
    	}
    }
    As you can see it will return Date only once which means it will only execute once.
    Then you inject the above bean via 'trigger' attribute.

  4. #4
    Join Date
    Nov 2009
    Location
    Montreal, Quebec
    Posts
    398

    Default

    Thanks Oleg, I'll give that a try. Seems simple enough.

  5. #5
    Join Date
    Nov 2009
    Location
    Montreal, Quebec
    Posts
    398

    Default

    Oleg, I've implemented the Trigger interface like you suggested and injected it into the poller. However when my app runs, it seems to be waiting after it completes the single execution. My MessageHandler method gets called just fine and the output is what I expect, but after the MessageHandler completes, that's when the app seems to be waiting for something. This is my new updated config.

    Code:
    	<int-jdbc:inbound-channel-adapter query="select * from tblData_OutboundTrace where datediff(d, MidnightStartDate, getdate()) = 1 and Extension != '' order by MidnightStartDate asc"
    		channel="outboundTraceResults"
    		data-source="pfDataSource">
    		<poller trigger="runOnceTrigger"/>
    	</int-jdbc:inbound-channel-adapter>
    		
    	<channel id="outboundTraceResults"/>
    	
    	<service-activator id="outboundTraceProcessor" input-channel="outboundTraceResults"
    		ref="pfMessageHandler" method="processOutboundTraceResults"/>
    		
    		
    	<!-- Message Handlers -->
    	
    	<beans:bean id="pfMessageHandler"
    		class="com.myco.phones.trace.PrairieFyreTraceMessageHandler"/>
    		
    	
    	<!-- Triggers -->
    	
    	<beans:bean id="runOnceTrigger" class="com.myco.scheduling.RunOnceTrigger"/>

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

    Default

    but I'm only interested in making one initial query
    So what you see is that your inbound adapter is triggered once and will never gets triggered again during that instance of the Application Context. Are you expecting something different?

  7. #7
    Join Date
    Nov 2009
    Location
    Montreal, Quebec
    Posts
    398

    Default

    That's right, I see that my inbound adapter is triggered only once. After I've processed the Message payload in my MessageHandler, I expect the app to end, not just wait and hang at the console.

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

    Default

    Ok, the thing is that polling consumer is a Lifecycle object so all you need to do is execute stop() on ApplicationContext.

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

    Default

    If the application really is so short-lived, it might make more sense to use JdbcTemplate directly within some code that implements SmartLifecycle or InitializingBean... or implement an ApplicationListener, parameterized with ContextRefreshedEvent.

    Or... do you intend to add more logic to this application so that it will include other long-running processes?

  10. #10
    Join Date
    Nov 2009
    Location
    Montreal, Quebec
    Posts
    398

    Default

    Given that the poller runs in a task scheduler thread rather than the main thread, if I call context.stop() from my main method, then execution of the poller terminates before completion. I hope I'm explaining myself well.

    My main method is just as simple as this. The inbound channel adapter is called as soon as the app starts.
    Code:
    	public static void main(String[] args) {
    		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/META-INF/spring/applicationContext.xml", Client.class);
    		context.stop();
    	}

Posting Permissions

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