Announcement Announcement Module
Collapse
No announcement yet.
Spring Integration and Java Configuration Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring Integration and Java Configuration

    I managed to get my spring integration working with xml config. I would now like to convert the xml config into its java equivalent. It seems like spring-amqp supports this as they give the following example :

    HTML Code:
    @Configuration
    public class RabbitConfiguration {
    
      @Bean
      public ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory("localhost");
        return connectionFactory;
      }
    
      @Bean
      public AmqpAdmin amqpAdmin() {
        return new RabbitAdmin(connectionFactory());
      }
    
      @Bean
      public RabbitTemplate rabbitTemplate() {
        return new RabbitTemplate(connectionFactory());
      }
    
       @Bean
       public Queue myQueue() {
         return new Queue("myqueue");
       }
     }
    It would seam that Spring Integration is still dependent on xml configuration as the reference documentation for 3.0.0.M1 doesn't include Java Configuration examples.

    Undeterred I had a go at configurating it via java

    HTML Code:
    **
     * AMQP Configuration
     */
    @Configuration
    public class AmqpConfig {
    
        public static final int DEFAULT_REPLY_TIMEOUT = 5000;
        private static final String EXCHANGE_NAME = "profile.manager.exchange";
        private static final String QUEUE_NAME = "profile.manager.queue";
    
        @Bean
        public MessageChannel profileManagerRequestChannel() {
            DirectChannel channel = new DirectChannel();
            return channel;
        }
    
        @Bean
        public MessageChannel profileManagerReplyChannel() {
            return new DirectChannel();
        }
    
        @Bean
        public MessageChannel profileManagerErrorChannel() {
            return new DirectChannel();
        }
    
        @Bean
        public ProfileManagerService profileManagerService() {
            return new ProfileManagerServiceImpl();
        }
    
        @Bean
        public JsonMessageConverter jsonMessageConverter() {
            return new JsonMessageConverter();
        }
    
        @Bean
        public GatewayProxyFactoryBean gatewayProxyFactoryBean() {
            GatewayProxyFactoryBean gatewayProxyFactoryBean = new GatewayProxyFactoryBean();
            gatewayProxyFactoryBean.setServiceInterface(ProfileManagerClient.class);
            gatewayProxyFactoryBean.setDefaultRequestChannel(profileManagerRequestChannel());
            gatewayProxyFactoryBean.setDefaultReplyTimeout(DEFAULT_REPLY_TIMEOUT);
            return gatewayProxyFactoryBean;
        }
    
        @Bean
        public AmqpOutboundEndpoint outboundGateway() {
            AmqpOutboundEndpoint outboundGateway = new AmqpOutboundEndpoint(rabbitTemplate());
            
            //how do I sent the input
            outboundGateway.setExpectReply(true);
            outboundGateway.setExchangeName(EXCHANGE_NAME);
            outboundGateway.setRoutingKey(QUEUE_NAME);
    
            return outboundGateway;
        }
    
        @Bean
        public AmqpInboundGateway inboundGateway() {
            //AbstractMessageListenerContainer listenerContainer ???
            AmqpInboundGateway inboundGateway = new AmqpInboundGateway();
            inboundGateway.setRequestChannel(profileManagerReplyChannel());
            inboundGateway.setMessageConverter(jsonMessageConverter());
            inboundGateway.setErrorChannel(profileManagerErrorChannel());
            inboundGateway.setReplyTimeout(DEFAULT_REPLY_TIMEOUT);
    
            return  inboundGateway;
        }
    
        @Bean
        public ConnectionFactory rabbitConnectionFactory() {
           return new CachingConnectionFactory();
        }
    
        @Bean
        public RabbitTemplate rabbitTemplate() {
            RabbitTemplate rabbitTemplate = new RabbitTemplate();
            rabbitTemplate.setConnectionFactory(rabbitConnectionFactory());
            rabbitTemplate.setMessageConverter(jsonMessageConverter());
    
            return rabbitTemplate;
        }
    
        @Bean
        public AmqpAdmin amqpAdmin() {
            return new RabbitAdmin(rabbitConnectionFactory());
        }
    
        @Bean
        public Queue profileManagerQueue() {
            return new Queue(QUEUE_NAME);
        }
    
    }
    To get this far I had to dig into the Namespace resolver code to work out the mappings between xml elements and classes.


    Its strange that there is an AmqpInboundGateway class but NO AmqpOutboundGateway - instead you create an AmqpOutboundEndpoint and the replyExpected flag causes it to behave as either an endpointAdapter or a gateway.

    The next thing that seems odd is that you cant specify the requestChannel for either the AmqpInboundGateway or AmqpOutboundEndpoint ???

    When I try and create an AmqpInboundGateway the constructor wants a referenced to a AbstractMessageListenerContainer ????


    I guess I am not supposed to see these innards as they are hidden from me by the Xml configuration ? If you can advise me how to fix my attempt at configuring spring integration via Java Configuration that would be great. If its all too hard at the moment do you have an idea when spring integration will support Java Configuration ??

    I am trying to add spring integration into a production system and they are pretty keen to minimize the amount of xml configuration.

    Cheers

  • #2
    Well, as you have seen, the namespace hides a lot of configuration, particularly on the outbound side. We are looking at various options to provide a java configurarion API (although it won't be pure JavaConfig because that really maps one-to-one with <bean/> definitions; outbound endpoints usually need two or more beans).

    The parsers are the best place to understand what is needed.

    The outbound gateway needs a ConsumerEndpointFactorBean which gets its AmqpOutboundEndpoint in its handler property. If you explore the parsers further (including the super class AbstractConsumerEndpointParser) you'll see that the request-channel attribute gets mapped to the factory bean's inputChannelName property. The factory bean then decides what type of consumer it needs, depending on the channel type.

    There's a lot more complexity in there too, particularly around the auto-generation of direct channels if the channel (request-channel) has not been explicitly declared. But there's other stuff too, parsing pollers etc.

    On the inbound side, the gateway is message-driven so, yes, it needs a listener container - configure up a SimpleMessageListenerContainer as a @Bean.

    We realize that some users would prefer to configure using java and, trust us, if it was "easy", it would have been done by now.

    But, ... watch this space.

    Comment


    • #3
      Hello, Gary!

      How it is going? I'm also looking for a simple way to configure my Integration beans via java-based config. Are there any updates on this topic?

      Regards, Alexey

      Comment


      • #4
        Nothing is available yet; it is on our radar, though.

        Comment


        • #5
          +1 for this from me. I'm using pure Java configuration with Servlet 3, Spring 3.2.5 and CXF 3.0, and I wouldn;t like to go "back" to XML configurations...

          Comment


          • #6
            Is there a JIRA ticket we can vote on, Gary?

            Comment

            Working...
            X