2016-09-15 121 views
1

爲了學習彈簧集成,我一直在試圖創建一個簡單的,有彈性的日誌處理器。我也想堅持使用java配置方法。將JMS隊列XML配置轉換爲Java配置

我一直在困難的時間翻譯現有的XML配置,主要是因爲對於一般的春天來說太新了。

a question on the spring forums Gary Russell提出了一個類似的解決方案,使用帶有簡單XML配置的publish-subscribe + JMS模型。

我一直在試圖將他的建議翻譯成Java配置,但我堅持。即我不確定適用於出站通道適配器,服務激活器或如何正確設置消息順序的適當實體。

這裏是加里的XML配置:

<int-file:inbound-channel-adapter id="dispatcher" 
     directory="spool" 
     channel="fileChannel"> 
     <int:poller fixed-delay="2000"> 
      <int:transactional/> 
     </int:poller> 
    </int-file:inbound-channel-adapter> 

    <int:channel id="fileChannel" /> 

    <int-file:file-to-string-transformer input-channel="fileChannel" output-channel="dispatchChannel" /> 

    <int:publish-subscribe-channel id="dispatchChannel" /> 

    <int-jms:outbound-channel-adapter id="dispatcherJms" channel="dispatchChannel" order="1" 
     connection-factory="connectionFactory" 
     destination="dispatcher.queue" /> 

    <!-- If JMS Send was successful, remove the file (within the transaction)--> 
    <int:service-activator input-channel="dispatchChannel" order="2" 
     output-channel="nullChannel" 
        expression="headers.file_originalFile.delete()"> 

    <bean id="transactionManager" class="org.springframework.jms.connection.JmsTransactionManager"> 
     <property name="connectionFactory" ref="connectionFactory"/> 
    </bean> 

UPDATE

基礎上的評論下面我已經更新了Java的配置。

但是,我仍然收到錯誤,並且很可能不瞭解實體之間的流程和連接,但原始問題已得到解答。

@Bean 
@Transactional 
@InboundChannelAdapter(channel = "dispatchChannel", poller = @Poller(fixedDelay = "2000")) 
public MessageSource<?> dispatcher() { 
    CompositeFileListFilter<File> filters = new CompositeFileListFilter<>(); 
    filters.addFilter(new SimplePatternFileListFilter(sourceFilenamePattern)); 
    //filters.addFilter(persistentFilter()); 

    FileReadingMessageSource source = new FileReadingMessageSource(); 
    source.setAutoCreateDirectory(true); 
    source.setDirectory(new File(sourceDirectory)); 
    source.setFilter(filters); 

    return source; 
} 

@Bean 
public MessageChannel fileChannel() { 
    return new DirectChannel(); 
} 

@Bean 
public PublishSubscribeChannel dispatchChannel() { 
    return new PublishSubscribeChannel(); 
} 

@Autowired 
JmsTemplate jmsTemplate; 

@Autowired 
ConnectionFactory connectionFactory; 

@Bean 
@Order(1) 
@ServiceActivator(inputChannel = "dispatchChannel") 
public MessageHandler dispatcherJmsOutboundChannelAdapter(Message<File> message) { 
    JmsSendingMessageHandler handler = new JmsSendingMessageHandler(jmsTemplate); 
    handler.setDestinationName("dispatcher.queue"); 

    return handler; 
} 

@Bean 
@Order(2) 
@ServiceActivator(inputChannel = "dispatchChannel") 
public void removeFile(Message<?> message) { 
    //message.getHeaders().get(FileHeaders.ORIGINAL_FILE, File.class).delete(); 
    log.info("delete"); 
} 

@Bean 
public JmsTransactionManager transactionManager(ConnectionFactory connectionFactory) { 
    return new JmsTransactionManager(connectionFactory); 
} 

我使用的是spring啓動和幾個啓動組件,比如activemq。我已經爲JmsListenerContainerFactory和@JmsListener添加了@Bean,但我不確定這些是否真的有必要。

直到將@EnableJms添加到我的配置文件以及@Autowiring jmstemplate和connectionfactory之前,我無法運行任何程序。

運行時,現在我收到的錯誤是:

org.springframework.beans.factory.NoSuchBeanDefinitionException: 
    No qualifying bean of type [org.springframework.messaging.Message] found for dependency 
[org.springframework.messaging.Message<?>]: 
    expected at least 1 bean which qualifies as autowire candidate for this dependency. 
Dependency annotations: {} 

回答

1

這一個

<int:service-activator input-channel="dispatchChannel" order="2" 
    output-channel="nullChannel" 
       expression="headers.file_originalFile.delete()"> 

很簡單在Java中:

@ServiceActivator(inputChannel = "dispatchChannel") 
public void removeFile(Message<?> message) { 
    message.getHeaders().get(FileHeaders.ORIGINAL_FILE, File.class).delete(); 
} 

<int-jms:outbound-channel-adapter> 

被翻譯成這樣:

@Bean 
@ServiceActivator(inputChannel = "dispatchChannel") 
public MessageHandler dispatcherJmsOutboundChannelAdapter() { 
    JmsSendingMessageHandler handler = 
       new JmsSendingMessageHandler(new JmsTemplate(this.connectionFactory)); 
    handler.setDestinationName("dispatcher.queue"); 
    return handler; 
} 

注意這個段落在Reference Manual

+0

謝謝阿爾喬姆。消息順序如何轉換?也許我錯過了。 – rcurrie

+0

M-m-m。如果我正確地按照你的要求,你可以在'JmsSendingMessageHandler'上使用'setOrder()'。 –

+0

再次感謝。在Gary的解決方案中,他具有訂單=「1」的jms出站通道適配器和用於刪除訂單=「2」的文件的服務激活器 – rcurrie

0

拼圖的最後一塊是FileWritingMessageHandler

@Bean 
public FileWritingMessageHandler fileWritingMessageHandler() { 
    SpelExpressionParser parser = new SpelExpressionParser(); 
    Expression expression = parser.parseExpression("headers.file_originalFile.delete()"); 
    FileWritingMessageHandler fileWritingMessageHandler = new FileWritingMessageHandler(expression); 
    fileWritingMessageHandler.setOutputChannel(new NullChannel()); 
    fileWritingMessageHandler.setDeleteSourceFiles(true); 
    return fileWritingMessageHandler; 
} 
+0

請看看我的答案。即使你的解決方案有效,但是我們不得不花費簡單的文件刪除操作來處理這樣一個怪物:-)。 –

+0

感謝您提供更簡單的解決方案。只是享受學習的過程中,怪物會不時出現:) –