├── LICENSE.txt ├── Pro Spring Messaging Source Code ├── .gitignore ├── README.md ├── ch02 │ └── rest-api-demo │ │ ├── pom.xml │ │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── apress │ │ │ │ └── messaging │ │ │ │ ├── RestApiDemoApplication.java │ │ │ │ ├── ServletInitializer.java │ │ │ │ ├── annotation │ │ │ │ └── ToUpper.java │ │ │ │ ├── aop │ │ │ │ └── CurrencyCodeAudit.java │ │ │ │ ├── controller │ │ │ │ └── CurrencyController.java │ │ │ │ ├── domain │ │ │ │ ├── CurrencyConversion.java │ │ │ │ ├── CurrencyExchange.java │ │ │ │ └── Rate.java │ │ │ │ ├── repository │ │ │ │ └── RateRepository.java │ │ │ │ └── service │ │ │ │ └── CurrencyConversionService.java │ │ └── resources │ │ │ ├── application.properties │ │ │ └── public │ │ │ └── error │ │ │ ├── 4xx.html │ │ │ └── 5xx.html │ │ └── test │ │ └── java │ │ └── com │ │ └── apress │ │ └── messaging │ │ └── RestApiDemoApplicationTests.java ├── ch03 │ └── rest-api-events │ │ ├── pom.xml │ │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── apress │ │ │ │ └── messaging │ │ │ │ ├── RestApiEventsApplication.java │ │ │ │ ├── ServletInitializer.java │ │ │ │ ├── annotation │ │ │ │ ├── Log.java │ │ │ │ └── ToUpper.java │ │ │ │ ├── aop │ │ │ │ ├── CodeLogger.java │ │ │ │ ├── CurrencyCodeAudit.java │ │ │ │ └── CurrencyConversionAudit.java │ │ │ │ ├── controller │ │ │ │ └── CurrencyController.java │ │ │ │ ├── domain │ │ │ │ ├── CurrencyConversion.java │ │ │ │ ├── CurrencyExchange.java │ │ │ │ └── Rate.java │ │ │ │ ├── event │ │ │ │ ├── CurrencyConversionEvent.java │ │ │ │ └── CurrencyEvent.java │ │ │ │ ├── exception │ │ │ │ └── BadCodeRuntimeException.java │ │ │ │ ├── listener │ │ │ │ ├── CurrencyConversionEventListener.java │ │ │ │ ├── RateEventListener.java │ │ │ │ ├── RestApiEventsListener.java │ │ │ │ └── RestAppEventListener.java │ │ │ │ ├── repository │ │ │ │ └── RateRepository.java │ │ │ │ └── service │ │ │ │ ├── CurrencyConversionService.java │ │ │ │ └── CurrencyService.java │ │ └── resources │ │ │ ├── application.properties │ │ │ └── public │ │ │ └── error │ │ │ ├── 4xx.html │ │ │ └── 5xx.html │ │ └── test │ │ └── java │ │ └── com │ │ └── apress │ │ └── messaging │ │ └── RestApiEventsApplicationTests.java ├── ch04 │ ├── jms-sender │ │ ├── .gitignore │ │ ├── pom.xml │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── apress │ │ │ │ │ └── messaging │ │ │ │ │ ├── JmsSenderApplication.java │ │ │ │ │ ├── ServletInitializer.java │ │ │ │ │ ├── aop │ │ │ │ │ └── JMSAudit.java │ │ │ │ │ ├── config │ │ │ │ │ ├── JMSConfig.java │ │ │ │ │ └── JMSProperties.java │ │ │ │ │ ├── domain │ │ │ │ │ └── Rate.java │ │ │ │ │ └── jms │ │ │ │ │ ├── AnnotatedReceiver.java │ │ │ │ │ ├── QueueListener.java │ │ │ │ │ ├── RateReceiver.java │ │ │ │ │ ├── RateReplyReceiver.java │ │ │ │ │ ├── RateSender.java │ │ │ │ │ └── SimpleSender.java │ │ │ └── resources │ │ │ │ ├── META-INF │ │ │ │ └── additional-spring-configuration-metadata.json │ │ │ │ └── application.properties │ │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── apress │ │ │ └── messaging │ │ │ └── JmsSenderApplicationTests.java │ ├── jms-topic-subscriber │ │ ├── .gitignore │ │ ├── pom.xml │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── apress │ │ │ │ │ └── messaging │ │ │ │ │ ├── JmsTopicSubscriberApplication.java │ │ │ │ │ ├── ServletInitializer.java │ │ │ │ │ ├── aop │ │ │ │ │ └── JMSAudit.java │ │ │ │ │ ├── config │ │ │ │ │ ├── JMSConfig.java │ │ │ │ │ └── JMSProperties.java │ │ │ │ │ ├── domain │ │ │ │ │ └── Rate.java │ │ │ │ │ └── jms │ │ │ │ │ └── RateTopicReceiver.java │ │ │ └── resources │ │ │ │ ├── META-INF │ │ │ │ └── additional-spring-configuration-metadata.json │ │ │ │ └── application.properties │ │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── apress │ │ │ └── messaging │ │ │ └── JmsTopicSubscriberApplicationTests.java │ └── rest-api-jms │ │ ├── pom.xml │ │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── apress │ │ │ │ └── messaging │ │ │ │ ├── RestApiJMSApplication.java │ │ │ │ ├── ServletInitializer.java │ │ │ │ ├── annotation │ │ │ │ ├── Log.java │ │ │ │ └── ToUpper.java │ │ │ │ ├── aop │ │ │ │ ├── CodeLogger.java │ │ │ │ ├── CurrencyCodeAudit.java │ │ │ │ └── CurrencyConversionAudit.java │ │ │ │ ├── config │ │ │ │ ├── RateJmsConfiguration.java │ │ │ │ └── RateProperties.java │ │ │ │ ├── controller │ │ │ │ └── CurrencyController.java │ │ │ │ ├── domain │ │ │ │ ├── CurrencyConversion.java │ │ │ │ ├── CurrencyExchange.java │ │ │ │ └── Rate.java │ │ │ │ ├── event │ │ │ │ ├── CurrencyConversionEvent.java │ │ │ │ └── CurrencyEvent.java │ │ │ │ ├── exception │ │ │ │ └── BadCodeRuntimeException.java │ │ │ │ ├── jms │ │ │ │ └── RateJmsReceiver.java │ │ │ │ ├── listener │ │ │ │ ├── CurrencyConversionEventListener.java │ │ │ │ ├── RateEventListener.java │ │ │ │ ├── RestApiEventsListener.java │ │ │ │ └── RestAppEventListener.java │ │ │ │ ├── repository │ │ │ │ └── RateRepository.java │ │ │ │ └── service │ │ │ │ ├── CurrencyConversionService.java │ │ │ │ └── CurrencyService.java │ │ └── resources │ │ │ ├── META-INF │ │ │ └── additional-spring-configuration-metadata.json │ │ │ ├── application.properties │ │ │ └── public │ │ │ └── error │ │ │ ├── 4xx.html │ │ │ └── 5xx.html │ │ └── test │ │ └── java │ │ └── com │ │ └── apress │ │ └── messaging │ │ └── RestApiJMSApplicationTests.java ├── ch05 │ ├── amqp-demo │ │ ├── .gitignore │ │ ├── pom.xml │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── apress │ │ │ │ │ └── messaging │ │ │ │ │ ├── AmqpDemoApplication.java │ │ │ │ │ ├── ServletInitializer.java │ │ │ │ │ ├── amqp │ │ │ │ │ ├── AnnotatedConsumer.java │ │ │ │ │ ├── Consumer.java │ │ │ │ │ ├── MultiListenerService.java │ │ │ │ │ ├── Producer.java │ │ │ │ │ ├── RateConsumer.java │ │ │ │ │ ├── RateProducer.java │ │ │ │ │ ├── ReplyToService.java │ │ │ │ │ ├── RpcClient.java │ │ │ │ │ └── RpcServer.java │ │ │ │ │ ├── aop │ │ │ │ │ └── AMQPAudit.java │ │ │ │ │ ├── config │ │ │ │ │ ├── AMQPConfig.java │ │ │ │ │ └── AMQPProperties.java │ │ │ │ │ ├── domain │ │ │ │ │ ├── ClientRate.java │ │ │ │ │ ├── Invoice.java │ │ │ │ │ ├── InvoiceWithTax.java │ │ │ │ │ ├── Item.java │ │ │ │ │ ├── Order.java │ │ │ │ │ └── Rate.java │ │ │ │ │ └── listener │ │ │ │ │ └── RabbitMQEventListener.java │ │ │ └── resources │ │ │ │ ├── META-INF │ │ │ │ └── additional-spring-configuration-metadata.json │ │ │ │ └── application.properties │ │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── apress │ │ │ └── messaging │ │ │ └── AmqpDemoApplicationTests.java │ └── rest-api-amqp │ │ ├── .gitignore │ │ ├── pom.xml │ │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── apress │ │ │ │ └── messaging │ │ │ │ ├── RestApiAMQPApplication.java │ │ │ │ ├── ServletInitializer.java │ │ │ │ ├── amqp │ │ │ │ ├── RateConsumer.java │ │ │ │ └── RateProducer.java │ │ │ │ ├── annotation │ │ │ │ ├── Log.java │ │ │ │ └── ToUpper.java │ │ │ │ ├── aop │ │ │ │ ├── CodeLogger.java │ │ │ │ ├── CurrencyCodeAudit.java │ │ │ │ └── CurrencyConversionAudit.java │ │ │ │ ├── config │ │ │ │ ├── RateJmsConfiguration.java │ │ │ │ └── RateProperties.java │ │ │ │ ├── controller │ │ │ │ └── CurrencyController.java │ │ │ │ ├── domain │ │ │ │ ├── CurrencyConversion.java │ │ │ │ ├── CurrencyExchange.java │ │ │ │ └── Rate.java │ │ │ │ ├── event │ │ │ │ ├── CurrencyConversionEvent.java │ │ │ │ └── CurrencyEvent.java │ │ │ │ ├── exception │ │ │ │ └── BadCodeRuntimeException.java │ │ │ │ ├── jms │ │ │ │ └── RateJmsReceiver.java │ │ │ │ ├── listener │ │ │ │ ├── CurrencyConversionEventListener.java │ │ │ │ ├── RateEventListener.java │ │ │ │ ├── RestApiEventsListener.java │ │ │ │ └── RestAppEventListener.java │ │ │ │ ├── repository │ │ │ │ └── RateRepository.java │ │ │ │ └── service │ │ │ │ ├── CurrencyConversionService.java │ │ │ │ └── CurrencyService.java │ │ └── resources │ │ │ ├── META-INF │ │ │ └── additional-spring-configuration-metadata.json │ │ │ ├── application.properties │ │ │ └── public │ │ │ └── error │ │ │ ├── 4xx.html │ │ │ └── 5xx.html │ │ └── test │ │ └── java │ │ └── com │ │ └── apress │ │ └── messaging │ │ └── RestApiAMQPApplicationTests.java ├── ch06 │ ├── redis-demo │ │ ├── .gitignore │ │ ├── pom.xml │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── apress │ │ │ │ │ └── messaging │ │ │ │ │ ├── RedisDemoApplication.java │ │ │ │ │ ├── ServletInitializer.java │ │ │ │ │ ├── aop │ │ │ │ │ └── RedisAudit.java │ │ │ │ │ ├── config │ │ │ │ │ ├── RedisConfig.java │ │ │ │ │ └── SimpleRedisProperties.java │ │ │ │ │ ├── domain │ │ │ │ │ └── Rate.java │ │ │ │ │ └── redis │ │ │ │ │ ├── RateSubscriber.java │ │ │ │ │ └── Subscriber.java │ │ │ └── resources │ │ │ │ ├── META-INF │ │ │ │ └── additional-spring-configuration-metadata.json │ │ │ │ └── application.properties │ │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── apress │ │ │ └── messaging │ │ │ └── RedisDemoApplicationTests.java │ └── rest-api-redis │ │ ├── .gitignore │ │ ├── pom.xml │ │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── apress │ │ │ │ └── messaging │ │ │ │ ├── RestApiAMQPApplication.java │ │ │ │ ├── ServletInitializer.java │ │ │ │ ├── amqp │ │ │ │ ├── RateConsumer.java │ │ │ │ └── RateProducer.java │ │ │ │ ├── annotation │ │ │ │ ├── Log.java │ │ │ │ └── ToUpper.java │ │ │ │ ├── aop │ │ │ │ ├── CodeLogger.java │ │ │ │ ├── CurrencyCodeAudit.java │ │ │ │ └── CurrencyConversionAudit.java │ │ │ │ ├── config │ │ │ │ ├── RateJmsConfiguration.java │ │ │ │ ├── RateProperties.java │ │ │ │ ├── RateRedisConfig.java │ │ │ │ └── RateRedisProperties.java │ │ │ │ ├── controller │ │ │ │ └── CurrencyController.java │ │ │ │ ├── domain │ │ │ │ ├── CurrencyConversion.java │ │ │ │ ├── CurrencyExchange.java │ │ │ │ └── Rate.java │ │ │ │ ├── event │ │ │ │ ├── CurrencyConversionEvent.java │ │ │ │ └── CurrencyEvent.java │ │ │ │ ├── exception │ │ │ │ └── BadCodeRuntimeException.java │ │ │ │ ├── jms │ │ │ │ └── RateJmsReceiver.java │ │ │ │ ├── listener │ │ │ │ ├── CurrencyConversionEventListener.java │ │ │ │ ├── RateEventListener.java │ │ │ │ ├── RestApiEventsListener.java │ │ │ │ └── RestAppEventListener.java │ │ │ │ ├── redis │ │ │ │ └── RateRedisSubscriber.java │ │ │ │ ├── repository │ │ │ │ └── RateRepository.java │ │ │ │ └── service │ │ │ │ ├── CurrencyConversionService.java │ │ │ │ └── CurrencyService.java │ │ └── resources │ │ │ ├── META-INF │ │ │ └── additional-spring-configuration-metadata.json │ │ │ ├── application.properties │ │ │ └── public │ │ │ └── error │ │ │ ├── 4xx.html │ │ │ └── 5xx.html │ │ └── test │ │ └── java │ │ └── com │ │ └── apress │ │ └── messaging │ │ └── RestApiAMQPApplicationTests.java ├── ch07 │ ├── rest-api-websockets │ │ ├── .gitignore │ │ ├── pom.xml │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── apress │ │ │ │ │ └── messaging │ │ │ │ │ ├── RestApiWebSocketsApplication.java │ │ │ │ │ ├── ServletInitializer.java │ │ │ │ │ ├── amqp │ │ │ │ │ ├── RateConsumer.java │ │ │ │ │ └── RateProducer.java │ │ │ │ │ ├── annotation │ │ │ │ │ ├── Log.java │ │ │ │ │ └── ToUpper.java │ │ │ │ │ ├── aop │ │ │ │ │ ├── CodeLogger.java │ │ │ │ │ ├── CurrencyCodeAudit.java │ │ │ │ │ └── CurrencyConversionAudit.java │ │ │ │ │ ├── config │ │ │ │ │ ├── RateJmsConfiguration.java │ │ │ │ │ ├── RateProperties.java │ │ │ │ │ ├── RateRedisConfig.java │ │ │ │ │ ├── RateRedisProperties.java │ │ │ │ │ ├── RateWebSocketsConfig.java │ │ │ │ │ └── RateWebSocketsProperties.java │ │ │ │ │ ├── controller │ │ │ │ │ └── CurrencyController.java │ │ │ │ │ ├── domain │ │ │ │ │ ├── CurrencyConversion.java │ │ │ │ │ ├── CurrencyExchange.java │ │ │ │ │ └── Rate.java │ │ │ │ │ ├── event │ │ │ │ │ ├── CurrencyConversionEvent.java │ │ │ │ │ └── CurrencyEvent.java │ │ │ │ │ ├── exception │ │ │ │ │ └── BadCodeRuntimeException.java │ │ │ │ │ ├── jms │ │ │ │ │ └── RateJmsReceiver.java │ │ │ │ │ ├── listener │ │ │ │ │ ├── CurrencyConversionEventListener.java │ │ │ │ │ ├── RateEventListener.java │ │ │ │ │ ├── RestApiEventsListener.java │ │ │ │ │ └── RestAppEventListener.java │ │ │ │ │ ├── redis │ │ │ │ │ └── RateRedisSubscriber.java │ │ │ │ │ ├── repository │ │ │ │ │ └── RateRepository.java │ │ │ │ │ └── service │ │ │ │ │ ├── CurrencyConversionService.java │ │ │ │ │ └── CurrencyService.java │ │ │ └── resources │ │ │ │ ├── META-INF │ │ │ │ └── additional-spring-configuration-metadata.json │ │ │ │ ├── application.properties │ │ │ │ └── public │ │ │ │ ├── error │ │ │ │ ├── 4xx.html │ │ │ │ └── 5xx.html │ │ │ │ └── index-ws.html │ │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── apress │ │ │ └── messaging │ │ │ └── RestApiWebSocketsApplicationTests.java │ └── websocket-demo │ │ ├── .gitignore │ │ ├── pom.xml │ │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── apress │ │ │ │ └── messaging │ │ │ │ ├── ServletInitializer.java │ │ │ │ ├── WebSocketsDemoApplication.java │ │ │ │ ├── aop │ │ │ │ └── WebSocketsAudit.java │ │ │ │ ├── config │ │ │ │ ├── LlWebSocketConfig.java │ │ │ │ ├── SimpleWebSocketsProperties.java │ │ │ │ └── WebSocketsConfig.java │ │ │ │ ├── controller │ │ │ │ └── SimpleController.java │ │ │ │ ├── domain │ │ │ │ ├── ChatMessage.java │ │ │ │ └── Rate.java │ │ │ │ └── web │ │ │ │ └── socket │ │ │ │ └── LlWebSocketHandler.java │ │ └── resources │ │ │ ├── META-INF │ │ │ └── additional-spring-configuration-metadata.json │ │ │ ├── application.properties │ │ │ └── static │ │ │ ├── llws.html │ │ │ └── sockjs-stomp.html │ │ └── test │ │ └── java │ │ └── com │ │ └── apress │ │ └── messaging │ │ └── WebSocketsDemoApplicationTests.java ├── ch08 │ ├── rest-api-si │ │ ├── .gitignore │ │ ├── pom.xml │ │ ├── rates-2017-02-21.txt │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── apress │ │ │ │ │ └── messaging │ │ │ │ │ ├── RestApiSpiApplication.java │ │ │ │ │ ├── ServletInitializer.java │ │ │ │ │ ├── amqp │ │ │ │ │ ├── RateConsumer.java │ │ │ │ │ └── RateProducer.java │ │ │ │ │ ├── annotation │ │ │ │ │ ├── Log.java │ │ │ │ │ └── ToUpper.java │ │ │ │ │ ├── aop │ │ │ │ │ ├── CodeLogger.java │ │ │ │ │ ├── CurrencyCodeAudit.java │ │ │ │ │ └── CurrencyConversionAudit.java │ │ │ │ │ ├── config │ │ │ │ │ ├── RateJmsConfiguration.java │ │ │ │ │ ├── RateProperties.java │ │ │ │ │ ├── RateRedisConfig.java │ │ │ │ │ ├── RateRedisProperties.java │ │ │ │ │ ├── RateSpiConfig.java │ │ │ │ │ ├── RateSpiProperties.java │ │ │ │ │ ├── RateWebSocketsConfig.java │ │ │ │ │ └── RateWebSocketsProperties.java │ │ │ │ │ ├── controller │ │ │ │ │ └── CurrencyController.java │ │ │ │ │ ├── domain │ │ │ │ │ ├── CurrencyConversion.java │ │ │ │ │ ├── CurrencyExchange.java │ │ │ │ │ └── Rate.java │ │ │ │ │ ├── event │ │ │ │ │ ├── CurrencyConversionEvent.java │ │ │ │ │ └── CurrencyEvent.java │ │ │ │ │ ├── exception │ │ │ │ │ └── BadCodeRuntimeException.java │ │ │ │ │ ├── integration │ │ │ │ │ └── RateServiceActivator.java │ │ │ │ │ ├── jms │ │ │ │ │ └── RateJmsReceiver.java │ │ │ │ │ ├── listener │ │ │ │ │ ├── CurrencyConversionEventListener.java │ │ │ │ │ ├── RateEventListener.java │ │ │ │ │ ├── RestApiEventsListener.java │ │ │ │ │ └── RestAppEventListener.java │ │ │ │ │ ├── redis │ │ │ │ │ └── RateRedisSubscriber.java │ │ │ │ │ ├── repository │ │ │ │ │ └── RateRepository.java │ │ │ │ │ └── service │ │ │ │ │ ├── CurrencyConversionService.java │ │ │ │ │ └── CurrencyService.java │ │ │ └── resources │ │ │ │ ├── META-INF │ │ │ │ └── additional-spring-configuration-metadata.json │ │ │ │ ├── application.properties │ │ │ │ └── public │ │ │ │ ├── error │ │ │ │ ├── 4xx.html │ │ │ │ └── 5xx.html │ │ │ │ └── index-ws.html │ │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── apress │ │ │ └── messaging │ │ │ └── RestApiSpiApplicationTests.java │ └── si-demo │ │ ├── .gitignore │ │ ├── contacts.txt │ │ ├── pom.xml │ │ ├── rates-2017-02-21.txt │ │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── apress │ │ │ │ └── messaging │ │ │ │ ├── SpiDemoApplication.java │ │ │ │ ├── aop │ │ │ │ └── SpiAudit.java │ │ │ │ ├── config │ │ │ │ ├── RateConfig.java │ │ │ │ ├── SimpleAnnotationConfiguration.java │ │ │ │ ├── SpiFileConfiguration.java │ │ │ │ ├── SpiFileToJdbcConfigutation.java │ │ │ │ ├── SpiProperties.java │ │ │ │ └── SpiSimpleConfiguration.java │ │ │ │ ├── controller │ │ │ │ └── SimpleController.java │ │ │ │ ├── domain │ │ │ │ ├── Person.java │ │ │ │ └── Rate.java │ │ │ │ └── integration │ │ │ │ ├── PersonConverter.java │ │ │ │ └── SimpleMessageHandler.java │ │ └── resources │ │ │ ├── META-INF │ │ │ └── spring │ │ │ │ └── integration │ │ │ │ ├── spi-context.xml │ │ │ │ └── spi-file-to-jdbc.xml │ │ │ ├── application.properties │ │ │ └── schema.sql │ │ └── test │ │ └── java │ │ └── com │ │ └── apress │ │ └── messaging │ │ └── SpiDemoApplicationTests.java ├── ch09 │ ├── app-starters │ │ ├── http │ │ │ ├── http-source-rabbit-1.1.2.RELEASE.jar │ │ │ └── start.sh │ │ └── log │ │ │ ├── log-sink-rabbit-1.1.1.RELEASE.jar │ │ │ └── start.sh │ ├── cloud-stream-demo │ │ ├── .gitignore │ │ ├── pom.xml │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── apress │ │ │ │ │ └── messaging │ │ │ │ │ ├── CloudStreamDemoApplication.java │ │ │ │ │ ├── aop │ │ │ │ │ └── CloudStreamAudit.java │ │ │ │ │ └── cloud │ │ │ │ │ └── stream │ │ │ │ │ ├── SimpleProcessor.java │ │ │ │ │ ├── SimpleSink.java │ │ │ │ │ └── SimpleSource.java │ │ │ └── resources │ │ │ │ ├── META-INF │ │ │ │ └── spring.integration.properties │ │ │ │ └── application.properties │ │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── apress │ │ │ └── cloud │ │ │ └── stream │ │ │ └── CloudStreamDemoApplicationTests.java │ ├── cloud-stream-processor-demo │ │ ├── .gitignore │ │ ├── pom.xml │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── apress │ │ │ │ │ └── messaging │ │ │ │ │ ├── CloudStreamProcessorDemoApplication.java │ │ │ │ │ ├── aop │ │ │ │ │ └── CloudStreamAudit.java │ │ │ │ │ ├── cloud │ │ │ │ │ └── stream │ │ │ │ │ │ └── PersonTicketProcessor.java │ │ │ │ │ └── domain │ │ │ │ │ ├── Person.java │ │ │ │ │ └── Ticket.java │ │ │ └── resources │ │ │ │ └── application.properties │ │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── apress │ │ │ └── messging │ │ │ └── CloudStreamProcessorDemoApplicationTests.java │ ├── cloud-stream-sink-demo │ │ ├── .gitignore │ │ ├── pom.xml │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── apress │ │ │ │ │ └── messaging │ │ │ │ │ ├── CloudStreamSinkDemoApplication.java │ │ │ │ │ ├── aop │ │ │ │ │ └── CloudStreamAudit.java │ │ │ │ │ └── cloud │ │ │ │ │ └── stream │ │ │ │ │ ├── TicketSink.java │ │ │ │ │ └── TicketSinkProperties.java │ │ │ └── resources │ │ │ │ └── application.properties │ │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── apress │ │ │ └── messging │ │ │ └── CloudStreamSinkDemoApplicationTests.java │ ├── cloud-stream-source-demo │ │ ├── .gitignore │ │ ├── contacts.txt │ │ ├── pom.xml │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── apress │ │ │ │ │ └── messaging │ │ │ │ │ ├── CloudStreamSourceDemoApplication.java │ │ │ │ │ ├── aop │ │ │ │ │ └── CloudStreamAudit.java │ │ │ │ │ ├── cloud │ │ │ │ │ └── stream │ │ │ │ │ │ ├── PersonFileProperties.java │ │ │ │ │ │ └── PersonFileSource.java │ │ │ │ │ ├── domain │ │ │ │ │ ├── Person.java │ │ │ │ │ └── Rate.java │ │ │ │ │ └── integration │ │ │ │ │ ├── PersonConverter.java │ │ │ │ │ └── SimpleMessageHandler.java │ │ │ └── resources │ │ │ │ └── application.properties │ │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── apress │ │ │ └── messging │ │ │ └── CloudStreamSourceDemoApplicationTests.java │ └── rest-api-cloud-stream │ │ ├── .gitignore │ │ ├── output │ │ └── rates-2017-02-21.processed │ │ ├── pom.xml │ │ ├── rates-2017-02-21.txt │ │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── apress │ │ │ │ └── messaging │ │ │ │ ├── RestApiCloudStreamApplication.java │ │ │ │ ├── ServletInitializer.java │ │ │ │ ├── amqp │ │ │ │ ├── RateConsumer.java │ │ │ │ └── RateProducer.java │ │ │ │ ├── annotation │ │ │ │ ├── Log.java │ │ │ │ └── ToUpper.java │ │ │ │ ├── aop │ │ │ │ ├── CodeLogger.java │ │ │ │ ├── CurrencyCodeAudit.java │ │ │ │ └── CurrencyConversionAudit.java │ │ │ │ ├── cloud │ │ │ │ └── stream │ │ │ │ │ ├── RateExchange.java │ │ │ │ │ ├── RateProcessor.java │ │ │ │ │ └── RateSink.java │ │ │ │ ├── config │ │ │ │ ├── RateJmsConfiguration.java │ │ │ │ ├── RateProperties.java │ │ │ │ ├── RateRedisConfig.java │ │ │ │ ├── RateRedisProperties.java │ │ │ │ ├── RateSpiConfig.java │ │ │ │ ├── RateSpiProperties.java │ │ │ │ ├── RateWebSocketsConfig.java │ │ │ │ └── RateWebSocketsProperties.java │ │ │ │ ├── controller │ │ │ │ └── CurrencyController.java │ │ │ │ ├── domain │ │ │ │ ├── CurrencyConversion.java │ │ │ │ ├── CurrencyExchange.java │ │ │ │ └── Rate.java │ │ │ │ ├── event │ │ │ │ ├── CurrencyConversionEvent.java │ │ │ │ └── CurrencyEvent.java │ │ │ │ ├── exception │ │ │ │ └── BadCodeRuntimeException.java │ │ │ │ ├── integration │ │ │ │ └── RateServiceActivator.java │ │ │ │ ├── jms │ │ │ │ └── RateJmsReceiver.java │ │ │ │ ├── listener │ │ │ │ ├── CurrencyConversionEventListener.java │ │ │ │ ├── RateEventListener.java │ │ │ │ ├── RestApiEventsListener.java │ │ │ │ └── RestAppEventListener.java │ │ │ │ ├── redis │ │ │ │ └── RateRedisSubscriber.java │ │ │ │ ├── repository │ │ │ │ └── RateRepository.java │ │ │ │ └── service │ │ │ │ ├── CurrencyConversionService.java │ │ │ │ └── CurrencyService.java │ │ └── resources │ │ │ ├── META-INF │ │ │ └── additional-spring-configuration-metadata.json │ │ │ ├── application.properties │ │ │ └── public │ │ │ ├── error │ │ │ ├── 4xx.html │ │ │ └── 5xx.html │ │ │ └── index-ws.html │ │ └── test │ │ └── java │ │ └── com │ │ └── apress │ │ └── messaging │ │ └── RestApiCloudStreamApplicationTests.java ├── ch10 │ ├── reactor-demo │ │ ├── .gitignore │ │ ├── pom.xml │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── apress │ │ │ │ │ └── messaging │ │ │ │ │ ├── ReactorDemoApplication.java │ │ │ │ │ ├── domain │ │ │ │ │ └── Exchange.java │ │ │ │ │ └── service │ │ │ │ │ └── ExchangeService.java │ │ │ └── resources │ │ │ │ └── application.properties │ │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── apress │ │ │ └── messaging │ │ │ └── ReactorDemoApplicationTests.java │ ├── rxjava-demo │ │ ├── .gitignore │ │ ├── pom.xml │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── apress │ │ │ │ │ └── messaging │ │ │ │ │ ├── RxJavaDemoApplication.java │ │ │ │ │ ├── domain │ │ │ │ │ └── Exchange.java │ │ │ │ │ └── service │ │ │ │ │ └── ExchangeService.java │ │ │ └── resources │ │ │ │ └── application.yaml │ │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── apress │ │ │ └── messaging │ │ │ └── RxJavaDemoApplicationTests.java │ ├── spring-web-flux-reactive │ │ ├── .gitignore │ │ ├── pom.xml │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── apress │ │ │ │ │ └── messaging │ │ │ │ │ ├── SpringWebFluxReactiveApplication.java │ │ │ │ │ ├── config │ │ │ │ │ └── ReactiveConfig.java │ │ │ │ │ ├── controller │ │ │ │ │ └── ReactiveController.java │ │ │ │ │ ├── domain │ │ │ │ │ └── Person.java │ │ │ │ │ └── repository │ │ │ │ │ └── PersonRepository.java │ │ │ └── resources │ │ │ │ └── application.properties │ │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── apress │ │ │ └── messaging │ │ │ └── SpringWebFluxReactiveApplicationTests.java │ ├── spring-web-flux │ │ ├── .gitignore │ │ ├── pom.xml │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── apress │ │ │ │ │ └── messaging │ │ │ │ │ ├── SpringWebFluxApplication.java │ │ │ │ │ ├── config │ │ │ │ │ └── ServerConfig.java │ │ │ │ │ ├── domain │ │ │ │ │ └── Person.java │ │ │ │ │ ├── handler │ │ │ │ │ └── PersonHandler.java │ │ │ │ │ └── repository │ │ │ │ │ └── PersonRepository.java │ │ │ └── resources │ │ │ │ └── application.properties │ │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── apress │ │ │ └── messaging │ │ │ └── SpringWebFluxApplicationTests.java │ └── web-emitter │ │ ├── .gitignore │ │ ├── pom.xml │ │ ├── random-names.txt │ │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── apress │ │ │ │ └── messaging │ │ │ │ ├── WebEmitterApplication.java │ │ │ │ ├── config │ │ │ │ ├── EmitterConfig.java │ │ │ │ └── EmitterProperties.java │ │ │ │ └── controller │ │ │ │ └── SimpleEmitterController.java │ │ └── resources │ │ │ └── application.properties │ │ └── test │ │ └── java │ │ └── com │ │ └── apress │ │ └── messaging │ │ └── WebEmitterApplicationTests.java └── ch11 │ ├── circuit-breaker-service-demo │ ├── .gitignore │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── apress │ │ │ │ └── messaging │ │ │ │ └── CircuitBreakerServiceDemoApplication.java │ │ └── resources │ │ │ └── application.properties │ │ └── test │ │ └── java │ │ └── com │ │ └── apress │ │ └── messaging │ │ └── CircuitBreakerServiceDemoApplicationTests.java │ ├── config-client-demo │ ├── .gitignore │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── apress │ │ │ │ └── messaging │ │ │ │ └── ConfigClientDemoApplication.java │ │ └── resources │ │ │ └── application.properties │ │ └── test │ │ └── java │ │ └── com │ │ └── apress │ │ └── messaging │ │ └── ConfigClientDemoApplicationTests.java │ ├── config-server-demo │ ├── .gitignore │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── apress │ │ │ │ └── messaging │ │ │ │ └── ConfigServerDemoApplication.java │ │ └── resources │ │ │ └── application.properties │ │ └── test │ │ └── java │ │ └── com │ │ └── apress │ │ └── messaging │ │ └── ConfigServerDemoApplicationTests.java │ ├── service-registry-client-demo │ ├── .gitignore │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── apress │ │ │ │ └── messaging │ │ │ │ └── ServiceRegistryClientDemoApplication.java │ │ └── resources │ │ │ └── application.properties │ │ └── test │ │ └── java │ │ └── com │ │ └── apress │ │ └── messaging │ │ └── ServiceRegistryClientDemoApplicationTests.java │ ├── service-registry-server-demo │ ├── .gitignore │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── apress │ │ │ │ └── messaging │ │ │ │ └── ServiceRegistryDemoApplication.java │ │ └── resources │ │ │ └── application.properties │ │ └── test │ │ └── java │ │ └── com │ │ └── apress │ │ └── messaging │ │ └── ServiceRegistryDemoApplicationTests.java │ └── service-registry-service-demo │ ├── .gitignore │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── apress │ │ │ └── messaging │ │ │ └── ServiceRegistryServiceDemoApplication.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── apress │ └── messaging │ └── ServiceRegistryServiceDemoApplicationTests.java ├── README.md └── contributing.md /LICENSE.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/spring-boot-messaging/02b8fff85fbfe7082e36872b73631af1dc3671bc/LICENSE.txt -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .factorypath 3 | .project 4 | .settings/ 5 | target/ 6 | 7 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/README.md: -------------------------------------------------------------------------------- 1 | # Spring Boot Messaging Book Code from Apress 2 | 3 | ![alt text](https://images.springer.com/sgw/books/medium/9781484212257.jpg "Spring Boot Messaging") 4 | 5 | Spring Boot Messaging 6 | Source Code 7 | 8 | [You can get it here](http://www.apress.com/us/book/9781484212257) 9 | 10 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch02/rest-api-demo/src/main/java/com/apress/messaging/RestApiDemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import java.util.Date; 4 | 5 | import org.springframework.boot.CommandLineRunner; 6 | import org.springframework.boot.SpringApplication; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | import org.springframework.context.annotation.Bean; 9 | 10 | import com.apress.messaging.domain.Rate; 11 | import com.apress.messaging.repository.RateRepository; 12 | 13 | @SpringBootApplication 14 | public class RestApiDemoApplication { 15 | 16 | public static void main(String[] args) { 17 | SpringApplication.run(RestApiDemoApplication.class, args); 18 | } 19 | 20 | @Bean 21 | public CommandLineRunner data(RateRepository repository) { 22 | return (args) -> { 23 | repository.save(new Rate("EUR",0.88857F,new Date())); 24 | repository.save(new Rate("JPY",102.17F,new Date())); 25 | repository.save(new Rate("MXN",19.232F,new Date())); 26 | repository.save(new Rate("GBP",0.75705F,new Date())); 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch02/rest-api-demo/src/main/java/com/apress/messaging/ServletInitializer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.springframework.boot.builder.SpringApplicationBuilder; 4 | import org.springframework.boot.web.support.SpringBootServletInitializer; 5 | 6 | public class ServletInitializer extends SpringBootServletInitializer { 7 | 8 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 9 | return application.sources(RestApiDemoApplication.class); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch02/rest-api-demo/src/main/java/com/apress/messaging/annotation/ToUpper.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.PARAMETER) 10 | public @interface ToUpper { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch02/rest-api-demo/src/main/java/com/apress/messaging/domain/CurrencyConversion.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.domain; 2 | 3 | public class CurrencyConversion { 4 | 5 | private String base; 6 | private String code; 7 | private float amount; 8 | private float total; 9 | 10 | public CurrencyConversion(){} 11 | 12 | public CurrencyConversion(String base, String code, float amount, float total) { 13 | super(); 14 | this.base = base; 15 | this.code = code; 16 | this.amount = amount; 17 | this.total = total; 18 | } 19 | 20 | public String getBase() { 21 | return base; 22 | } 23 | public void setBase(String base) { 24 | this.base = base; 25 | } 26 | public String getCode() { 27 | return code; 28 | } 29 | public void setCode(String code) { 30 | this.code = code; 31 | } 32 | public float getAmount() { 33 | return amount; 34 | } 35 | public void setAmount(float amount) { 36 | this.amount = amount; 37 | } 38 | public float getTotal() { 39 | return total; 40 | } 41 | public void setTotal(float total) { 42 | this.total = total; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch02/rest-api-demo/src/main/java/com/apress/messaging/domain/CurrencyExchange.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.domain; 2 | 3 | public class CurrencyExchange { 4 | 5 | public static final String BASE_CODE = "USD"; 6 | private String base; 7 | private String date; 8 | private Rate[] rates; 9 | 10 | public CurrencyExchange(String base, String date, Rate[] rates) { 11 | super(); 12 | this.base = base; 13 | this.date = date; 14 | this.rates = rates; 15 | } 16 | 17 | public String getBase() { 18 | return base; 19 | } 20 | public void setBase(String base) { 21 | this.base = base; 22 | } 23 | public String getDate() { 24 | return date; 25 | } 26 | public void setDate(String date) { 27 | this.date = date; 28 | } 29 | public Rate[] getRates() { 30 | return rates; 31 | } 32 | public void setRates(Rate[] rates) { 33 | this.rates = rates; 34 | } 35 | 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch02/rest-api-demo/src/main/java/com/apress/messaging/repository/RateRepository.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.repository; 2 | 3 | import java.util.Date; 4 | import java.util.List; 5 | 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | 8 | import com.apress.messaging.domain.Rate; 9 | 10 | public interface RateRepository extends JpaRepository{ 11 | List findByDate(Date date); 12 | Rate findByDateAndCode(Date date,String code); 13 | } 14 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch02/rest-api-demo/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #spring.h2.console.enabled=true 2 | #server.error.whitelabel.enabled=false 3 | 4 | #spring.aop.auto=true 5 | #spring.aop.proxy-target-class=true 6 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch02/rest-api-demo/src/main/resources/public/error/4xx.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Error: BAD REQUEST!

4 |

5 | Take a look at the Body/Path/Parameter format. 6 |

7 | 8 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch02/rest-api-demo/src/main/resources/public/error/5xx.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Error: BAD REQUEST!

4 |

5 | Take a look at the Body/Path/Parameter format. 6 |

7 | 8 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch02/rest-api-demo/src/test/java/com/apress/messaging/RestApiDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class RestApiDemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch03/rest-api-events/src/main/java/com/apress/messaging/RestApiEventsApplication.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import java.util.Date; 4 | 5 | import org.springframework.boot.CommandLineRunner; 6 | import org.springframework.boot.SpringApplication; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | import org.springframework.context.annotation.Bean; 9 | 10 | import com.apress.messaging.domain.Rate; 11 | import com.apress.messaging.service.CurrencyService; 12 | 13 | @SpringBootApplication 14 | public class RestApiEventsApplication { 15 | 16 | public static void main(String[] args) { 17 | SpringApplication.run(RestApiEventsApplication.class, args); 18 | } 19 | 20 | @Bean 21 | public CommandLineRunner data(CurrencyService service) { 22 | return (args) -> { 23 | service.saveRate(new Rate("EUR",0.88857F,new Date())); 24 | service.saveRate(new Rate("JPY",102.17F,new Date())); 25 | service.saveRate(new Rate("MXN",19.232F,new Date())); 26 | service.saveRate(new Rate("GBP",0.75705F,new Date())); 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch03/rest-api-events/src/main/java/com/apress/messaging/ServletInitializer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.springframework.boot.builder.SpringApplicationBuilder; 4 | import org.springframework.boot.web.support.SpringBootServletInitializer; 5 | 6 | public class ServletInitializer extends SpringBootServletInitializer { 7 | 8 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 9 | return application.sources(RestApiEventsApplication.class); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch03/rest-api-events/src/main/java/com/apress/messaging/annotation/Log.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.METHOD) 10 | public @interface Log { 11 | boolean printParamsValues() default false; 12 | String callMethodWithNoParamsToString() default "toString"; 13 | } 14 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch03/rest-api-events/src/main/java/com/apress/messaging/annotation/ToUpper.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.PARAMETER) 10 | public @interface ToUpper { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch03/rest-api-events/src/main/java/com/apress/messaging/domain/CurrencyExchange.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.domain; 2 | 3 | import java.util.Arrays; 4 | 5 | public class CurrencyExchange { 6 | 7 | public static final String BASE_CODE = "USD"; 8 | private String base; 9 | private String date; 10 | private Rate[] rates; 11 | 12 | public CurrencyExchange(String base, String date, Rate[] rates) { 13 | super(); 14 | this.base = base; 15 | this.date = date; 16 | this.rates = rates; 17 | } 18 | 19 | public String getBase() { 20 | return base; 21 | } 22 | public void setBase(String base) { 23 | this.base = base; 24 | } 25 | public String getDate() { 26 | return date; 27 | } 28 | public void setDate(String date) { 29 | this.date = date; 30 | } 31 | public Rate[] getRates() { 32 | return rates; 33 | } 34 | public void setRates(Rate[] rates) { 35 | this.rates = rates; 36 | } 37 | 38 | @Override 39 | public String toString() { 40 | return "CurrencyExchange [base=" + base + ", date=" + date + ", rates=" + Arrays.toString(rates) + "]"; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch03/rest-api-events/src/main/java/com/apress/messaging/event/CurrencyConversionEvent.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.event; 2 | 3 | import org.springframework.context.ApplicationEvent; 4 | 5 | import com.apress.messaging.domain.CurrencyConversion; 6 | 7 | public class CurrencyConversionEvent extends ApplicationEvent { 8 | 9 | private static final long serialVersionUID = -4481493963350551884L; 10 | private CurrencyConversion conversion; 11 | private String message; 12 | 13 | public CurrencyConversionEvent(Object source, CurrencyConversion conversion) { 14 | super(source); 15 | this.conversion = conversion; 16 | } 17 | 18 | public CurrencyConversionEvent(Object source, String message, CurrencyConversion conversion) { 19 | super(source); 20 | this.message = message; 21 | this.conversion = conversion; 22 | } 23 | 24 | public CurrencyConversion getConversion(){ 25 | return conversion; 26 | } 27 | 28 | public String getMessage(){ 29 | return message; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch03/rest-api-events/src/main/java/com/apress/messaging/event/CurrencyEvent.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.event; 2 | 3 | import org.springframework.context.ApplicationEvent; 4 | 5 | import com.apress.messaging.domain.Rate; 6 | 7 | public class CurrencyEvent extends ApplicationEvent { 8 | 9 | private static final long serialVersionUID = 889202626288526113L; 10 | private Rate rate; 11 | 12 | public CurrencyEvent(Object source,Rate rate) { 13 | super(source); 14 | this.rate = rate; 15 | } 16 | 17 | public Rate getRate(){ 18 | return this.rate; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch03/rest-api-events/src/main/java/com/apress/messaging/exception/BadCodeRuntimeException.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.exception; 2 | 3 | import com.apress.messaging.domain.CurrencyConversion; 4 | import com.apress.messaging.domain.Rate; 5 | 6 | public class BadCodeRuntimeException extends RuntimeException { 7 | 8 | private static final long serialVersionUID = -2411444965751028974L; 9 | private CurrencyConversion conversion; 10 | private Rate rate; 11 | 12 | public BadCodeRuntimeException(String message) { 13 | super(message); 14 | } 15 | 16 | public BadCodeRuntimeException(String message,CurrencyConversion conversion) { 17 | super(message); 18 | this.conversion = conversion; 19 | } 20 | 21 | public BadCodeRuntimeException(String message,Rate rate) { 22 | super(message); 23 | this.rate = rate; 24 | } 25 | 26 | public CurrencyConversion getConversion(){ 27 | return conversion; 28 | } 29 | 30 | public Rate getRate(){ 31 | return rate; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch03/rest-api-events/src/main/java/com/apress/messaging/listener/RateEventListener.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.listener; 2 | 3 | import org.springframework.stereotype.Component; 4 | import org.springframework.transaction.event.TransactionalEventListener; 5 | 6 | import com.apress.messaging.annotation.Log; 7 | import com.apress.messaging.event.CurrencyEvent; 8 | 9 | @Component 10 | public class RateEventListener { 11 | 12 | //@TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT) 13 | @TransactionalEventListener 14 | @Log(printParamsValues=true,callMethodWithNoParamsToString="getRate") 15 | public void processEvent(CurrencyEvent event){ } 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch03/rest-api-events/src/main/java/com/apress/messaging/listener/RestAppEventListener.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.listener; 2 | 3 | import org.springframework.boot.context.event.SpringApplicationEvent; 4 | import org.springframework.context.event.EventListener; 5 | import org.springframework.stereotype.Component; 6 | 7 | import com.apress.messaging.annotation.Log; 8 | 9 | @Component 10 | public class RestAppEventListener { 11 | 12 | //@EventListener(condition = "#springApp.args.length > 1") 13 | //@EventListener({CurrencyEvent.class,CurrencyConversionEvent.class}) 14 | //@Order(Ordered.HIGHEST_PRECEDENCE) 15 | //@Async 16 | @EventListener 17 | @Log(printParamsValues=true) 18 | public void restAppHandler(SpringApplicationEvent springApp){ 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch03/rest-api-events/src/main/java/com/apress/messaging/repository/RateRepository.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.repository; 2 | 3 | import java.util.Date; 4 | import java.util.List; 5 | 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | 8 | import com.apress.messaging.domain.Rate; 9 | 10 | public interface RateRepository extends JpaRepository{ 11 | List findByDate(Date date); 12 | Rate findByDateAndCode(Date date,String code); 13 | } 14 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch03/rest-api-events/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #spring.h2.console.enabled=true 2 | #server.error.whitelabel.enabled=false 3 | 4 | #spring.aop.auto=true 5 | #spring.aop.proxy-target-class=true 6 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch03/rest-api-events/src/main/resources/public/error/4xx.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Error: BAD REQUEST!

4 |

5 | Take a look at the Body/Path/Parameter format. 6 |

7 | 8 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch03/rest-api-events/src/main/resources/public/error/5xx.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Error: BAD REQUEST!

4 |

5 | Take a look at the Body/Path/Parameter format. 6 |

7 | 8 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch03/rest-api-events/src/test/java/com/apress/messaging/RestApiEventsApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class RestApiEventsApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/jms-sender/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/jms-sender/src/main/java/com/apress/messaging/ServletInitializer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.springframework.boot.builder.SpringApplicationBuilder; 4 | import org.springframework.boot.web.support.SpringBootServletInitializer; 5 | 6 | public class ServletInitializer extends SpringBootServletInitializer { 7 | 8 | @Override 9 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 10 | return application.sources(JmsSenderApplication.class); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/jms-sender/src/main/java/com/apress/messaging/config/JMSProperties.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | @ConfigurationProperties(prefix="apress.jms") 6 | public class JMSProperties { 7 | 8 | private String queue; 9 | private String rateQueue; 10 | private String rateReplyQueue; 11 | private String topic; 12 | 13 | public String getQueue() { 14 | return queue; 15 | } 16 | public void setQueue(String queue) { 17 | this.queue = queue; 18 | } 19 | public String getRateQueue() { 20 | return rateQueue; 21 | } 22 | public void setRateQueue(String rateQueue) { 23 | this.rateQueue = rateQueue; 24 | } 25 | public String getRateReplyQueue() { 26 | return rateReplyQueue; 27 | } 28 | public void setRateReplyQueue(String rateReplyQueue) { 29 | this.rateReplyQueue = rateReplyQueue; 30 | } 31 | public String getTopic() { 32 | return topic; 33 | } 34 | public void setTopic(String topic) { 35 | this.topic = topic; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/jms-sender/src/main/java/com/apress/messaging/domain/Rate.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.domain; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | 6 | public class Rate { 7 | 8 | private String code; 9 | private Float rate; 10 | private Date date; 11 | 12 | public Rate() { 13 | } 14 | 15 | public Rate(String base, Float rate, Date date) { 16 | super(); 17 | this.code = base; 18 | this.rate = rate; 19 | this.date = date; 20 | } 21 | 22 | public String getCode() { 23 | return code; 24 | } 25 | 26 | public void setCode(String code) { 27 | this.code = code; 28 | } 29 | 30 | public Float getRate() { 31 | return rate; 32 | } 33 | 34 | public void setRate(Float rate) { 35 | this.rate = rate; 36 | } 37 | 38 | public Date getDate() { 39 | return date; 40 | } 41 | 42 | public void setDate(Date date) { 43 | this.date = date; 44 | } 45 | 46 | @Override 47 | public String toString() { 48 | String format = new SimpleDateFormat("yyyy-MM-dd").format(date); 49 | return "Rate [code=" + code + ", rate=" + rate + ", date=" + format + "]"; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/jms-sender/src/main/java/com/apress/messaging/jms/AnnotatedReceiver.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.jms; 2 | 3 | import org.springframework.jms.annotation.JmsListener; 4 | 5 | //@Component 6 | public class AnnotatedReceiver { 7 | 8 | @JmsListener(destination = "${apress.jms.queue}") 9 | public void processMessage(String content) { 10 | 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/jms-sender/src/main/java/com/apress/messaging/jms/QueueListener.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.jms; 2 | 3 | import javax.jms.Message; 4 | import javax.jms.MessageListener; 5 | 6 | //@Component 7 | public class QueueListener implements MessageListener { 8 | 9 | public void onMessage(Message message) { 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/jms-sender/src/main/java/com/apress/messaging/jms/RateReceiver.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.jms; 2 | 3 | import org.springframework.jms.annotation.JmsListener; 4 | 5 | import com.apress.messaging.domain.Rate; 6 | 7 | //@Component 8 | public class RateReceiver { 9 | 10 | @JmsListener(destination = "${apress.jms.rate-queue}") 11 | public void processRate(Rate rate){ 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/jms-sender/src/main/java/com/apress/messaging/jms/RateReplyReceiver.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.jms; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | import java.util.UUID; 6 | 7 | import org.springframework.jms.annotation.JmsListener; 8 | import org.springframework.messaging.Message; 9 | import org.springframework.messaging.handler.annotation.SendTo; 10 | import org.springframework.messaging.support.MessageBuilder; 11 | 12 | import com.apress.messaging.domain.Rate; 13 | 14 | //@Component 15 | public class RateReplyReceiver { 16 | 17 | 18 | @JmsListener(destination = "${apress.jms.rate-queue}") 19 | @SendTo("${apress.jms.rate-reply-queue}") 20 | public Message processRate(Rate rate){ 21 | 22 | //Process the Rate and return any significant value 23 | 24 | return MessageBuilder 25 | .withPayload("PROCCESSED") 26 | .setHeader("CODE", rate.getCode()) 27 | .setHeader("RATE", rate.getRate()) 28 | .setHeader("ID", UUID.randomUUID().toString()) 29 | .setHeader("DATE", new SimpleDateFormat("yyyy-MM-dd").format(new Date())) 30 | .build(); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/jms-sender/src/main/java/com/apress/messaging/jms/RateSender.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.jms; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.jms.core.JmsTemplate; 5 | import org.springframework.stereotype.Component; 6 | 7 | import com.apress.messaging.domain.Rate; 8 | 9 | @Component 10 | public class RateSender { 11 | 12 | private JmsTemplate jmsTemplate; 13 | 14 | @Autowired 15 | public RateSender(JmsTemplate jmsTemplate){ 16 | this.jmsTemplate = jmsTemplate; 17 | } 18 | 19 | public void sendCurrency(String destination, Rate rate){ 20 | this.jmsTemplate.convertAndSend(destination,rate); 21 | } 22 | 23 | /* This code is for the reply-to-queue section 24 | 25 | @JmsListener(destination="${apress.jms.rate-reply-queue}") 26 | public void process(String body,@Header("CODE") String code){ 27 | 28 | } 29 | 30 | */ 31 | } 32 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/jms-sender/src/main/java/com/apress/messaging/jms/SimpleSender.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.jms; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.jms.core.JmsTemplate; 5 | import org.springframework.stereotype.Component; 6 | 7 | @Component 8 | public class SimpleSender { 9 | 10 | private JmsTemplate jmsTemplate; 11 | 12 | @Autowired 13 | public SimpleSender(JmsTemplate jmsTemplate){ 14 | this.jmsTemplate = jmsTemplate; 15 | } 16 | 17 | public void sendMessage(String destination, String message){ 18 | this.jmsTemplate.convertAndSend(destination, message); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/jms-sender/src/main/resources/META-INF/additional-spring-configuration-metadata.json: -------------------------------------------------------------------------------- 1 | {"properties": [{ 2 | "name": "apress.jms.queue", 3 | "type": "java.lang.String", 4 | "description": "The queue name" 5 | },{ 6 | "name": "apress.jms.topic", 7 | "type": "java.lang.String", 8 | "description": "The topic name" 9 | },{ 10 | "name": "apress.jms.rate-queue", 11 | "type": "java.lang.String", 12 | "description": "The Rate queue name" 13 | 14 | },{ 15 | "name": "apress.jms.rate-reply-queue", 16 | "type": "java.lang.String", 17 | "description": "The Rate reply queue name" 18 | 19 | }]} 20 | 21 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/jms-sender/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # Spring Web 2 | spring.main.web-environment=false 3 | 4 | #Jackson 5 | #spring.jackson.date-format=yyyy-MM-dd 6 | 7 | #Default ActiveMQ properties 8 | spring.activemq.broker-url=tcp://localhost:61616 9 | spring.activemq.user=admin 10 | spring.activemq.password=admin 11 | 12 | 13 | #Apress Configuration 14 | apress.jms.queue=jms-demo 15 | apress.jms.rate-queue=rates 16 | apress.jms.rate-reply-queue=reply-rate 17 | 18 | 19 | #Enable Topic Messaging 20 | #spring.jms.pub-sub-domain=true 21 | 22 | #Apress Topic Configuration 23 | apress.jms.topic=rate-topic 24 | 25 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/jms-sender/src/test/java/com/apress/messaging/JmsSenderApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class JmsSenderApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/jms-topic-subscriber/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/jms-topic-subscriber/src/main/java/com/apress/messaging/JmsTopicSubscriberApplication.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class JmsTopicSubscriberApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(JmsTopicSubscriberApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/jms-topic-subscriber/src/main/java/com/apress/messaging/ServletInitializer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.springframework.boot.builder.SpringApplicationBuilder; 4 | import org.springframework.boot.web.support.SpringBootServletInitializer; 5 | 6 | public class ServletInitializer extends SpringBootServletInitializer { 7 | 8 | @Override 9 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 10 | return application.sources(JmsTopicSubscriberApplication.class); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/jms-topic-subscriber/src/main/java/com/apress/messaging/config/JMSProperties.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | @ConfigurationProperties(prefix="apress.jms") 6 | public class JMSProperties { 7 | 8 | private String topic; 9 | 10 | public String getTopic() { 11 | return topic; 12 | } 13 | 14 | public void setTopic(String topic) { 15 | this.topic = topic; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/jms-topic-subscriber/src/main/java/com/apress/messaging/domain/Rate.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.domain; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | 6 | public class Rate { 7 | 8 | private String code; 9 | private Float rate; 10 | private Date date; 11 | 12 | public Rate() { 13 | } 14 | 15 | public Rate(String base, Float rate, Date date) { 16 | super(); 17 | this.code = base; 18 | this.rate = rate; 19 | this.date = date; 20 | } 21 | 22 | public String getCode() { 23 | return code; 24 | } 25 | 26 | public void setCode(String code) { 27 | this.code = code; 28 | } 29 | 30 | public Float getRate() { 31 | return rate; 32 | } 33 | 34 | public void setRate(Float rate) { 35 | this.rate = rate; 36 | } 37 | 38 | public Date getDate() { 39 | return date; 40 | } 41 | 42 | public void setDate(Date date) { 43 | this.date = date; 44 | } 45 | 46 | @Override 47 | public String toString() { 48 | String format = new SimpleDateFormat("yyyy-MM-dd").format(date); 49 | return "Rate [code=" + code + ", rate=" + rate + ", date=" + format + "]"; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/jms-topic-subscriber/src/main/java/com/apress/messaging/jms/RateTopicReceiver.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.jms; 2 | 3 | import org.springframework.jms.annotation.JmsListener; 4 | import org.springframework.stereotype.Component; 5 | 6 | import com.apress.messaging.domain.Rate; 7 | 8 | @Component 9 | public class RateTopicReceiver { 10 | 11 | @JmsListener(destination = "${apress.jms.topic}") 12 | public void processTopicRate(Rate rate){ 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/jms-topic-subscriber/src/main/resources/META-INF/additional-spring-configuration-metadata.json: -------------------------------------------------------------------------------- 1 | {"properties": [{ 2 | "name": "apress.jms.topic", 3 | "type": "java.lang.String", 4 | "description": "The topic name" 5 | }]} -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/jms-topic-subscriber/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # Spring Web 2 | spring.main.web-environment=false 3 | 4 | #Default ActiveMQ properties 5 | spring.activemq.broker-url=tcp://localhost:61616 6 | spring.activemq.user=admin 7 | spring.activemq.password=admin 8 | 9 | #Enable Topic 10 | spring.jms.pub-sub-domain=true 11 | 12 | #Apress Topic Configuration 13 | apress.jms.topic=rates 14 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/jms-topic-subscriber/src/test/java/com/apress/messaging/JmsTopicSubscriberApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class JmsTopicSubscriberApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/rest-api-jms/src/main/java/com/apress/messaging/RestApiJMSApplication.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class RestApiJMSApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(RestApiJMSApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/rest-api-jms/src/main/java/com/apress/messaging/ServletInitializer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.springframework.boot.builder.SpringApplicationBuilder; 4 | import org.springframework.boot.web.support.SpringBootServletInitializer; 5 | 6 | public class ServletInitializer extends SpringBootServletInitializer { 7 | 8 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 9 | return application.sources(RestApiJMSApplication.class); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/rest-api-jms/src/main/java/com/apress/messaging/annotation/Log.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.METHOD) 10 | public @interface Log { 11 | boolean printParamsValues() default false; 12 | String callMethodWithNoParamsToString() default "toString"; 13 | } 14 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/rest-api-jms/src/main/java/com/apress/messaging/annotation/ToUpper.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.PARAMETER) 10 | public @interface ToUpper { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/rest-api-jms/src/main/java/com/apress/messaging/config/RateJmsConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.config; 2 | 3 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.jms.support.converter.MappingJackson2MessageConverter; 7 | import org.springframework.jms.support.converter.MessageConverter; 8 | import org.springframework.jms.support.converter.MessageType; 9 | 10 | @Configuration 11 | @EnableConfigurationProperties(RateProperties.class) 12 | public class RateJmsConfiguration { 13 | 14 | @Bean 15 | public MessageConverter jacksonJmsMessageConverter() { 16 | MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(); 17 | converter.setTargetType(MessageType.TEXT); 18 | converter.setTypeIdPropertyName("_class_"); // This value can be anything, it will save the JSON class name and it must be the same for sender/receiver 19 | return converter; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/rest-api-jms/src/main/java/com/apress/messaging/config/RateProperties.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | @ConfigurationProperties(prefix="rate.jms") 6 | public class RateProperties { 7 | 8 | private String queueName; 9 | private String replyQueueName; 10 | 11 | public String getQueueName() { 12 | return queueName; 13 | } 14 | 15 | public void setQueueName(String queueName) { 16 | this.queueName = queueName; 17 | } 18 | 19 | public String getReplyQueueName() { 20 | return replyQueueName; 21 | } 22 | 23 | public void setReplyQueueName(String replyQueueName) { 24 | this.replyQueueName = replyQueueName; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/rest-api-jms/src/main/java/com/apress/messaging/domain/CurrencyExchange.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.domain; 2 | 3 | import java.util.Arrays; 4 | 5 | public class CurrencyExchange { 6 | 7 | public static final String BASE_CODE = "USD"; 8 | private String base; 9 | private String date; 10 | private Rate[] rates; 11 | 12 | public CurrencyExchange(String base, String date, Rate[] rates) { 13 | super(); 14 | this.base = base; 15 | this.date = date; 16 | this.rates = rates; 17 | } 18 | 19 | public String getBase() { 20 | return base; 21 | } 22 | public void setBase(String base) { 23 | this.base = base; 24 | } 25 | public String getDate() { 26 | return date; 27 | } 28 | public void setDate(String date) { 29 | this.date = date; 30 | } 31 | public Rate[] getRates() { 32 | return rates; 33 | } 34 | public void setRates(Rate[] rates) { 35 | this.rates = rates; 36 | } 37 | 38 | @Override 39 | public String toString() { 40 | return "CurrencyExchange [base=" + base + ", date=" + date + ", rates=" + Arrays.toString(rates) + "]"; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/rest-api-jms/src/main/java/com/apress/messaging/event/CurrencyConversionEvent.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.event; 2 | 3 | import org.springframework.context.ApplicationEvent; 4 | 5 | import com.apress.messaging.domain.CurrencyConversion; 6 | 7 | public class CurrencyConversionEvent extends ApplicationEvent { 8 | 9 | private static final long serialVersionUID = -4481493963350551884L; 10 | private CurrencyConversion conversion; 11 | private String message; 12 | 13 | public CurrencyConversionEvent(Object source, CurrencyConversion conversion) { 14 | super(source); 15 | this.conversion = conversion; 16 | } 17 | 18 | public CurrencyConversionEvent(Object source, String message, CurrencyConversion conversion) { 19 | super(source); 20 | this.message = message; 21 | this.conversion = conversion; 22 | } 23 | 24 | public CurrencyConversion getConversion(){ 25 | return conversion; 26 | } 27 | 28 | public String getMessage(){ 29 | return message; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/rest-api-jms/src/main/java/com/apress/messaging/event/CurrencyEvent.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.event; 2 | 3 | import org.springframework.context.ApplicationEvent; 4 | 5 | import com.apress.messaging.domain.Rate; 6 | 7 | public class CurrencyEvent extends ApplicationEvent { 8 | 9 | private static final long serialVersionUID = 889202626288526113L; 10 | private Rate rate; 11 | 12 | public CurrencyEvent(Object source,Rate rate) { 13 | super(source); 14 | this.rate = rate; 15 | } 16 | 17 | public Rate getRate(){ 18 | return this.rate; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/rest-api-jms/src/main/java/com/apress/messaging/exception/BadCodeRuntimeException.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.exception; 2 | 3 | import com.apress.messaging.domain.CurrencyConversion; 4 | import com.apress.messaging.domain.Rate; 5 | 6 | public class BadCodeRuntimeException extends RuntimeException { 7 | 8 | private static final long serialVersionUID = -2411444965751028974L; 9 | private CurrencyConversion conversion; 10 | private Rate rate; 11 | 12 | public BadCodeRuntimeException(String message) { 13 | super(message); 14 | } 15 | 16 | public BadCodeRuntimeException(String message,CurrencyConversion conversion) { 17 | super(message); 18 | this.conversion = conversion; 19 | } 20 | 21 | public BadCodeRuntimeException(String message,Rate rate) { 22 | super(message); 23 | this.rate = rate; 24 | } 25 | 26 | public CurrencyConversion getConversion(){ 27 | return conversion; 28 | } 29 | 30 | public Rate getRate(){ 31 | return rate; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/rest-api-jms/src/main/java/com/apress/messaging/listener/RateEventListener.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.listener; 2 | 3 | import org.springframework.stereotype.Component; 4 | import org.springframework.transaction.event.TransactionalEventListener; 5 | 6 | import com.apress.messaging.annotation.Log; 7 | import com.apress.messaging.event.CurrencyEvent; 8 | 9 | @Component 10 | public class RateEventListener { 11 | 12 | //@TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT) 13 | @TransactionalEventListener 14 | @Log(printParamsValues=true,callMethodWithNoParamsToString="getRate") 15 | public void processEvent(CurrencyEvent event){ } 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/rest-api-jms/src/main/java/com/apress/messaging/listener/RestApiEventsListener.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.listener; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.actuate.metrics.CounterService; 5 | import org.springframework.context.ApplicationEvent; 6 | import org.springframework.context.ApplicationListener; 7 | import org.springframework.stereotype.Component; 8 | import org.springframework.web.context.support.ServletRequestHandledEvent; 9 | 10 | import com.apress.messaging.annotation.Log; 11 | 12 | @Component 13 | public class RestApiEventsListener implements ApplicationListener{ 14 | 15 | private static final String LATEST = "/currency/latest"; 16 | 17 | @Autowired 18 | private CounterService counterService; 19 | 20 | @Log(printParamsValues=true) 21 | public void onApplicationEvent(ApplicationEvent event) { 22 | if(event instanceof ServletRequestHandledEvent){ 23 | if(((ServletRequestHandledEvent)event).getRequestUrl().equals(LATEST)){ 24 | counterService.increment("url.currency.lastest.hits"); 25 | } 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/rest-api-jms/src/main/java/com/apress/messaging/listener/RestAppEventListener.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.listener; 2 | 3 | import org.springframework.boot.context.event.SpringApplicationEvent; 4 | import org.springframework.context.event.EventListener; 5 | import org.springframework.stereotype.Component; 6 | 7 | import com.apress.messaging.annotation.Log; 8 | 9 | @Component 10 | public class RestAppEventListener { 11 | 12 | //@EventListener(condition = "#springApp.args.length > 1") 13 | //@EventListener({CurrencyEvent.class,CurrencyConversionEvent.class}) 14 | //@Order(Ordered.HIGHEST_PRECEDENCE) 15 | //@Async 16 | @EventListener 17 | @Log(printParamsValues=true) 18 | public void restAppHandler(SpringApplicationEvent springApp){ 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/rest-api-jms/src/main/java/com/apress/messaging/repository/RateRepository.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.repository; 2 | 3 | import java.util.Date; 4 | import java.util.List; 5 | 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | 8 | import com.apress.messaging.domain.Rate; 9 | 10 | public interface RateRepository extends JpaRepository{ 11 | List findByDate(Date date); 12 | Rate findByDateAndCode(Date date,String code); 13 | } 14 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/rest-api-jms/src/main/resources/META-INF/additional-spring-configuration-metadata.json: -------------------------------------------------------------------------------- 1 | {"properties": [{ 2 | "name": "rate.jms.queue-name", 3 | "type": "java.lang.String", 4 | "description": "The Rate Queue name" 5 | },{ 6 | "name": "rate.jms.reply-queue-name", 7 | "type": "java.lang.String", 8 | "description": "The Reply Rate Queue name" 9 | }]} -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/rest-api-jms/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #spring.h2.console.enabled=true 2 | #server.error.whitelabel.enabled=false 3 | 4 | #spring.aop.auto=true 5 | #spring.aop.proxy-target-class=true 6 | 7 | #Jackson 8 | #spring.jackson.date-format=yyyy-MM-dd 9 | 10 | #Default ActiveMQ properties 11 | spring.activemq.broker-url=tcp://localhost:61616 12 | spring.activemq.user=admin 13 | spring.activemq.password=admin 14 | 15 | #Rate App 16 | rate.jms.queue-name=rates 17 | rate.jms.reply-queue-name=reply-rate -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/rest-api-jms/src/main/resources/public/error/4xx.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Error: BAD REQUEST!

4 |

5 | Take a look at the Body/Path/Parameter format. 6 |

7 | 8 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/rest-api-jms/src/main/resources/public/error/5xx.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Error: BAD REQUEST!

4 |

5 | Take a look at the Body/Path/Parameter format. 6 |

7 | 8 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch04/rest-api-jms/src/test/java/com/apress/messaging/RestApiJMSApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class RestApiJMSApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/amqp-demo/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/amqp-demo/src/main/java/com/apress/messaging/ServletInitializer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.springframework.boot.builder.SpringApplicationBuilder; 4 | import org.springframework.boot.web.support.SpringBootServletInitializer; 5 | 6 | public class ServletInitializer extends SpringBootServletInitializer { 7 | 8 | @Override 9 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 10 | return application.sources(AmqpDemoApplication.class); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/amqp-demo/src/main/java/com/apress/messaging/amqp/AnnotatedConsumer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.amqp; 2 | 3 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 4 | 5 | //@Component 6 | public class AnnotatedConsumer { 7 | 8 | @RabbitListener(queues="${apress.amqp.queue}") 9 | public void process(String message){ 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/amqp-demo/src/main/java/com/apress/messaging/amqp/Consumer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.amqp; 2 | 3 | import org.springframework.amqp.core.Message; 4 | import org.springframework.amqp.core.MessageListener; 5 | 6 | //@Component 7 | public class Consumer implements MessageListener{ 8 | 9 | public void onMessage(Message message) { 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/amqp-demo/src/main/java/com/apress/messaging/amqp/Producer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.amqp; 2 | 3 | import org.springframework.amqp.rabbit.core.RabbitTemplate; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.stereotype.Component; 6 | 7 | @Component 8 | public class Producer { 9 | 10 | private RabbitTemplate template; 11 | 12 | @Autowired 13 | public Producer(RabbitTemplate template){ 14 | this.template = template; 15 | } 16 | 17 | public void sendMessage(String exchange,String routingKey, String message){ 18 | this.template.convertAndSend(exchange,routingKey, message); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/amqp-demo/src/main/java/com/apress/messaging/amqp/RateConsumer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.amqp; 2 | 3 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 4 | 5 | import com.apress.messaging.domain.Rate; 6 | 7 | //@Component 8 | public class RateConsumer { 9 | 10 | @RabbitListener(queues="${apress.amqp.rate-queue}") 11 | public void messageHandler(Rate rate){ 12 | 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/amqp-demo/src/main/java/com/apress/messaging/amqp/RateProducer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.amqp; 2 | 3 | import org.springframework.amqp.rabbit.core.RabbitTemplate; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | 6 | import com.apress.messaging.domain.Rate; 7 | 8 | //@Component 9 | public class RateProducer { 10 | 11 | private RabbitTemplate template; 12 | 13 | @Autowired 14 | public RateProducer(RabbitTemplate template) { 15 | this.template = template; 16 | } 17 | 18 | public void sendRate(String exchange, String routingKey, Rate rate) { 19 | this.template.convertAndSend(exchange, routingKey, rate); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/amqp-demo/src/main/java/com/apress/messaging/amqp/ReplyToService.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.amqp; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | import java.util.UUID; 6 | 7 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 8 | import org.springframework.messaging.Message; 9 | import org.springframework.messaging.handler.annotation.SendTo; 10 | import org.springframework.messaging.support.MessageBuilder; 11 | 12 | //@Component 13 | public class ReplyToService { 14 | 15 | @RabbitListener(queues="${apress.amqp.queue}") 16 | @SendTo("${apress.amqp.reply-exchange-queue}") 17 | public Message replyToProcess(String message){ 18 | 19 | //More Processing here... 20 | 21 | return MessageBuilder 22 | .withPayload("PROCESSED:OK") 23 | .setHeader("PROCESSED", new SimpleDateFormat("yyyy-MM-dd").format(new Date())) 24 | .setHeader("CODE", UUID.randomUUID().toString()) 25 | .build(); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/amqp-demo/src/main/java/com/apress/messaging/amqp/RpcClient.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.amqp; 2 | 3 | 4 | import org.springframework.amqp.rabbit.core.RabbitTemplate; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | 7 | //@Component 8 | public class RpcClient { 9 | 10 | private RabbitTemplate template; 11 | 12 | @Autowired 13 | public RpcClient(RabbitTemplate template) { 14 | this.template = template; 15 | } 16 | 17 | public Object sendMessage(String exchange, String routingKey, String message) { 18 | Object response = this.template.convertSendAndReceive(exchange, routingKey, message); 19 | return response; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/amqp-demo/src/main/java/com/apress/messaging/amqp/RpcServer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.amqp; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | import java.util.UUID; 6 | 7 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 8 | import org.springframework.messaging.Message; 9 | import org.springframework.messaging.support.MessageBuilder; 10 | 11 | //@Component 12 | public class RpcServer { 13 | 14 | @RabbitListener(queues="${apress.amqp.queue}") 15 | //@SendTo("${apress.amqp.reply-exchange-queue}") //Used when the client doesn't set replyTo. 16 | public Message process(String message){ 17 | 18 | //More Processing here... 19 | 20 | return MessageBuilder 21 | .withPayload("PROCESSED:OK") 22 | .setHeader("PROCESSED", new SimpleDateFormat("yyyy-MM-dd").format(new Date())) 23 | .setHeader("CODE", UUID.randomUUID().toString()) 24 | .build(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/amqp-demo/src/main/java/com/apress/messaging/domain/Invoice.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.domain; 2 | 3 | public class Invoice { 4 | 5 | private Float total; 6 | 7 | public Float getTotal() { 8 | return total; 9 | } 10 | 11 | public void setTotal(Float total) { 12 | this.total = total; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/amqp-demo/src/main/java/com/apress/messaging/domain/InvoiceWithTax.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.domain; 2 | 3 | public class InvoiceWithTax { 4 | 5 | private Float tax; 6 | private Float subTotal; 7 | private Float total; 8 | 9 | public Float getTax() { 10 | return tax; 11 | } 12 | 13 | public void setTax(Float tax) { 14 | this.tax = tax; 15 | } 16 | 17 | public Float getTotal() { 18 | return total; 19 | } 20 | 21 | public void setTotal(Float total) { 22 | this.total = total; 23 | } 24 | 25 | public Float getSubTotal() { 26 | return subTotal; 27 | } 28 | 29 | public void setSubTotal(Float subTotal) { 30 | this.subTotal = subTotal; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/amqp-demo/src/main/java/com/apress/messaging/domain/Item.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.domain; 2 | 3 | public class Item { 4 | 5 | private String id; 6 | private String name; 7 | private String label; 8 | private String description; 9 | private Float unitPrice; 10 | 11 | public String getId() { 12 | return id; 13 | } 14 | 15 | public void setId(String id) { 16 | this.id = id; 17 | } 18 | 19 | public String getName() { 20 | return name; 21 | } 22 | 23 | public void setName(String name) { 24 | this.name = name; 25 | } 26 | 27 | public String getLabel() { 28 | return label; 29 | } 30 | 31 | public void setLabel(String label) { 32 | this.label = label; 33 | } 34 | 35 | public String getDescription() { 36 | return description; 37 | } 38 | 39 | public void setDescription(String description) { 40 | this.description = description; 41 | } 42 | 43 | public Float getUnitPrice() { 44 | return unitPrice; 45 | } 46 | 47 | public void setUnitPrice(Float unitPrice) { 48 | this.unitPrice = unitPrice; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/amqp-demo/src/main/java/com/apress/messaging/domain/Order.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.domain; 2 | 3 | public class Order { 4 | 5 | private String id; 6 | private Invoice invoice; 7 | private String description; 8 | 9 | public String getId() { 10 | return id; 11 | } 12 | 13 | public void setId(String id) { 14 | this.id = id; 15 | } 16 | 17 | public Invoice getInvoice() { 18 | return invoice; 19 | } 20 | 21 | public void setInvoice(Invoice invoice) { 22 | this.invoice = invoice; 23 | } 24 | 25 | public String getDescription() { 26 | return description; 27 | } 28 | 29 | public void setDescription(String description) { 30 | this.description = description; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/amqp-demo/src/main/java/com/apress/messaging/domain/Rate.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.domain; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | 6 | public class Rate { 7 | 8 | private String code; 9 | private Float rate; 10 | private Date date; 11 | 12 | public Rate() { 13 | } 14 | 15 | public Rate(String base, Float rate, Date date) { 16 | super(); 17 | this.code = base; 18 | this.rate = rate; 19 | this.date = date; 20 | } 21 | 22 | public String getCode() { 23 | return code; 24 | } 25 | 26 | public void setCode(String code) { 27 | this.code = code; 28 | } 29 | 30 | public Float getRate() { 31 | return rate; 32 | } 33 | 34 | public void setRate(Float rate) { 35 | this.rate = rate; 36 | } 37 | 38 | public Date getDate() { 39 | return date; 40 | } 41 | 42 | public void setDate(Date date) { 43 | this.date = date; 44 | } 45 | 46 | @Override 47 | public String toString() { 48 | String format = new SimpleDateFormat("yyyy-MM-dd").format(date); 49 | return "Rate [code=" + code + ", rate=" + rate + ", date=" + format + "]"; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/amqp-demo/src/main/java/com/apress/messaging/listener/RabbitMQEventListener.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.listener; 2 | 3 | import org.springframework.amqp.rabbit.listener.ListenerContainerConsumerFailedEvent; 4 | import org.springframework.context.event.EventListener; 5 | 6 | //@Component 7 | public class RabbitMQEventListener { 8 | 9 | @EventListener 10 | public void handler(ListenerContainerConsumerFailedEvent container){ 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/amqp-demo/src/test/java/com/apress/messaging/AmqpDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class AmqpDemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/rest-api-amqp/.gitignore: -------------------------------------------------------------------------------- 1 | /.apt_generated/ 2 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/rest-api-amqp/src/main/java/com/apress/messaging/RestApiAMQPApplication.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class RestApiAMQPApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(RestApiAMQPApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/rest-api-amqp/src/main/java/com/apress/messaging/ServletInitializer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.springframework.boot.builder.SpringApplicationBuilder; 4 | import org.springframework.boot.web.support.SpringBootServletInitializer; 5 | 6 | public class ServletInitializer extends SpringBootServletInitializer { 7 | 8 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 9 | return application.sources(RestApiAMQPApplication.class); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/rest-api-amqp/src/main/java/com/apress/messaging/amqp/RateConsumer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.amqp; 2 | 3 | public class RateConsumer { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/rest-api-amqp/src/main/java/com/apress/messaging/amqp/RateProducer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.amqp; 2 | 3 | public class RateProducer { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/rest-api-amqp/src/main/java/com/apress/messaging/annotation/Log.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.METHOD) 10 | public @interface Log { 11 | boolean printParamsValues() default false; 12 | String callMethodWithNoParamsToString() default "toString"; 13 | } 14 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/rest-api-amqp/src/main/java/com/apress/messaging/annotation/ToUpper.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.PARAMETER) 10 | public @interface ToUpper { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/rest-api-amqp/src/main/java/com/apress/messaging/config/RateJmsConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.config; 2 | 3 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.jms.support.converter.MappingJackson2MessageConverter; 7 | import org.springframework.jms.support.converter.MessageConverter; 8 | import org.springframework.jms.support.converter.MessageType; 9 | 10 | @Configuration 11 | @EnableConfigurationProperties(RateProperties.class) 12 | public class RateJmsConfiguration { 13 | 14 | @Bean 15 | public MessageConverter jacksonJmsMessageConverter() { 16 | MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(); 17 | converter.setTargetType(MessageType.TEXT); 18 | converter.setTypeIdPropertyName("_class_"); // This value can be anything, it will save the JSON class name and it must be the same for sender/receiver 19 | return converter; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/rest-api-amqp/src/main/java/com/apress/messaging/config/RateProperties.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | @ConfigurationProperties(prefix="rate.jms") 6 | public class RateProperties { 7 | 8 | private String queueName; 9 | private String replyQueueName; 10 | 11 | public String getQueueName() { 12 | return queueName; 13 | } 14 | 15 | public void setQueueName(String queueName) { 16 | this.queueName = queueName; 17 | } 18 | 19 | public String getReplyQueueName() { 20 | return replyQueueName; 21 | } 22 | 23 | public void setReplyQueueName(String replyQueueName) { 24 | this.replyQueueName = replyQueueName; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/rest-api-amqp/src/main/java/com/apress/messaging/domain/CurrencyExchange.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.domain; 2 | 3 | import java.util.Arrays; 4 | 5 | public class CurrencyExchange { 6 | 7 | public static final String BASE_CODE = "USD"; 8 | private String base; 9 | private String date; 10 | private Rate[] rates; 11 | 12 | public CurrencyExchange(String base, String date, Rate[] rates) { 13 | super(); 14 | this.base = base; 15 | this.date = date; 16 | this.rates = rates; 17 | } 18 | 19 | public String getBase() { 20 | return base; 21 | } 22 | public void setBase(String base) { 23 | this.base = base; 24 | } 25 | public String getDate() { 26 | return date; 27 | } 28 | public void setDate(String date) { 29 | this.date = date; 30 | } 31 | public Rate[] getRates() { 32 | return rates; 33 | } 34 | public void setRates(Rate[] rates) { 35 | this.rates = rates; 36 | } 37 | 38 | @Override 39 | public String toString() { 40 | return "CurrencyExchange [base=" + base + ", date=" + date + ", rates=" + Arrays.toString(rates) + "]"; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/rest-api-amqp/src/main/java/com/apress/messaging/event/CurrencyConversionEvent.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.event; 2 | 3 | import org.springframework.context.ApplicationEvent; 4 | 5 | import com.apress.messaging.domain.CurrencyConversion; 6 | 7 | public class CurrencyConversionEvent extends ApplicationEvent { 8 | 9 | private static final long serialVersionUID = -4481493963350551884L; 10 | private CurrencyConversion conversion; 11 | private String message; 12 | 13 | public CurrencyConversionEvent(Object source, CurrencyConversion conversion) { 14 | super(source); 15 | this.conversion = conversion; 16 | } 17 | 18 | public CurrencyConversionEvent(Object source, String message, CurrencyConversion conversion) { 19 | super(source); 20 | this.message = message; 21 | this.conversion = conversion; 22 | } 23 | 24 | public CurrencyConversion getConversion(){ 25 | return conversion; 26 | } 27 | 28 | public String getMessage(){ 29 | return message; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/rest-api-amqp/src/main/java/com/apress/messaging/event/CurrencyEvent.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.event; 2 | 3 | import org.springframework.context.ApplicationEvent; 4 | 5 | import com.apress.messaging.domain.Rate; 6 | 7 | public class CurrencyEvent extends ApplicationEvent { 8 | 9 | private static final long serialVersionUID = 889202626288526113L; 10 | private Rate rate; 11 | 12 | public CurrencyEvent(Object source,Rate rate) { 13 | super(source); 14 | this.rate = rate; 15 | } 16 | 17 | public Rate getRate(){ 18 | return this.rate; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/rest-api-amqp/src/main/java/com/apress/messaging/exception/BadCodeRuntimeException.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.exception; 2 | 3 | import com.apress.messaging.domain.CurrencyConversion; 4 | import com.apress.messaging.domain.Rate; 5 | 6 | public class BadCodeRuntimeException extends RuntimeException { 7 | 8 | private static final long serialVersionUID = -2411444965751028974L; 9 | private CurrencyConversion conversion; 10 | private Rate rate; 11 | 12 | public BadCodeRuntimeException(String message) { 13 | super(message); 14 | } 15 | 16 | public BadCodeRuntimeException(String message,CurrencyConversion conversion) { 17 | super(message); 18 | this.conversion = conversion; 19 | } 20 | 21 | public BadCodeRuntimeException(String message,Rate rate) { 22 | super(message); 23 | this.rate = rate; 24 | } 25 | 26 | public CurrencyConversion getConversion(){ 27 | return conversion; 28 | } 29 | 30 | public Rate getRate(){ 31 | return rate; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/rest-api-amqp/src/main/java/com/apress/messaging/listener/RateEventListener.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.listener; 2 | 3 | import org.springframework.stereotype.Component; 4 | import org.springframework.transaction.event.TransactionalEventListener; 5 | 6 | import com.apress.messaging.annotation.Log; 7 | import com.apress.messaging.event.CurrencyEvent; 8 | 9 | @Component 10 | public class RateEventListener { 11 | 12 | //@TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT) 13 | @TransactionalEventListener 14 | @Log(printParamsValues=true,callMethodWithNoParamsToString="getRate") 15 | public void processEvent(CurrencyEvent event){ } 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/rest-api-amqp/src/main/java/com/apress/messaging/listener/RestApiEventsListener.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.listener; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.actuate.metrics.CounterService; 5 | import org.springframework.context.ApplicationEvent; 6 | import org.springframework.context.ApplicationListener; 7 | import org.springframework.stereotype.Component; 8 | import org.springframework.web.context.support.ServletRequestHandledEvent; 9 | 10 | import com.apress.messaging.annotation.Log; 11 | 12 | @Component 13 | public class RestApiEventsListener implements ApplicationListener{ 14 | 15 | private static final String LATEST = "/currency/latest"; 16 | 17 | @Autowired 18 | private CounterService counterService; 19 | 20 | @Log(printParamsValues=true) 21 | public void onApplicationEvent(ApplicationEvent event) { 22 | if(event instanceof ServletRequestHandledEvent){ 23 | if(((ServletRequestHandledEvent)event).getRequestUrl().equals(LATEST)){ 24 | counterService.increment("url.currency.lastest.hits"); 25 | } 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/rest-api-amqp/src/main/java/com/apress/messaging/listener/RestAppEventListener.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.listener; 2 | 3 | import org.springframework.boot.context.event.SpringApplicationEvent; 4 | import org.springframework.context.event.EventListener; 5 | import org.springframework.stereotype.Component; 6 | 7 | import com.apress.messaging.annotation.Log; 8 | 9 | @Component 10 | public class RestAppEventListener { 11 | 12 | //@EventListener(condition = "#springApp.args.length > 1") 13 | //@EventListener({CurrencyEvent.class,CurrencyConversionEvent.class}) 14 | //@Order(Ordered.HIGHEST_PRECEDENCE) 15 | //@Async 16 | @EventListener 17 | @Log(printParamsValues=true) 18 | public void restAppHandler(SpringApplicationEvent springApp){ 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/rest-api-amqp/src/main/java/com/apress/messaging/repository/RateRepository.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.repository; 2 | 3 | import java.util.Date; 4 | import java.util.List; 5 | 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | 8 | import com.apress.messaging.domain.Rate; 9 | 10 | public interface RateRepository extends JpaRepository{ 11 | List findByDate(Date date); 12 | Rate findByDateAndCode(Date date,String code); 13 | } 14 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/rest-api-amqp/src/main/resources/META-INF/additional-spring-configuration-metadata.json: -------------------------------------------------------------------------------- 1 | {"properties": [{ 2 | "name": "rata.jms.queue-name", 3 | "type": "java.lang.String", 4 | "description": "The Rate Queue name" 5 | },{ 6 | "name": "rate.jms.reply-queue-name", 7 | "type": "java.lang.String", 8 | "description": "The Reply Rate Queue name" 9 | }]} -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/rest-api-amqp/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #spring.h2.console.enabled=true 2 | #server.error.whitelabel.enabled=false 3 | 4 | #spring.aop.auto=true 5 | #spring.aop.proxy-target-class=true 6 | 7 | #Jackson 8 | #spring.jackson.date-format=yyyy-MM-dd 9 | 10 | #Default ActiveMQ properties 11 | #spring.activemq.broker-url=tcp://localhost:61616 12 | #spring.activemq.user=admin 13 | #spring.activemq.password=admin 14 | 15 | #Rate App 16 | #rate.jms.queue-name=rates 17 | #rate.jms.reply-queue-name=reply-rate -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/rest-api-amqp/src/main/resources/public/error/4xx.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Error: BAD REQUEST!

4 |

5 | Take a look at the Body/Path/Parameter format. 6 |

7 | 8 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/rest-api-amqp/src/main/resources/public/error/5xx.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Error: BAD REQUEST!

4 |

5 | Take a look at the Body/Path/Parameter format. 6 |

7 | 8 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch05/rest-api-amqp/src/test/java/com/apress/messaging/RestApiAMQPApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class RestApiAMQPApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/redis-demo/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/redis-demo/src/main/java/com/apress/messaging/ServletInitializer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.springframework.boot.builder.SpringApplicationBuilder; 4 | import org.springframework.boot.web.support.SpringBootServletInitializer; 5 | 6 | public class ServletInitializer extends SpringBootServletInitializer { 7 | 8 | @Override 9 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 10 | return application.sources(RedisDemoApplication.class); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/redis-demo/src/main/java/com/apress/messaging/config/SimpleRedisProperties.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | @ConfigurationProperties(prefix = "apress.redis") 6 | public class SimpleRedisProperties { 7 | 8 | private String topic; 9 | private String rate; 10 | 11 | public String getTopic() { 12 | return topic; 13 | } 14 | 15 | public void setTopic(String topic) { 16 | this.topic = topic; 17 | } 18 | 19 | public String getRate() { 20 | return rate; 21 | } 22 | 23 | public void setRate(String rate) { 24 | this.rate = rate; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/redis-demo/src/main/java/com/apress/messaging/domain/Rate.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.domain; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | 6 | public class Rate { 7 | 8 | private String code; 9 | private Float rate; 10 | private Date date; 11 | 12 | public Rate() { 13 | } 14 | 15 | public Rate(String base, Float rate, Date date) { 16 | super(); 17 | this.code = base; 18 | this.rate = rate; 19 | this.date = date; 20 | } 21 | 22 | public String getCode() { 23 | return code; 24 | } 25 | 26 | public void setCode(String code) { 27 | this.code = code; 28 | } 29 | 30 | public Float getRate() { 31 | return rate; 32 | } 33 | 34 | public void setRate(Float rate) { 35 | this.rate = rate; 36 | } 37 | 38 | public Date getDate() { 39 | return date; 40 | } 41 | 42 | public void setDate(Date date) { 43 | this.date = date; 44 | } 45 | 46 | @Override 47 | public String toString() { 48 | String format = new SimpleDateFormat("yyyy-MM-dd").format(date); 49 | return "Rate [code=" + code + ", rate=" + rate + ", date=" + format + "]"; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/redis-demo/src/main/java/com/apress/messaging/redis/RateSubscriber.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.redis; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | import com.apress.messaging.domain.Rate; 6 | 7 | @Component 8 | public class RateSubscriber { 9 | 10 | // If only one method defined, it must be named: handleMessage 11 | public void handleMessage(Rate rate){ 12 | // Process message here ... 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/redis-demo/src/main/java/com/apress/messaging/redis/Subscriber.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.redis; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | @Component 6 | public class Subscriber { 7 | 8 | // If only one method defined, it must be named: handleMessage 9 | public void handleMessage(String message){ 10 | // Process message here ... 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/redis-demo/src/main/resources/META-INF/additional-spring-configuration-metadata.json: -------------------------------------------------------------------------------- 1 | {"properties": [{ 2 | "name": "apress.redis.topic", 3 | "type": "java.lang.String", 4 | "description": "The Redis Topic name" 5 | },{ 6 | "name": "apress.redis.rate", 7 | "type": "java.lang.String", 8 | "description": "The Rate Topic name" 9 | }]} -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/redis-demo/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #Spring Boot - Web (Off) - command line parameter: --web=[true|false] 2 | spring.main.web-environment=${web:false} 3 | 4 | # Spring Redis 5 | 6 | # Apress Redis Queue 7 | apress.redis.topic=spring-boot-chat 8 | 9 | # Rate 10 | apress.redis.rate=currency-rate 11 | 12 | 13 | # Debug 14 | #debug=true -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/redis-demo/src/test/java/com/apress/messaging/RedisDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class RedisDemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/rest-api-redis/.gitignore: -------------------------------------------------------------------------------- 1 | /.apt_generated/ 2 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/rest-api-redis/src/main/java/com/apress/messaging/RestApiAMQPApplication.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class RestApiAMQPApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(RestApiAMQPApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/rest-api-redis/src/main/java/com/apress/messaging/ServletInitializer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.springframework.boot.builder.SpringApplicationBuilder; 4 | import org.springframework.boot.web.support.SpringBootServletInitializer; 5 | 6 | public class ServletInitializer extends SpringBootServletInitializer { 7 | 8 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 9 | return application.sources(RestApiAMQPApplication.class); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/rest-api-redis/src/main/java/com/apress/messaging/amqp/RateConsumer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.amqp; 2 | 3 | public class RateConsumer { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/rest-api-redis/src/main/java/com/apress/messaging/amqp/RateProducer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.amqp; 2 | 3 | public class RateProducer { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/rest-api-redis/src/main/java/com/apress/messaging/annotation/Log.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.METHOD) 10 | public @interface Log { 11 | boolean printParamsValues() default false; 12 | String callMethodWithNoParamsToString() default "toString"; 13 | } 14 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/rest-api-redis/src/main/java/com/apress/messaging/annotation/ToUpper.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.PARAMETER) 10 | public @interface ToUpper { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/rest-api-redis/src/main/java/com/apress/messaging/config/RateJmsConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.config; 2 | 3 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.jms.support.converter.MappingJackson2MessageConverter; 7 | import org.springframework.jms.support.converter.MessageConverter; 8 | import org.springframework.jms.support.converter.MessageType; 9 | 10 | @Configuration 11 | @EnableConfigurationProperties(RateProperties.class) 12 | public class RateJmsConfiguration { 13 | 14 | @Bean 15 | public MessageConverter jacksonJmsMessageConverter() { 16 | MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(); 17 | converter.setTargetType(MessageType.TEXT); 18 | converter.setTypeIdPropertyName("_class_"); // This value can be anything, it will save the JSON class name and it must be the same for sender/receiver 19 | return converter; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/rest-api-redis/src/main/java/com/apress/messaging/config/RateProperties.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | @ConfigurationProperties(prefix="rate.jms") 6 | public class RateProperties { 7 | 8 | private String queueName; 9 | private String replyQueueName; 10 | 11 | public String getQueueName() { 12 | return queueName; 13 | } 14 | 15 | public void setQueueName(String queueName) { 16 | this.queueName = queueName; 17 | } 18 | 19 | public String getReplyQueueName() { 20 | return replyQueueName; 21 | } 22 | 23 | public void setReplyQueueName(String replyQueueName) { 24 | this.replyQueueName = replyQueueName; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/rest-api-redis/src/main/java/com/apress/messaging/config/RateRedisProperties.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | @ConfigurationProperties(prefix="rate.redis") 6 | public class RateRedisProperties { 7 | 8 | private String topic; 9 | 10 | public String getTopic() { 11 | return topic; 12 | } 13 | 14 | public void setTopic(String topic) { 15 | this.topic = topic; 16 | } 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/rest-api-redis/src/main/java/com/apress/messaging/domain/CurrencyExchange.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.domain; 2 | 3 | import java.util.Arrays; 4 | 5 | public class CurrencyExchange { 6 | 7 | public static final String BASE_CODE = "USD"; 8 | private String base; 9 | private String date; 10 | private Rate[] rates; 11 | 12 | public CurrencyExchange(String base, String date, Rate[] rates) { 13 | super(); 14 | this.base = base; 15 | this.date = date; 16 | this.rates = rates; 17 | } 18 | 19 | public String getBase() { 20 | return base; 21 | } 22 | public void setBase(String base) { 23 | this.base = base; 24 | } 25 | public String getDate() { 26 | return date; 27 | } 28 | public void setDate(String date) { 29 | this.date = date; 30 | } 31 | public Rate[] getRates() { 32 | return rates; 33 | } 34 | public void setRates(Rate[] rates) { 35 | this.rates = rates; 36 | } 37 | 38 | @Override 39 | public String toString() { 40 | return "CurrencyExchange [base=" + base + ", date=" + date + ", rates=" + Arrays.toString(rates) + "]"; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/rest-api-redis/src/main/java/com/apress/messaging/event/CurrencyConversionEvent.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.event; 2 | 3 | import org.springframework.context.ApplicationEvent; 4 | 5 | import com.apress.messaging.domain.CurrencyConversion; 6 | 7 | public class CurrencyConversionEvent extends ApplicationEvent { 8 | 9 | private static final long serialVersionUID = -4481493963350551884L; 10 | private CurrencyConversion conversion; 11 | private String message; 12 | 13 | public CurrencyConversionEvent(Object source, CurrencyConversion conversion) { 14 | super(source); 15 | this.conversion = conversion; 16 | } 17 | 18 | public CurrencyConversionEvent(Object source, String message, CurrencyConversion conversion) { 19 | super(source); 20 | this.message = message; 21 | this.conversion = conversion; 22 | } 23 | 24 | public CurrencyConversion getConversion(){ 25 | return conversion; 26 | } 27 | 28 | public String getMessage(){ 29 | return message; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/rest-api-redis/src/main/java/com/apress/messaging/event/CurrencyEvent.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.event; 2 | 3 | import org.springframework.context.ApplicationEvent; 4 | 5 | import com.apress.messaging.domain.Rate; 6 | 7 | public class CurrencyEvent extends ApplicationEvent { 8 | 9 | private static final long serialVersionUID = 889202626288526113L; 10 | private Rate rate; 11 | 12 | public CurrencyEvent(Object source,Rate rate) { 13 | super(source); 14 | this.rate = rate; 15 | } 16 | 17 | public Rate getRate(){ 18 | return this.rate; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/rest-api-redis/src/main/java/com/apress/messaging/exception/BadCodeRuntimeException.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.exception; 2 | 3 | import com.apress.messaging.domain.CurrencyConversion; 4 | import com.apress.messaging.domain.Rate; 5 | 6 | public class BadCodeRuntimeException extends RuntimeException { 7 | 8 | private static final long serialVersionUID = -2411444965751028974L; 9 | private CurrencyConversion conversion; 10 | private Rate rate; 11 | 12 | public BadCodeRuntimeException(String message) { 13 | super(message); 14 | } 15 | 16 | public BadCodeRuntimeException(String message,CurrencyConversion conversion) { 17 | super(message); 18 | this.conversion = conversion; 19 | } 20 | 21 | public BadCodeRuntimeException(String message,Rate rate) { 22 | super(message); 23 | this.rate = rate; 24 | } 25 | 26 | public CurrencyConversion getConversion(){ 27 | return conversion; 28 | } 29 | 30 | public Rate getRate(){ 31 | return rate; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/rest-api-redis/src/main/java/com/apress/messaging/listener/RateEventListener.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.listener; 2 | 3 | import org.springframework.stereotype.Component; 4 | import org.springframework.transaction.event.TransactionalEventListener; 5 | 6 | import com.apress.messaging.annotation.Log; 7 | import com.apress.messaging.event.CurrencyEvent; 8 | 9 | @Component 10 | public class RateEventListener { 11 | 12 | //@TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT) 13 | @TransactionalEventListener 14 | @Log(printParamsValues=true,callMethodWithNoParamsToString="getRate") 15 | public void processEvent(CurrencyEvent event){ } 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/rest-api-redis/src/main/java/com/apress/messaging/listener/RestApiEventsListener.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.listener; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.actuate.metrics.CounterService; 5 | import org.springframework.context.ApplicationEvent; 6 | import org.springframework.context.ApplicationListener; 7 | import org.springframework.stereotype.Component; 8 | import org.springframework.web.context.support.ServletRequestHandledEvent; 9 | 10 | import com.apress.messaging.annotation.Log; 11 | 12 | @Component 13 | public class RestApiEventsListener implements ApplicationListener{ 14 | 15 | private static final String LATEST = "/currency/latest"; 16 | 17 | @Autowired 18 | private CounterService counterService; 19 | 20 | @Log(printParamsValues=true) 21 | public void onApplicationEvent(ApplicationEvent event) { 22 | if(event instanceof ServletRequestHandledEvent){ 23 | if(((ServletRequestHandledEvent)event).getRequestUrl().equals(LATEST)){ 24 | counterService.increment("url.currency.lastest.hits"); 25 | } 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/rest-api-redis/src/main/java/com/apress/messaging/listener/RestAppEventListener.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.listener; 2 | 3 | import org.springframework.boot.context.event.SpringApplicationEvent; 4 | import org.springframework.context.event.EventListener; 5 | import org.springframework.stereotype.Component; 6 | 7 | import com.apress.messaging.annotation.Log; 8 | 9 | @Component 10 | public class RestAppEventListener { 11 | 12 | //@EventListener(condition = "#springApp.args.length > 1") 13 | //@EventListener({CurrencyEvent.class,CurrencyConversionEvent.class}) 14 | //@Order(Ordered.HIGHEST_PRECEDENCE) 15 | //@Async 16 | @EventListener 17 | @Log(printParamsValues=true) 18 | public void restAppHandler(SpringApplicationEvent springApp){ 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/rest-api-redis/src/main/java/com/apress/messaging/redis/RateRedisSubscriber.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.redis; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | import com.apress.messaging.domain.Rate; 6 | 7 | @Component 8 | public class RateRedisSubscriber { 9 | 10 | // If only one method defined, it must be named: handleMessage 11 | public void handleMessage(Rate rate) { 12 | // Process message here ... 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/rest-api-redis/src/main/java/com/apress/messaging/repository/RateRepository.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.repository; 2 | 3 | import java.util.Date; 4 | import java.util.List; 5 | 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | 8 | import com.apress.messaging.domain.Rate; 9 | 10 | public interface RateRepository extends JpaRepository{ 11 | List findByDate(Date date); 12 | Rate findByDateAndCode(Date date,String code); 13 | } 14 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/rest-api-redis/src/main/resources/META-INF/additional-spring-configuration-metadata.json: -------------------------------------------------------------------------------- 1 | {"properties": [{ 2 | "name": "rata.jms.queue-name", 3 | "type": "java.lang.String", 4 | "description": "The Rate Queue name" 5 | },{ 6 | "name": "rate.jms.reply-queue-name", 7 | "type": "java.lang.String", 8 | "description": "The Reply Rate Queue name" 9 | },{ 10 | "name": "rate.redis.topic", 11 | "type": "java.lang.String", 12 | "description": "The Redis Rate topic" 13 | }]} -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/rest-api-redis/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #spring.h2.console.enabled=true 2 | #server.error.whitelabel.enabled=false 3 | 4 | #spring.aop.auto=true 5 | #spring.aop.proxy-target-class=true 6 | 7 | #Jackson 8 | #spring.jackson.date-format=yyyy-MM-dd 9 | 10 | #Default ActiveMQ properties 11 | #spring.activemq.broker-url=tcp://localhost:61616 12 | #spring.activemq.user=admin 13 | #spring.activemq.password=admin 14 | 15 | #Rate App 16 | #rate.jms.queue-name=rates 17 | #rate.jms.reply-queue-name=reply-rate 18 | 19 | #Rate Redis 20 | #rate.redis.topic=rates-topic 21 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/rest-api-redis/src/main/resources/public/error/4xx.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Error: BAD REQUEST!

4 |

5 | Take a look at the Body/Path/Parameter format. 6 |

7 | 8 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/rest-api-redis/src/main/resources/public/error/5xx.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Error: BAD REQUEST!

4 |

5 | Take a look at the Body/Path/Parameter format. 6 |

7 | 8 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch06/rest-api-redis/src/test/java/com/apress/messaging/RestApiAMQPApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class RestApiAMQPApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/rest-api-websockets/.gitignore: -------------------------------------------------------------------------------- 1 | /.apt_generated/ 2 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/rest-api-websockets/src/main/java/com/apress/messaging/RestApiWebSocketsApplication.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import java.util.Date; 4 | 5 | import org.springframework.boot.CommandLineRunner; 6 | import org.springframework.boot.SpringApplication; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | import org.springframework.context.annotation.Bean; 9 | 10 | import com.apress.messaging.domain.Rate; 11 | import com.apress.messaging.repository.RateRepository; 12 | 13 | @SpringBootApplication 14 | public class RestApiWebSocketsApplication { 15 | 16 | public static void main(String[] args) { 17 | SpringApplication.run(RestApiWebSocketsApplication.class, args); 18 | } 19 | 20 | @Bean 21 | public CommandLineRunner data(RateRepository repository) { 22 | return (args) -> { 23 | repository.save(new Rate("EUR",0.88857F,new Date())); 24 | repository.save(new Rate("JPY",102.17F,new Date())); 25 | repository.save(new Rate("MXN",19.232F,new Date())); 26 | repository.save(new Rate("GBP",0.75705F,new Date())); 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/rest-api-websockets/src/main/java/com/apress/messaging/ServletInitializer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.springframework.boot.builder.SpringApplicationBuilder; 4 | import org.springframework.boot.web.support.SpringBootServletInitializer; 5 | 6 | public class ServletInitializer extends SpringBootServletInitializer { 7 | 8 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 9 | return application.sources(RestApiWebSocketsApplication.class); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/rest-api-websockets/src/main/java/com/apress/messaging/amqp/RateConsumer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.amqp; 2 | 3 | public class RateConsumer { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/rest-api-websockets/src/main/java/com/apress/messaging/amqp/RateProducer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.amqp; 2 | 3 | public class RateProducer { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/rest-api-websockets/src/main/java/com/apress/messaging/annotation/Log.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.METHOD) 10 | public @interface Log { 11 | boolean printParamsValues() default false; 12 | String callMethodWithNoParamsToString() default "toString"; 13 | } 14 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/rest-api-websockets/src/main/java/com/apress/messaging/annotation/ToUpper.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.PARAMETER) 10 | public @interface ToUpper { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/rest-api-websockets/src/main/java/com/apress/messaging/config/RateJmsConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.config; 2 | 3 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.jms.support.converter.MappingJackson2MessageConverter; 7 | import org.springframework.jms.support.converter.MessageConverter; 8 | import org.springframework.jms.support.converter.MessageType; 9 | 10 | @Configuration 11 | @EnableConfigurationProperties(RateProperties.class) 12 | public class RateJmsConfiguration { 13 | 14 | @Bean 15 | public MessageConverter jacksonJmsMessageConverter() { 16 | MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(); 17 | converter.setTargetType(MessageType.TEXT); 18 | converter.setTypeIdPropertyName("_class_"); // This value can be anything, it will save the JSON class name and it must be the same for sender/receiver 19 | return converter; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/rest-api-websockets/src/main/java/com/apress/messaging/config/RateProperties.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | @ConfigurationProperties(prefix="rate.jms") 6 | public class RateProperties { 7 | 8 | private String queueName; 9 | private String replyQueueName; 10 | 11 | public String getQueueName() { 12 | return queueName; 13 | } 14 | 15 | public void setQueueName(String queueName) { 16 | this.queueName = queueName; 17 | } 18 | 19 | public String getReplyQueueName() { 20 | return replyQueueName; 21 | } 22 | 23 | public void setReplyQueueName(String replyQueueName) { 24 | this.replyQueueName = replyQueueName; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/rest-api-websockets/src/main/java/com/apress/messaging/config/RateRedisProperties.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | @ConfigurationProperties(prefix="rate.redis") 6 | public class RateRedisProperties { 7 | 8 | private String topic; 9 | 10 | public String getTopic() { 11 | return topic; 12 | } 13 | 14 | public void setTopic(String topic) { 15 | this.topic = topic; 16 | } 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/rest-api-websockets/src/main/java/com/apress/messaging/config/RateWebSocketsProperties.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | @ConfigurationProperties(prefix = "rate.ws") 6 | public class RateWebSocketsProperties { 7 | 8 | private String app = "/rest-api-ws"; 9 | private String broker = "/rate"; 10 | private String endpoint = "/stomp"; 11 | 12 | public String getApp() { 13 | return app; 14 | } 15 | 16 | public void setApp(String app) { 17 | this.app = app; 18 | } 19 | 20 | public String getBroker() { 21 | return broker; 22 | } 23 | 24 | public void setBroker(String broker) { 25 | this.broker = broker; 26 | } 27 | 28 | public String getEndpoint() { 29 | return endpoint; 30 | } 31 | 32 | public void setEndpoint(String endpoint) { 33 | this.endpoint = endpoint; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/rest-api-websockets/src/main/java/com/apress/messaging/domain/CurrencyExchange.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.domain; 2 | 3 | import java.util.Arrays; 4 | 5 | public class CurrencyExchange { 6 | 7 | public static final String BASE_CODE = "USD"; 8 | private String base; 9 | private String date; 10 | private Rate[] rates; 11 | 12 | public CurrencyExchange(){} 13 | 14 | public CurrencyExchange(String base, String date, Rate[] rates) { 15 | super(); 16 | this.base = base; 17 | this.date = date; 18 | this.rates = rates; 19 | } 20 | 21 | public String getBase() { 22 | return base; 23 | } 24 | public void setBase(String base) { 25 | this.base = base; 26 | } 27 | public String getDate() { 28 | return date; 29 | } 30 | public void setDate(String date) { 31 | this.date = date; 32 | } 33 | public Rate[] getRates() { 34 | return rates; 35 | } 36 | public void setRates(Rate[] rates) { 37 | this.rates = rates; 38 | } 39 | 40 | @Override 41 | public String toString() { 42 | return "CurrencyExchange [base=" + base + ", date=" + date + ", rates=" + Arrays.toString(rates) + "]"; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/rest-api-websockets/src/main/java/com/apress/messaging/event/CurrencyConversionEvent.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.event; 2 | 3 | import org.springframework.context.ApplicationEvent; 4 | 5 | import com.apress.messaging.domain.CurrencyConversion; 6 | 7 | public class CurrencyConversionEvent extends ApplicationEvent { 8 | 9 | private static final long serialVersionUID = -4481493963350551884L; 10 | private CurrencyConversion conversion; 11 | private String message; 12 | 13 | public CurrencyConversionEvent(Object source, CurrencyConversion conversion) { 14 | super(source); 15 | this.conversion = conversion; 16 | } 17 | 18 | public CurrencyConversionEvent(Object source, String message, CurrencyConversion conversion) { 19 | super(source); 20 | this.message = message; 21 | this.conversion = conversion; 22 | } 23 | 24 | public CurrencyConversion getConversion(){ 25 | return conversion; 26 | } 27 | 28 | public String getMessage(){ 29 | return message; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/rest-api-websockets/src/main/java/com/apress/messaging/event/CurrencyEvent.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.event; 2 | 3 | import org.springframework.context.ApplicationEvent; 4 | 5 | import com.apress.messaging.domain.Rate; 6 | 7 | public class CurrencyEvent extends ApplicationEvent { 8 | 9 | private static final long serialVersionUID = 889202626288526113L; 10 | private Rate rate; 11 | 12 | public CurrencyEvent(Object source,Rate rate) { 13 | super(source); 14 | this.rate = rate; 15 | } 16 | 17 | public Rate getRate(){ 18 | return this.rate; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/rest-api-websockets/src/main/java/com/apress/messaging/exception/BadCodeRuntimeException.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.exception; 2 | 3 | import com.apress.messaging.domain.CurrencyConversion; 4 | import com.apress.messaging.domain.Rate; 5 | 6 | public class BadCodeRuntimeException extends RuntimeException { 7 | 8 | private static final long serialVersionUID = -2411444965751028974L; 9 | private CurrencyConversion conversion; 10 | private Rate rate; 11 | 12 | public BadCodeRuntimeException(String message) { 13 | super(message); 14 | } 15 | 16 | public BadCodeRuntimeException(String message,CurrencyConversion conversion) { 17 | super(message); 18 | this.conversion = conversion; 19 | } 20 | 21 | public BadCodeRuntimeException(String message,Rate rate) { 22 | super(message); 23 | this.rate = rate; 24 | } 25 | 26 | public CurrencyConversion getConversion(){ 27 | return conversion; 28 | } 29 | 30 | public Rate getRate(){ 31 | return rate; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/rest-api-websockets/src/main/java/com/apress/messaging/listener/RateEventListener.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.listener; 2 | 3 | import org.springframework.stereotype.Component; 4 | import org.springframework.transaction.event.TransactionalEventListener; 5 | 6 | import com.apress.messaging.annotation.Log; 7 | import com.apress.messaging.event.CurrencyEvent; 8 | 9 | @Component 10 | public class RateEventListener { 11 | 12 | //@TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT) 13 | @TransactionalEventListener 14 | @Log(printParamsValues=true,callMethodWithNoParamsToString="getRate") 15 | public void processEvent(CurrencyEvent event){ } 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/rest-api-websockets/src/main/java/com/apress/messaging/listener/RestAppEventListener.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.listener; 2 | 3 | import org.springframework.boot.context.event.SpringApplicationEvent; 4 | import org.springframework.context.event.EventListener; 5 | import org.springframework.stereotype.Component; 6 | 7 | import com.apress.messaging.annotation.Log; 8 | 9 | @Component 10 | public class RestAppEventListener { 11 | 12 | //@EventListener(condition = "#springApp.args.length > 1") 13 | //@EventListener({CurrencyEvent.class,CurrencyConversionEvent.class}) 14 | //@Order(Ordered.HIGHEST_PRECEDENCE) 15 | //@Async 16 | @EventListener 17 | @Log(printParamsValues=true) 18 | public void restAppHandler(SpringApplicationEvent springApp){ 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/rest-api-websockets/src/main/java/com/apress/messaging/redis/RateRedisSubscriber.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.redis; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | import com.apress.messaging.domain.Rate; 6 | 7 | @Component 8 | public class RateRedisSubscriber { 9 | 10 | // If only one method defined, it must be named: handleMessage 11 | public void handleMessage(Rate rate) { 12 | // Process message here ... 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/rest-api-websockets/src/main/java/com/apress/messaging/repository/RateRepository.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.repository; 2 | 3 | import java.util.Date; 4 | import java.util.List; 5 | 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | 8 | import com.apress.messaging.domain.Rate; 9 | 10 | public interface RateRepository extends JpaRepository{ 11 | List findByDate(Date date); 12 | Rate findByDateAndCode(Date date,String code); 13 | } 14 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/rest-api-websockets/src/main/resources/META-INF/additional-spring-configuration-metadata.json: -------------------------------------------------------------------------------- 1 | {"properties": [{ 2 | "name": "rata.jms.queue-name", 3 | "type": "java.lang.String", 4 | "description": "The Rate Queue name" 5 | },{ 6 | "name": "rate.jms.reply-queue-name", 7 | "type": "java.lang.String", 8 | "description": "The Reply Rate Queue name" 9 | },{ 10 | "name": "rate.redis.topic", 11 | "type": "java.lang.String", 12 | "description": "The Redis Rate topic" 13 | }]} -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/rest-api-websockets/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #spring.h2.console.enabled=true 2 | #server.error.whitelabel.enabled=false 3 | 4 | #spring.aop.auto=true 5 | #spring.aop.proxy-target-class=true 6 | 7 | #Jackson 8 | #spring.jackson.date-format=yyyy-MM-dd 9 | 10 | #Default ActiveMQ properties 11 | #spring.activemq.broker-url=tcp://localhost:61616 12 | #spring.activemq.user=admin 13 | #spring.activemq.password=admin 14 | 15 | #JMS Rate App 16 | #rate.jms.queue-name=rates 17 | #rate.jms.reply-queue-name=reply-rate 18 | 19 | #Rate Redis 20 | #rate.redis.topic=rates-topic 21 | 22 | #WebSockets 23 | #rate.ws.endpoint=/stomp 24 | #rate.ws.broker=/rate 25 | #rate.ws.app=/rest-api-ws 26 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/rest-api-websockets/src/main/resources/public/error/4xx.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Error: BAD REQUEST!

4 |

5 | Take a look at the Body/Path/Parameter format. 6 |

7 | 8 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/rest-api-websockets/src/main/resources/public/error/5xx.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Error: BAD REQUEST!

4 |

5 | Take a look at the Body/Path/Parameter format. 6 |

7 | 8 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/rest-api-websockets/src/test/java/com/apress/messaging/RestApiWebSocketsApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class RestApiWebSocketsApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/websocket-demo/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/websocket-demo/src/main/java/com/apress/messaging/ServletInitializer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.springframework.boot.builder.SpringApplicationBuilder; 4 | import org.springframework.boot.web.support.SpringBootServletInitializer; 5 | 6 | public class ServletInitializer extends SpringBootServletInitializer { 7 | 8 | @Override 9 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 10 | return application.sources(WebSocketsDemoApplication.class); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/websocket-demo/src/main/java/com/apress/messaging/config/LlWebSocketConfig.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.web.socket.config.annotation.EnableWebSocket; 5 | import org.springframework.web.socket.config.annotation.WebSocketConfigurer; 6 | import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; 7 | 8 | import com.apress.messaging.web.socket.LlWebSocketHandler; 9 | 10 | @Configuration 11 | @EnableWebSocket 12 | public class LlWebSocketConfig implements WebSocketConfigurer{ 13 | 14 | LlWebSocketHandler handler; 15 | 16 | public LlWebSocketConfig(LlWebSocketHandler handler){ 17 | this.handler = handler; 18 | } 19 | 20 | @Override 21 | public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { 22 | registry.addHandler(this.handler, "/llws"); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/websocket-demo/src/main/java/com/apress/messaging/controller/SimpleController.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.controller; 2 | 3 | import org.springframework.messaging.handler.annotation.MessageMapping; 4 | import org.springframework.messaging.handler.annotation.SendTo; 5 | import org.springframework.stereotype.Controller; 6 | 7 | import com.apress.messaging.domain.ChatMessage; 8 | 9 | @Controller 10 | public class SimpleController { 11 | 12 | @MessageMapping("${apress.ws.mapping}") 13 | @SendTo("/topic/chat-room") 14 | public ChatMessage chatRoom(ChatMessage message) { 15 | return message; 16 | } 17 | 18 | 19 | /* Enable for a dynamic destination */ 20 | /* 21 | @MessageMapping("${apress.ws.mapping}/{room}") 22 | @SendTo("/topic/chat-room/{user}") 23 | public ChatMessage directChatRoom(@DestinationVariable("room")String room 24 | ,@DestinationVariable("user")String user,ChatMessage message) { 25 | 26 | return message; 27 | } 28 | */ 29 | } 30 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/websocket-demo/src/main/java/com/apress/messaging/domain/Rate.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.domain; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | 6 | public class Rate { 7 | 8 | private String code; 9 | private Float rate; 10 | private Date date; 11 | 12 | public Rate() { 13 | } 14 | 15 | public Rate(String base, Float rate, Date date) { 16 | super(); 17 | this.code = base; 18 | this.rate = rate; 19 | this.date = date; 20 | } 21 | 22 | public String getCode() { 23 | return code; 24 | } 25 | 26 | public void setCode(String code) { 27 | this.code = code; 28 | } 29 | 30 | public Float getRate() { 31 | return rate; 32 | } 33 | 34 | public void setRate(Float rate) { 35 | this.rate = rate; 36 | } 37 | 38 | public Date getDate() { 39 | return date; 40 | } 41 | 42 | public void setDate(Date date) { 43 | this.date = date; 44 | } 45 | 46 | @Override 47 | public String toString() { 48 | String format = new SimpleDateFormat("yyyy-MM-dd").format(date); 49 | return "Rate [code=" + code + ", rate=" + rate + ", date=" + format + "]"; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/websocket-demo/src/main/java/com/apress/messaging/web/socket/LlWebSocketHandler.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.web.socket; 2 | 3 | import org.springframework.stereotype.Component; 4 | import org.springframework.web.socket.TextMessage; 5 | import org.springframework.web.socket.WebSocketSession; 6 | import org.springframework.web.socket.handler.TextWebSocketHandler; 7 | 8 | @Component 9 | public class LlWebSocketHandler extends TextWebSocketHandler{ 10 | 11 | 12 | @Override 13 | public void afterConnectionEstablished(WebSocketSession session) throws Exception { 14 | super.afterConnectionEstablished(session); 15 | } 16 | 17 | @Override 18 | public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { 19 | System.out.println(">>>> " + message); 20 | 21 | //Enable this if you want to return the Message to the Client 22 | //session.sendMessage(message); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/websocket-demo/src/main/resources/META-INF/additional-spring-configuration-metadata.json: -------------------------------------------------------------------------------- 1 | {"properties": [{ 2 | "name": "apress.ws.topic", 3 | "type": "java.lang.String", 4 | "description": "The Web Socket Topic name" 5 | },{ 6 | "name": "apress.ws.app-destination-prefix", 7 | "type": "java.lang.String", 8 | "description": "The Application destination prefix" 9 | },{ 10 | "name": "apress.ws.rate", 11 | "type": "java.lang.String", 12 | "description": "The Web Socket Rate Topic name" 13 | },{ 14 | "name": "apress.ws.mapping", 15 | "type": "java.lang.String", 16 | "description": "The Web Socket Mapping that accept incoming web socket messages" 17 | },{ 18 | "name": "apress.ws.endpoint", 19 | "type": "java.lang.String", 20 | "description": "The Web Socket Endpoint path" 21 | }]} -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/websocket-demo/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # Spring WebSockets 2 | spring.aop.proxy-target-class=true 3 | server.port=${port:8080} 4 | 5 | # Apress WebSockets 6 | apress.ws.endpoint=/stomp-endpoint 7 | apress.ws.app-destination-prefix=/my-app 8 | apress.ws.mapping=/chat-room 9 | apress.ws.mapping-reply=${apress.ws.topic}${apress.ws.mapping} 10 | apress.ws.topic=/topic 11 | 12 | 13 | # Rate 14 | 15 | 16 | # Debug 17 | #debug=true -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch07/websocket-demo/src/test/java/com/apress/messaging/WebSocketsDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class WebSocketsDemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/rest-api-si/.gitignore: -------------------------------------------------------------------------------- 1 | /.apt_generated/ 2 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/rest-api-si/rates-2017-02-21.txt: -------------------------------------------------------------------------------- 1 | {"code":"EUR","rate":0.82857,"date":"2017-02-15"} 2 | {"code":"JPY","rate":105.17,"date":"2017-02-15"} 3 | {"code":"MXN","rate":22.232,"date":"2017-02-15"} 4 | {"code":"GBP","rate":0.75705,"date":"2017-02-16"} -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/rest-api-si/src/main/java/com/apress/messaging/RestApiSpiApplication.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class RestApiSpiApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(RestApiSpiApplication.class, args); 11 | } 12 | 13 | /* 14 | @Bean 15 | public CommandLineRunner data(RateRepository repository) { 16 | return (args) -> { 17 | repository.save(new Rate("EUR",0.88857F,new Date())); 18 | repository.save(new Rate("JPY",102.17F,new Date())); 19 | repository.save(new Rate("MXN",19.232F,new Date())); 20 | repository.save(new Rate("GBP",0.75705F,new Date())); 21 | }; 22 | } 23 | */ 24 | } 25 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/rest-api-si/src/main/java/com/apress/messaging/ServletInitializer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.springframework.boot.builder.SpringApplicationBuilder; 4 | import org.springframework.boot.web.support.SpringBootServletInitializer; 5 | 6 | public class ServletInitializer extends SpringBootServletInitializer { 7 | 8 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 9 | return application.sources(RestApiSpiApplication.class); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/rest-api-si/src/main/java/com/apress/messaging/amqp/RateConsumer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.amqp; 2 | 3 | public class RateConsumer { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/rest-api-si/src/main/java/com/apress/messaging/amqp/RateProducer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.amqp; 2 | 3 | public class RateProducer { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/rest-api-si/src/main/java/com/apress/messaging/annotation/Log.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.METHOD) 10 | public @interface Log { 11 | boolean printParamsValues() default false; 12 | String callMethodWithNoParamsToString() default "toString"; 13 | } 14 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/rest-api-si/src/main/java/com/apress/messaging/annotation/ToUpper.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.PARAMETER) 10 | public @interface ToUpper { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/rest-api-si/src/main/java/com/apress/messaging/config/RateJmsConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.config; 2 | 3 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.jms.support.converter.MappingJackson2MessageConverter; 7 | import org.springframework.jms.support.converter.MessageConverter; 8 | import org.springframework.jms.support.converter.MessageType; 9 | 10 | @Configuration 11 | @EnableConfigurationProperties(RateProperties.class) 12 | public class RateJmsConfiguration { 13 | 14 | @Bean 15 | public MessageConverter jacksonJmsMessageConverter() { 16 | MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(); 17 | converter.setTargetType(MessageType.TEXT); 18 | converter.setTypeIdPropertyName("_class_"); // This value can be anything, it will save the JSON class name and it must be the same for sender/receiver 19 | return converter; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/rest-api-si/src/main/java/com/apress/messaging/config/RateProperties.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | @ConfigurationProperties(prefix="rate.jms") 6 | public class RateProperties { 7 | 8 | private String queueName; 9 | private String replyQueueName; 10 | 11 | public String getQueueName() { 12 | return queueName; 13 | } 14 | 15 | public void setQueueName(String queueName) { 16 | this.queueName = queueName; 17 | } 18 | 19 | public String getReplyQueueName() { 20 | return replyQueueName; 21 | } 22 | 23 | public void setReplyQueueName(String replyQueueName) { 24 | this.replyQueueName = replyQueueName; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/rest-api-si/src/main/java/com/apress/messaging/config/RateRedisProperties.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | @ConfigurationProperties(prefix="rate.redis") 6 | public class RateRedisProperties { 7 | 8 | private String topic; 9 | 10 | public String getTopic() { 11 | return topic; 12 | } 13 | 14 | public void setTopic(String topic) { 15 | this.topic = topic; 16 | } 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/rest-api-si/src/main/java/com/apress/messaging/config/RateWebSocketsProperties.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | @ConfigurationProperties(prefix = "rate.ws") 6 | public class RateWebSocketsProperties { 7 | 8 | private String app = "/rest-api-ws"; 9 | private String broker = "/rate"; 10 | private String endpoint = "/stomp"; 11 | 12 | public String getApp() { 13 | return app; 14 | } 15 | 16 | public void setApp(String app) { 17 | this.app = app; 18 | } 19 | 20 | public String getBroker() { 21 | return broker; 22 | } 23 | 24 | public void setBroker(String broker) { 25 | this.broker = broker; 26 | } 27 | 28 | public String getEndpoint() { 29 | return endpoint; 30 | } 31 | 32 | public void setEndpoint(String endpoint) { 33 | this.endpoint = endpoint; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/rest-api-si/src/main/java/com/apress/messaging/domain/CurrencyExchange.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.domain; 2 | 3 | import java.util.Arrays; 4 | 5 | public class CurrencyExchange { 6 | 7 | public static final String BASE_CODE = "USD"; 8 | private String base; 9 | private String date; 10 | private Rate[] rates; 11 | 12 | public CurrencyExchange(){} 13 | 14 | public CurrencyExchange(String base, String date, Rate[] rates) { 15 | super(); 16 | this.base = base; 17 | this.date = date; 18 | this.rates = rates; 19 | } 20 | 21 | public String getBase() { 22 | return base; 23 | } 24 | public void setBase(String base) { 25 | this.base = base; 26 | } 27 | public String getDate() { 28 | return date; 29 | } 30 | public void setDate(String date) { 31 | this.date = date; 32 | } 33 | public Rate[] getRates() { 34 | return rates; 35 | } 36 | public void setRates(Rate[] rates) { 37 | this.rates = rates; 38 | } 39 | 40 | @Override 41 | public String toString() { 42 | return "CurrencyExchange [base=" + base + ", date=" + date + ", rates=" + Arrays.toString(rates) + "]"; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/rest-api-si/src/main/java/com/apress/messaging/event/CurrencyConversionEvent.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.event; 2 | 3 | import org.springframework.context.ApplicationEvent; 4 | 5 | import com.apress.messaging.domain.CurrencyConversion; 6 | 7 | public class CurrencyConversionEvent extends ApplicationEvent { 8 | 9 | private static final long serialVersionUID = -4481493963350551884L; 10 | private CurrencyConversion conversion; 11 | private String message; 12 | 13 | public CurrencyConversionEvent(Object source, CurrencyConversion conversion) { 14 | super(source); 15 | this.conversion = conversion; 16 | } 17 | 18 | public CurrencyConversionEvent(Object source, String message, CurrencyConversion conversion) { 19 | super(source); 20 | this.message = message; 21 | this.conversion = conversion; 22 | } 23 | 24 | public CurrencyConversion getConversion(){ 25 | return conversion; 26 | } 27 | 28 | public String getMessage(){ 29 | return message; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/rest-api-si/src/main/java/com/apress/messaging/event/CurrencyEvent.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.event; 2 | 3 | import org.springframework.context.ApplicationEvent; 4 | 5 | import com.apress.messaging.domain.Rate; 6 | 7 | public class CurrencyEvent extends ApplicationEvent { 8 | 9 | private static final long serialVersionUID = 889202626288526113L; 10 | private Rate rate; 11 | 12 | public CurrencyEvent(Object source,Rate rate) { 13 | super(source); 14 | this.rate = rate; 15 | } 16 | 17 | public Rate getRate(){ 18 | return this.rate; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/rest-api-si/src/main/java/com/apress/messaging/exception/BadCodeRuntimeException.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.exception; 2 | 3 | import com.apress.messaging.domain.CurrencyConversion; 4 | import com.apress.messaging.domain.Rate; 5 | 6 | public class BadCodeRuntimeException extends RuntimeException { 7 | 8 | private static final long serialVersionUID = -2411444965751028974L; 9 | private CurrencyConversion conversion; 10 | private Rate rate; 11 | 12 | public BadCodeRuntimeException(String message) { 13 | super(message); 14 | } 15 | 16 | public BadCodeRuntimeException(String message,CurrencyConversion conversion) { 17 | super(message); 18 | this.conversion = conversion; 19 | } 20 | 21 | public BadCodeRuntimeException(String message,Rate rate) { 22 | super(message); 23 | this.rate = rate; 24 | } 25 | 26 | public CurrencyConversion getConversion(){ 27 | return conversion; 28 | } 29 | 30 | public Rate getRate(){ 31 | return rate; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/rest-api-si/src/main/java/com/apress/messaging/integration/RateServiceActivator.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.integration; 2 | 3 | import java.util.Map; 4 | 5 | import org.springframework.messaging.handler.annotation.Headers; 6 | import org.springframework.stereotype.Component; 7 | 8 | import com.apress.messaging.annotation.Log; 9 | import com.apress.messaging.domain.Rate; 10 | 11 | @Component 12 | public class RateServiceActivator { 13 | 14 | @Log(printParamsValues=true) 15 | public void process(Rate rate, @Headers Map headers){ 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/rest-api-si/src/main/java/com/apress/messaging/listener/RateEventListener.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.listener; 2 | 3 | import org.springframework.stereotype.Component; 4 | import org.springframework.transaction.event.TransactionalEventListener; 5 | 6 | import com.apress.messaging.annotation.Log; 7 | import com.apress.messaging.event.CurrencyEvent; 8 | 9 | @Component 10 | public class RateEventListener { 11 | 12 | //@TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT) 13 | @TransactionalEventListener 14 | @Log(printParamsValues=true,callMethodWithNoParamsToString="getRate") 15 | public void processEvent(CurrencyEvent event){ } 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/rest-api-si/src/main/java/com/apress/messaging/listener/RestApiEventsListener.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.listener; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.actuate.metrics.CounterService; 5 | import org.springframework.context.ApplicationEvent; 6 | import org.springframework.context.ApplicationListener; 7 | import org.springframework.stereotype.Component; 8 | import org.springframework.web.context.support.ServletRequestHandledEvent; 9 | 10 | import com.apress.messaging.annotation.Log; 11 | 12 | @Component 13 | public class RestApiEventsListener implements ApplicationListener{ 14 | 15 | private static final String LATEST = "/currency/latest"; 16 | 17 | @Autowired 18 | private CounterService counterService; 19 | 20 | @Log(printParamsValues=true) 21 | public void onApplicationEvent(ApplicationEvent event) { 22 | if(event instanceof ServletRequestHandledEvent){ 23 | if(((ServletRequestHandledEvent)event).getRequestUrl().equals(LATEST)){ 24 | counterService.increment("url.currency.lastest.hits"); 25 | } 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/rest-api-si/src/main/java/com/apress/messaging/listener/RestAppEventListener.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.listener; 2 | 3 | import org.springframework.boot.context.event.SpringApplicationEvent; 4 | import org.springframework.context.event.EventListener; 5 | import org.springframework.stereotype.Component; 6 | 7 | import com.apress.messaging.annotation.Log; 8 | 9 | @Component 10 | public class RestAppEventListener { 11 | 12 | //@EventListener(condition = "#springApp.args.length > 1") 13 | //@EventListener({CurrencyEvent.class,CurrencyConversionEvent.class}) 14 | //@Order(Ordered.HIGHEST_PRECEDENCE) 15 | //@Async 16 | @EventListener 17 | @Log(printParamsValues=true) 18 | public void restAppHandler(SpringApplicationEvent springApp){ 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/rest-api-si/src/main/java/com/apress/messaging/redis/RateRedisSubscriber.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.redis; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | import com.apress.messaging.domain.Rate; 6 | 7 | @Component 8 | public class RateRedisSubscriber { 9 | 10 | // If only one method defined, it must be named: handleMessage 11 | public void handleMessage(Rate rate) { 12 | // Process message here ... 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/rest-api-si/src/main/java/com/apress/messaging/repository/RateRepository.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.repository; 2 | 3 | import java.util.Date; 4 | import java.util.List; 5 | 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | 8 | import com.apress.messaging.domain.Rate; 9 | 10 | public interface RateRepository extends JpaRepository{ 11 | List findByDate(Date date); 12 | Rate findByDateAndCode(Date date,String code); 13 | } 14 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/rest-api-si/src/main/resources/META-INF/additional-spring-configuration-metadata.json: -------------------------------------------------------------------------------- 1 | {"properties": [{ 2 | "name": "rata.jms.queue-name", 3 | "type": "java.lang.String", 4 | "description": "The Rate Queue name" 5 | },{ 6 | "name": "rate.jms.reply-queue-name", 7 | "type": "java.lang.String", 8 | "description": "The Reply Rate Queue name" 9 | },{ 10 | "name": "rate.redis.topic", 11 | "type": "java.lang.String", 12 | "description": "The Redis Rate topic" 13 | }]} -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/rest-api-si/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #spring.h2.console.enabled=true 2 | #server.error.whitelabel.enabled=false 3 | 4 | #spring.aop.auto=true 5 | #spring.aop.proxy-target-class=true 6 | 7 | #Jackson 8 | #spring.jackson.date-format=yyyy-MM-dd 9 | 10 | #Default ActiveMQ properties 11 | #spring.activemq.broker-url=tcp://localhost:61616 12 | #spring.activemq.user=admin 13 | #spring.activemq.password=admin 14 | 15 | #JMS Rate App 16 | #rate.jms.queue-name=rates 17 | #rate.jms.reply-queue-name=reply-rate 18 | 19 | #Rate Redis 20 | #rate.redis.topic=rates-topic 21 | 22 | #WebSockets 23 | #rate.ws.endpoint=/stomp 24 | #rate.ws.broker=/rate 25 | #rate.ws.app=/rest-api-ws 26 | 27 | #SPI 28 | rate.spi.directory=. 29 | rate.spi.file-pattern=rates*.txt 30 | rate.spi.process-directory='output' 31 | rate.spi.queue=spi.rate 32 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/rest-api-si/src/main/resources/public/error/4xx.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Error: BAD REQUEST!

4 |

5 | Take a look at the Body/Path/Parameter format. 6 |

7 | 8 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/rest-api-si/src/main/resources/public/error/5xx.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Error: BAD REQUEST!

4 |

5 | Take a look at the Body/Path/Parameter format. 6 |

7 | 8 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/rest-api-si/src/test/java/com/apress/messaging/RestApiSpiApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class RestApiSpiApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/si-demo/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/si-demo/contacts.txt: -------------------------------------------------------------------------------- 1 | John, Doe, 2000-02-22, +1 345-834-6789, john.doe@company.com, true 2 | Silvia, DeMarcos, 1998-04-21, +1 345-884-6311, silvia.demarcos@company.com, false 3 | Jim, Wolf, 1999-08-22, +1 285-374-2357, jim.wolf@company.com, true -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/si-demo/rates-2017-02-21.txt: -------------------------------------------------------------------------------- 1 | {"base":"USD","date":"2017-02-15","rates":[{"code":"EUR","rate":0.82857,"date":"2017-02-15"},{"code":"JPY","rate":105.17,"date":"2017-02-15"},{"code":"MXN","rate":22.232,"date":"2017-02-15"},{"code":"GBP","rate":0.75705,"date":"2017-02-16"}]} -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/si-demo/src/main/java/com/apress/messaging/config/SpiProperties.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | @ConfigurationProperties(prefix = "apress.spi") 6 | public class SpiProperties { 7 | 8 | private String directory; 9 | private String filePattern; 10 | private String exchange = ""; 11 | private String queue = "spi.rate"; 12 | 13 | public String getDirectory() { 14 | return directory; 15 | } 16 | 17 | public void setDirectory(String directory) { 18 | this.directory = directory; 19 | } 20 | 21 | public String getFilePattern() { 22 | return filePattern; 23 | } 24 | 25 | public void setFilePattern(String filePattern) { 26 | this.filePattern = filePattern; 27 | } 28 | 29 | public String getExchange() { 30 | return exchange; 31 | } 32 | 33 | public void setExchange(String exchange) { 34 | this.exchange = exchange; 35 | } 36 | 37 | public String getQueue() { 38 | return queue; 39 | } 40 | 41 | public void setQueue(String queue) { 42 | this.queue = queue; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/si-demo/src/main/java/com/apress/messaging/controller/SimpleController.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.controller; 2 | 3 | public class SimpleController { 4 | 5 | 6 | } 7 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/si-demo/src/main/java/com/apress/messaging/domain/Rate.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.domain; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | 6 | public class Rate { 7 | 8 | private String code; 9 | private Float rate; 10 | private Date date; 11 | 12 | public Rate() { 13 | } 14 | 15 | public Rate(String base, Float rate, Date date) { 16 | super(); 17 | this.code = base; 18 | this.rate = rate; 19 | this.date = date; 20 | } 21 | 22 | public String getCode() { 23 | return code; 24 | } 25 | 26 | public void setCode(String code) { 27 | this.code = code; 28 | } 29 | 30 | public Float getRate() { 31 | return rate; 32 | } 33 | 34 | public void setRate(Float rate) { 35 | this.rate = rate; 36 | } 37 | 38 | public Date getDate() { 39 | return date; 40 | } 41 | 42 | public void setDate(Date date) { 43 | this.date = date; 44 | } 45 | 46 | @Override 47 | public String toString() { 48 | String format = new SimpleDateFormat("yyyy-MM-dd").format(date); 49 | return "Rate [code=" + code + ", rate=" + rate + ", date=" + format + "]"; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/si-demo/src/main/java/com/apress/messaging/integration/PersonConverter.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.integration; 2 | 3 | import java.text.ParseException; 4 | import java.text.SimpleDateFormat; 5 | import java.util.List; 6 | import java.util.stream.Collectors; 7 | import java.util.stream.Stream; 8 | 9 | import org.springframework.core.convert.converter.Converter; 10 | import org.springframework.stereotype.Component; 11 | 12 | import com.apress.messaging.domain.Person; 13 | 14 | //@IntegrationConverter 15 | @Component 16 | public class PersonConverter implements Converter { 17 | 18 | @Override 19 | public Person convert(String str) { 20 | SimpleDateFormat df = new SimpleDateFormat("yyyyy-mm-dd"); 21 | List fields = Stream.of(str.split(",")).map(String::trim).collect(Collectors.toList()); 22 | try { 23 | return new Person(fields.get(0),fields.get(1),df.parse(fields.get(2)),fields.get(3),fields.get(4),Boolean.parseBoolean(fields.get(5))); 24 | } catch (ParseException e) { 25 | return null; 26 | } 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/si-demo/src/main/java/com/apress/messaging/integration/SimpleMessageHandler.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.integration; 2 | 3 | import org.springframework.messaging.Message; 4 | import org.springframework.stereotype.Component; 5 | 6 | @Component 7 | public class SimpleMessageHandler { 8 | 9 | public void process(Message message){ 10 | 11 | } 12 | 13 | /* Enable this for a concrete Person Rate */ 14 | /* 15 | public void process(Person message){ 16 | 17 | } 18 | */ 19 | 20 | /* Enable this for a concrete Message Rate */ 21 | /* 22 | public void process(Rate message){ 23 | 24 | } 25 | */ 26 | } 27 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/si-demo/src/main/resources/META-INF/spring/integration/spi-file-to-jdbc.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/si-demo/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # H2 Console 2 | spring.h2.console.enabled=true 3 | 4 | # Apress SPI properties 5 | apress.spi.directory=. 6 | apress.spi.file-pattern=contacts.txt 7 | 8 | apress.spi.queue=spi.rate 9 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/si-demo/src/main/resources/schema.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS person; 2 | 3 | CREATE TABLE person ( 4 | id integer NOT NULL AUTO_INCREMENT, 5 | first varchar(150), 6 | last varchar(150), 7 | dob date, 8 | phone varchar(12), 9 | email varchar(150), 10 | friend boolean, 11 | PRIMARY KEY(id) 12 | ); -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch08/si-demo/src/test/java/com/apress/messaging/SpiDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class SpiDemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/app-starters/http/http-source-rabbit-1.1.2.RELEASE.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/spring-boot-messaging/02b8fff85fbfe7082e36872b73631af1dc3671bc/Pro Spring Messaging Source Code/ch09/app-starters/http/http-source-rabbit-1.1.2.RELEASE.jar -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/app-starters/http/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | java -jar http-source-rabbit-1.1.2.RELEASE.jar --spring.cloud.stream.bindings.output.destination=simple-demo 3 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/app-starters/log/log-sink-rabbit-1.1.1.RELEASE.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/spring-boot-messaging/02b8fff85fbfe7082e36872b73631af1dc3671bc/Pro Spring Messaging Source Code/ch09/app-starters/log/log-sink-rabbit-1.1.1.RELEASE.jar -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/app-starters/log/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | java -jar log-sink-rabbit-1.1.1.RELEASE.jar --spring.cloud.stream.bindings.input.destination=simple-demo --server.port=8081 3 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/cloud-stream-demo/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/cloud-stream-demo/src/main/java/com/apress/messaging/cloud/stream/SimpleSink.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.cloud.stream; 2 | 3 | import org.springframework.cloud.stream.annotation.StreamListener; 4 | import org.springframework.cloud.stream.messaging.Sink; 5 | 6 | //@EnableBinding(Sink.class) 7 | public class SimpleSink { 8 | 9 | 10 | @StreamListener(Sink.INPUT) 11 | public void process(String message){ 12 | 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/cloud-stream-demo/src/main/resources/META-INF/spring.integration.properties: -------------------------------------------------------------------------------- 1 | # Headers to keep in between channel 2 | #spring.integration.readOnly.headers=contentType -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/cloud-stream-demo/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # Spring Cloud Stream 2 | 3 | # Message converter in channel INPUT (For the Processor and Sink streams) 4 | # spring.cloud.stream.bindings.input.content-type=text/plain 5 | 6 | # Message converter in channel OUTPUT (For the Source stream) 7 | #spring.cloud.stream.bindings.output.content-type=application/json -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/cloud-stream-demo/src/test/java/com/apress/cloud/stream/CloudStreamDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.cloud.stream; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class CloudStreamDemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/cloud-stream-processor-demo/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/cloud-stream-processor-demo/src/main/java/com/apress/messaging/CloudStreamProcessorDemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CloudStreamProcessorDemoApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(CloudStreamProcessorDemoApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/cloud-stream-processor-demo/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # Spring Cloud Stream - Processor 2 | # Spring 3 | server.port=${port:8082} 4 | 5 | # Spring Cloud Stream 6 | spring.cloud.stream.bindings.input.destination=person 7 | spring.cloud.stream.bindings.output.destination=tickets 8 | 9 | spring.cloud.stream.bindings.output.content-type=application/json 10 | 11 | # Date Format 12 | spring.jackson.date-format=yyyy-MM-dd -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/cloud-stream-processor-demo/src/test/java/com/apress/messging/CloudStreamProcessorDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.messging; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class CloudStreamProcessorDemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/cloud-stream-sink-demo/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/cloud-stream-sink-demo/src/main/java/com/apress/messaging/CloudStreamSinkDemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CloudStreamSinkDemoApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(CloudStreamSinkDemoApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/cloud-stream-sink-demo/src/main/java/com/apress/messaging/cloud/stream/TicketSinkProperties.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.cloud.stream; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | @ConfigurationProperties(prefix = "ticket") 6 | public class TicketSinkProperties { 7 | 8 | private String queue; 9 | private String exchange; 10 | 11 | public String getQueue() { 12 | return queue; 13 | } 14 | 15 | public void setQueue(String queue) { 16 | this.queue = queue; 17 | } 18 | 19 | public String getExchange() { 20 | return exchange; 21 | } 22 | 23 | public void setExchange(String exchange) { 24 | this.exchange = exchange; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/cloud-stream-sink-demo/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # Spring Cloud Stream - Sink 2 | # Spring 3 | server.port=${port:8083} 4 | 5 | # Spring Cloud Stream 6 | spring.cloud.stream.bindings.input.destination=tickets 7 | 8 | ticket.queue=processed.tickets -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/cloud-stream-sink-demo/src/test/java/com/apress/messging/CloudStreamSinkDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.messging; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class CloudStreamSinkDemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/cloud-stream-source-demo/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/cloud-stream-source-demo/contacts.txt: -------------------------------------------------------------------------------- 1 | John, Doe, 2000-02-22, +1 345-834-6789, john.doe@company.com, true 2 | Silvia, DeMarcos, 1998-04-21, +1 345-884-6311, silvia.demarcos@company.com, false 3 | Jim, Wolf, 1999-08-22, +1 285-374-2357, jim.wolf@company.com, true -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/cloud-stream-source-demo/src/main/java/com/apress/messaging/CloudStreamSourceDemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CloudStreamSourceDemoApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(CloudStreamSourceDemoApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/cloud-stream-source-demo/src/main/java/com/apress/messaging/cloud/stream/PersonFileProperties.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.cloud.stream; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | import org.springframework.stereotype.Component; 5 | 6 | @Component 7 | @ConfigurationProperties(prefix = "apress.stream.file") 8 | public class PersonFileProperties { 9 | 10 | private String directory; 11 | private String namePattern; 12 | 13 | public String getDirectory() { 14 | return directory; 15 | } 16 | 17 | public void setDirectory(String directory) { 18 | this.directory = directory; 19 | } 20 | 21 | public String getNamePattern() { 22 | return namePattern; 23 | } 24 | 25 | public void setNamePattern(String namePattern) { 26 | this.namePattern = namePattern; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/cloud-stream-source-demo/src/main/java/com/apress/messaging/domain/Rate.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.domain; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | 6 | public class Rate { 7 | 8 | private String code; 9 | private Float rate; 10 | private Date date; 11 | 12 | public Rate() { 13 | } 14 | 15 | public Rate(String base, Float rate, Date date) { 16 | super(); 17 | this.code = base; 18 | this.rate = rate; 19 | this.date = date; 20 | } 21 | 22 | public String getCode() { 23 | return code; 24 | } 25 | 26 | public void setCode(String code) { 27 | this.code = code; 28 | } 29 | 30 | public Float getRate() { 31 | return rate; 32 | } 33 | 34 | public void setRate(Float rate) { 35 | this.rate = rate; 36 | } 37 | 38 | public Date getDate() { 39 | return date; 40 | } 41 | 42 | public void setDate(Date date) { 43 | this.date = date; 44 | } 45 | 46 | @Override 47 | public String toString() { 48 | String format = new SimpleDateFormat("yyyy-MM-dd").format(date); 49 | return "Rate [code=" + code + ", rate=" + rate + ", date=" + format + "]"; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/cloud-stream-source-demo/src/main/java/com/apress/messaging/integration/PersonConverter.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.integration; 2 | 3 | import java.text.ParseException; 4 | import java.text.SimpleDateFormat; 5 | import java.util.List; 6 | import java.util.stream.Collectors; 7 | import java.util.stream.Stream; 8 | 9 | import org.springframework.core.convert.converter.Converter; 10 | import org.springframework.stereotype.Component; 11 | 12 | import com.apress.messaging.domain.Person; 13 | 14 | @Component 15 | public class PersonConverter implements Converter { 16 | 17 | @Override 18 | public Person convert(String str) { 19 | SimpleDateFormat df = new SimpleDateFormat("yyyyy-mm-dd"); 20 | List fields = Stream.of(str.split(",")).map(String::trim).collect(Collectors.toList()); 21 | try { 22 | return new Person(fields.get(0),fields.get(1),df.parse(fields.get(2)),fields.get(3),fields.get(4),Boolean.parseBoolean(fields.get(5))); 23 | } catch (ParseException e) { 24 | return null; 25 | } 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/cloud-stream-source-demo/src/main/java/com/apress/messaging/integration/SimpleMessageHandler.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.integration; 2 | 3 | import org.springframework.messaging.Message; 4 | import org.springframework.stereotype.Component; 5 | 6 | @Component 7 | public class SimpleMessageHandler { 8 | 9 | public void process(Message message){ 10 | 11 | } 12 | 13 | /* Enable this for a concrete Person Rate */ 14 | /* 15 | public void process(Person message){ 16 | 17 | } 18 | */ 19 | 20 | /* Enable this for a concrete Message Rate */ 21 | /* 22 | public void process(Rate message){ 23 | 24 | } 25 | */ 26 | } 27 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/cloud-stream-source-demo/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # Spring Cloud Stream - Source 2 | # Spring 3 | server.port=${port:8081} 4 | 5 | # Spring Cloud Stream 6 | spring.cloud.stream.bindings.output.destination=person 7 | 8 | 9 | # Apress Cloud Stream 10 | apress.stream.file.directory=. 11 | apress.stream.file.name-pattern=*.txt -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/cloud-stream-source-demo/src/test/java/com/apress/messging/CloudStreamSourceDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.messging; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class CloudStreamSourceDemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/rest-api-cloud-stream/.gitignore: -------------------------------------------------------------------------------- 1 | /.apt_generated/ 2 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/rest-api-cloud-stream/output/rates-2017-02-21.processed: -------------------------------------------------------------------------------- 1 | Rate [code=EUR, rate=0.82857, date=2017-02-14] 2 | Rate [code=JPY, rate=105.17, date=2017-02-14] 3 | Rate [code=MXN, rate=22.232, date=2017-02-14] 4 | Rate [code=GBP, rate=0.75705, date=2017-02-15] 5 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/rest-api-cloud-stream/rates-2017-02-21.txt: -------------------------------------------------------------------------------- 1 | {"code":"EUR","rate":0.82857,"date":"2017-02-15"} 2 | {"code":"JPY","rate":105.17,"date":"2017-02-15"} 3 | {"code":"MXN","rate":22.232,"date":"2017-02-15"} 4 | {"code":"GBP","rate":0.75705,"date":"2017-02-16"} -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/rest-api-cloud-stream/src/main/java/com/apress/messaging/ServletInitializer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.springframework.boot.builder.SpringApplicationBuilder; 4 | import org.springframework.boot.web.support.SpringBootServletInitializer; 5 | 6 | public class ServletInitializer extends SpringBootServletInitializer { 7 | 8 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 9 | return application.sources(RestApiCloudStreamApplication.class); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/rest-api-cloud-stream/src/main/java/com/apress/messaging/amqp/RateConsumer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.amqp; 2 | 3 | public class RateConsumer { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/rest-api-cloud-stream/src/main/java/com/apress/messaging/amqp/RateProducer.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.amqp; 2 | 3 | public class RateProducer { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/rest-api-cloud-stream/src/main/java/com/apress/messaging/annotation/Log.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.METHOD) 10 | public @interface Log { 11 | boolean printParamsValues() default false; 12 | String callMethodWithNoParamsToString() default "toString"; 13 | } 14 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/rest-api-cloud-stream/src/main/java/com/apress/messaging/annotation/ToUpper.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.PARAMETER) 10 | public @interface ToUpper { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/rest-api-cloud-stream/src/main/java/com/apress/messaging/cloud/stream/RateExchange.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.cloud.stream; 2 | 3 | import org.springframework.cloud.stream.annotation.Input; 4 | import org.springframework.cloud.stream.annotation.Output; 5 | import org.springframework.messaging.MessageChannel; 6 | import org.springframework.messaging.SubscribableChannel; 7 | 8 | public interface RateExchange { 9 | 10 | String INPUT = "rates"; 11 | String OUTPUT_EUR = "EUR"; 12 | String OUTPUT_JPY = "JPY"; 13 | 14 | 15 | @Input(RateExchange.INPUT) 16 | SubscribableChannel rates(); 17 | 18 | @Output(RateExchange.OUTPUT_EUR) 19 | MessageChannel eur(); 20 | 21 | @Output(RateExchange.OUTPUT_JPY) 22 | MessageChannel jpy(); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/rest-api-cloud-stream/src/main/java/com/apress/messaging/cloud/stream/RateSink.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.cloud.stream; 2 | 3 | import org.springframework.cloud.stream.annotation.StreamListener; 4 | import org.springframework.integration.annotation.ServiceActivator; 5 | 6 | import com.apress.messaging.annotation.Log; 7 | import com.apress.messaging.domain.Rate; 8 | 9 | //@EnableBinding(RateExchange.class) 10 | public class RateSink { 11 | 12 | @Log(printParamsValues=true) 13 | @ServiceActivator(inputChannel = RateExchange.OUTPUT_JPY) 14 | public void processJPY(Rate rate){ 15 | 16 | } 17 | 18 | @Log(printParamsValues=true) 19 | @StreamListener(RateExchange.OUTPUT_EUR) 20 | public void processEUR(Rate rate){ 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/rest-api-cloud-stream/src/main/java/com/apress/messaging/config/RateJmsConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.config; 2 | 3 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.jms.support.converter.MappingJackson2MessageConverter; 7 | import org.springframework.jms.support.converter.MessageConverter; 8 | import org.springframework.jms.support.converter.MessageType; 9 | 10 | @Configuration 11 | @EnableConfigurationProperties(RateProperties.class) 12 | public class RateJmsConfiguration { 13 | 14 | @Bean 15 | public MessageConverter jacksonJmsMessageConverter() { 16 | MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(); 17 | converter.setTargetType(MessageType.TEXT); 18 | converter.setTypeIdPropertyName("_class_"); // This value can be anything, it will save the JSON class name and it must be the same for sender/receiver 19 | return converter; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/rest-api-cloud-stream/src/main/java/com/apress/messaging/config/RateProperties.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | @ConfigurationProperties(prefix="rate.jms") 6 | public class RateProperties { 7 | 8 | private String queueName; 9 | private String replyQueueName; 10 | 11 | public String getQueueName() { 12 | return queueName; 13 | } 14 | 15 | public void setQueueName(String queueName) { 16 | this.queueName = queueName; 17 | } 18 | 19 | public String getReplyQueueName() { 20 | return replyQueueName; 21 | } 22 | 23 | public void setReplyQueueName(String replyQueueName) { 24 | this.replyQueueName = replyQueueName; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/rest-api-cloud-stream/src/main/java/com/apress/messaging/config/RateRedisProperties.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | @ConfigurationProperties(prefix="rate.redis") 6 | public class RateRedisProperties { 7 | 8 | private String topic; 9 | 10 | public String getTopic() { 11 | return topic; 12 | } 13 | 14 | public void setTopic(String topic) { 15 | this.topic = topic; 16 | } 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/rest-api-cloud-stream/src/main/java/com/apress/messaging/config/RateWebSocketsProperties.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | @ConfigurationProperties(prefix = "rate.ws") 6 | public class RateWebSocketsProperties { 7 | 8 | private String app = "/rest-api-ws"; 9 | private String broker = "/rate"; 10 | private String endpoint = "/stomp"; 11 | 12 | public String getApp() { 13 | return app; 14 | } 15 | 16 | public void setApp(String app) { 17 | this.app = app; 18 | } 19 | 20 | public String getBroker() { 21 | return broker; 22 | } 23 | 24 | public void setBroker(String broker) { 25 | this.broker = broker; 26 | } 27 | 28 | public String getEndpoint() { 29 | return endpoint; 30 | } 31 | 32 | public void setEndpoint(String endpoint) { 33 | this.endpoint = endpoint; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/rest-api-cloud-stream/src/main/java/com/apress/messaging/domain/CurrencyExchange.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.domain; 2 | 3 | import java.util.Arrays; 4 | 5 | public class CurrencyExchange { 6 | 7 | public static final String BASE_CODE = "USD"; 8 | private String base; 9 | private String date; 10 | private Rate[] rates; 11 | 12 | public CurrencyExchange(){} 13 | 14 | public CurrencyExchange(String base, String date, Rate[] rates) { 15 | super(); 16 | this.base = base; 17 | this.date = date; 18 | this.rates = rates; 19 | } 20 | 21 | public String getBase() { 22 | return base; 23 | } 24 | public void setBase(String base) { 25 | this.base = base; 26 | } 27 | public String getDate() { 28 | return date; 29 | } 30 | public void setDate(String date) { 31 | this.date = date; 32 | } 33 | public Rate[] getRates() { 34 | return rates; 35 | } 36 | public void setRates(Rate[] rates) { 37 | this.rates = rates; 38 | } 39 | 40 | @Override 41 | public String toString() { 42 | return "CurrencyExchange [base=" + base + ", date=" + date + ", rates=" + Arrays.toString(rates) + "]"; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/rest-api-cloud-stream/src/main/java/com/apress/messaging/event/CurrencyConversionEvent.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.event; 2 | 3 | import org.springframework.context.ApplicationEvent; 4 | 5 | import com.apress.messaging.domain.CurrencyConversion; 6 | 7 | public class CurrencyConversionEvent extends ApplicationEvent { 8 | 9 | private static final long serialVersionUID = -4481493963350551884L; 10 | private CurrencyConversion conversion; 11 | private String message; 12 | 13 | public CurrencyConversionEvent(Object source, CurrencyConversion conversion) { 14 | super(source); 15 | this.conversion = conversion; 16 | } 17 | 18 | public CurrencyConversionEvent(Object source, String message, CurrencyConversion conversion) { 19 | super(source); 20 | this.message = message; 21 | this.conversion = conversion; 22 | } 23 | 24 | public CurrencyConversion getConversion(){ 25 | return conversion; 26 | } 27 | 28 | public String getMessage(){ 29 | return message; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/rest-api-cloud-stream/src/main/java/com/apress/messaging/event/CurrencyEvent.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.event; 2 | 3 | import org.springframework.context.ApplicationEvent; 4 | 5 | import com.apress.messaging.domain.Rate; 6 | 7 | public class CurrencyEvent extends ApplicationEvent { 8 | 9 | private static final long serialVersionUID = 889202626288526113L; 10 | private Rate rate; 11 | 12 | public CurrencyEvent(Object source,Rate rate) { 13 | super(source); 14 | this.rate = rate; 15 | } 16 | 17 | public Rate getRate(){ 18 | return this.rate; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/rest-api-cloud-stream/src/main/java/com/apress/messaging/exception/BadCodeRuntimeException.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.exception; 2 | 3 | import com.apress.messaging.domain.CurrencyConversion; 4 | import com.apress.messaging.domain.Rate; 5 | 6 | public class BadCodeRuntimeException extends RuntimeException { 7 | 8 | private static final long serialVersionUID = -2411444965751028974L; 9 | private CurrencyConversion conversion; 10 | private Rate rate; 11 | 12 | public BadCodeRuntimeException(String message) { 13 | super(message); 14 | } 15 | 16 | public BadCodeRuntimeException(String message,CurrencyConversion conversion) { 17 | super(message); 18 | this.conversion = conversion; 19 | } 20 | 21 | public BadCodeRuntimeException(String message,Rate rate) { 22 | super(message); 23 | this.rate = rate; 24 | } 25 | 26 | public CurrencyConversion getConversion(){ 27 | return conversion; 28 | } 29 | 30 | public Rate getRate(){ 31 | return rate; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/rest-api-cloud-stream/src/main/java/com/apress/messaging/integration/RateServiceActivator.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.integration; 2 | 3 | import java.util.Map; 4 | 5 | import org.springframework.messaging.handler.annotation.Headers; 6 | import org.springframework.stereotype.Component; 7 | 8 | import com.apress.messaging.annotation.Log; 9 | import com.apress.messaging.domain.Rate; 10 | 11 | @Component 12 | public class RateServiceActivator { 13 | 14 | @Log(printParamsValues=true) 15 | public void process(Rate rate, @Headers Map headers){ 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/rest-api-cloud-stream/src/main/java/com/apress/messaging/listener/RateEventListener.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.listener; 2 | 3 | import org.springframework.stereotype.Component; 4 | import org.springframework.transaction.event.TransactionalEventListener; 5 | 6 | import com.apress.messaging.annotation.Log; 7 | import com.apress.messaging.event.CurrencyEvent; 8 | 9 | @Component 10 | public class RateEventListener { 11 | 12 | //@TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT) 13 | @TransactionalEventListener 14 | @Log(printParamsValues=true,callMethodWithNoParamsToString="getRate") 15 | public void processEvent(CurrencyEvent event){ } 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/rest-api-cloud-stream/src/main/java/com/apress/messaging/listener/RestAppEventListener.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.listener; 2 | 3 | import org.springframework.boot.context.event.SpringApplicationEvent; 4 | import org.springframework.context.event.EventListener; 5 | import org.springframework.stereotype.Component; 6 | 7 | import com.apress.messaging.annotation.Log; 8 | 9 | @Component 10 | public class RestAppEventListener { 11 | 12 | //@EventListener(condition = "#springApp.args.length > 1") 13 | //@EventListener({CurrencyEvent.class,CurrencyConversionEvent.class}) 14 | //@Order(Ordered.HIGHEST_PRECEDENCE) 15 | //@Async 16 | @EventListener 17 | @Log(printParamsValues=true) 18 | public void restAppHandler(SpringApplicationEvent springApp){ 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/rest-api-cloud-stream/src/main/java/com/apress/messaging/redis/RateRedisSubscriber.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.redis; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | import com.apress.messaging.domain.Rate; 6 | 7 | @Component 8 | public class RateRedisSubscriber { 9 | 10 | // If only one method defined, it must be named: handleMessage 11 | public void handleMessage(Rate rate) { 12 | // Process message here ... 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/rest-api-cloud-stream/src/main/java/com/apress/messaging/repository/RateRepository.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.repository; 2 | 3 | import java.util.Date; 4 | import java.util.List; 5 | 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | 8 | import com.apress.messaging.domain.Rate; 9 | 10 | public interface RateRepository extends JpaRepository{ 11 | List findByDate(Date date); 12 | Rate findByDateAndCode(Date date,String code); 13 | } 14 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/rest-api-cloud-stream/src/main/resources/META-INF/additional-spring-configuration-metadata.json: -------------------------------------------------------------------------------- 1 | {"properties": [{ 2 | "name": "rata.jms.queue-name", 3 | "type": "java.lang.String", 4 | "description": "The Rate Queue name" 5 | },{ 6 | "name": "rate.jms.reply-queue-name", 7 | "type": "java.lang.String", 8 | "description": "The Reply Rate Queue name" 9 | },{ 10 | "name": "rate.redis.topic", 11 | "type": "java.lang.String", 12 | "description": "The Redis Rate topic" 13 | }]} -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/rest-api-cloud-stream/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #spring.h2.console.enabled=true 2 | #server.error.whitelabel.enabled=false 3 | 4 | #spring.aop.auto=true 5 | #spring.aop.proxy-target-class=true 6 | 7 | #Jackson 8 | #spring.jackson.date-format=yyyy-MM-dd 9 | 10 | #Default ActiveMQ properties 11 | #spring.activemq.broker-url=tcp://localhost:61616 12 | #spring.activemq.user=admin 13 | #spring.activemq.password=admin 14 | 15 | #JMS Rate App 16 | #rate.jms.queue-name=rates 17 | #rate.jms.reply-queue-name=reply-rate 18 | 19 | #Rate Redis 20 | #rate.redis.topic=rates-topic 21 | 22 | #WebSockets 23 | #rate.ws.endpoint=/stomp 24 | #rate.ws.broker=/rate 25 | #rate.ws.app=/rest-api-ws 26 | 27 | #SPI 28 | #rate.spi.directory=. 29 | #rate.spi.file-pattern=rates*.txt 30 | #rate.spi.process-directory='output' 31 | #rate.spi.queue=spi.rate 32 | 33 | #Cloud Stream 34 | spring.cloud.stream.bindings.input.destination=rates 35 | spring.cloud.stream.bindings.output.destination=rates 36 | 37 | spring.cloud.stream.bindings.output.content-type=application/json 38 | spring.jackson.date-format=yyyy-MM-dd -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/rest-api-cloud-stream/src/main/resources/public/error/4xx.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Error: BAD REQUEST!

4 |

5 | Take a look at the Body/Path/Parameter format. 6 |

7 | 8 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/rest-api-cloud-stream/src/main/resources/public/error/5xx.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Error: BAD REQUEST!

4 |

5 | Take a look at the Body/Path/Parameter format. 6 |

7 | 8 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch09/rest-api-cloud-stream/src/test/java/com/apress/messaging/RestApiCloudStreamApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class RestApiCloudStreamApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch10/reactor-demo/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch10/reactor-demo/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/spring-boot-messaging/02b8fff85fbfe7082e36872b73631af1dc3671bc/Pro Spring Messaging Source Code/ch10/reactor-demo/src/main/resources/application.properties -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch10/reactor-demo/src/test/java/com/apress/messaging/ReactorDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class ReactorDemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch10/rxjava-demo/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch10/rxjava-demo/src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | security: 2 | basic: 3 | enabled: false 4 | 5 | yahoo: 6 | client-id: dj0yJmk9emcxQU5XQWVaTXY2JmQ9WVdrOVJtWnVZV0ZJTm0wbWNHbzlNQS0tJnM9Y29uc3VtZXJzZWNyZXQmeD00Zg-- 7 | client-secret: 2134dfca8d11673217d1768741428fc598daa447 8 | user-authorization-uri: https://api.login.yahoo.com/oauth2/request_auth 9 | access-token-uri: https://api.login.yahoo.com/oauth2/get_token 10 | grant-type: password 11 | token-name: token -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch10/rxjava-demo/src/test/java/com/apress/messaging/RxJavaDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class RxJavaDemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch10/spring-web-flux-reactive/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch10/spring-web-flux-reactive/src/main/java/com/apress/messaging/config/ReactiveConfig.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.integration.dsl.channel.MessageChannels; 6 | import org.springframework.messaging.SubscribableChannel; 7 | 8 | @Configuration 9 | public class ReactiveConfig { 10 | 11 | @Bean 12 | public SubscribableChannel personChannel(){ 13 | return MessageChannels.publishSubscribe().get(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch10/spring-web-flux-reactive/src/main/java/com/apress/messaging/domain/Person.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.domain; 2 | 3 | import org.springframework.data.annotation.Id; 4 | import org.springframework.data.mongodb.core.mapping.Document; 5 | 6 | @Document 7 | public class Person { 8 | 9 | @Id 10 | private String id; 11 | private String name; 12 | private Integer age; 13 | 14 | public Person(){} 15 | 16 | public Person(String name, Integer age) { 17 | this.name = name; 18 | this.age = age; 19 | } 20 | 21 | public String getId() { 22 | return id; 23 | } 24 | 25 | public void setId(String id) { 26 | this.id = id; 27 | } 28 | 29 | public String getName() { 30 | return name; 31 | } 32 | 33 | public void setName(String name) { 34 | this.name = name; 35 | } 36 | 37 | public Integer getAge() { 38 | return age; 39 | } 40 | 41 | public void setAge(Integer age) { 42 | this.age = age; 43 | } 44 | 45 | @Override 46 | public String toString() { 47 | return "Person [id=" + id + ", name=" + name + ", age=" + age + "]"; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch10/spring-web-flux-reactive/src/main/java/com/apress/messaging/repository/PersonRepository.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.repository; 2 | 3 | import java.util.stream.Stream; 4 | 5 | import org.springframework.data.mongodb.repository.MongoRepository; 6 | import org.springframework.data.mongodb.repository.Query; 7 | 8 | import com.apress.messaging.domain.Person; 9 | 10 | public interface PersonRepository extends MongoRepository{ 11 | 12 | //CompletableFuture getById(String id); 13 | 14 | @Query("{}") 15 | Stream getAll(); 16 | } -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch10/spring-web-flux-reactive/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/spring-boot-messaging/02b8fff85fbfe7082e36872b73631af1dc3671bc/Pro Spring Messaging Source Code/ch10/spring-web-flux-reactive/src/main/resources/application.properties -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch10/spring-web-flux-reactive/src/test/java/com/apress/messaging/SpringWebFluxReactiveApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class SpringWebFluxReactiveApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch10/spring-web-flux/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch10/spring-web-flux/src/main/java/com/apress/messaging/domain/Person.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.domain; 2 | 3 | import org.springframework.data.annotation.Id; 4 | import org.springframework.data.mongodb.core.mapping.Document; 5 | 6 | @Document 7 | public class Person { 8 | 9 | @Id 10 | private String id; 11 | private String name; 12 | private Integer age; 13 | 14 | public Person(){} 15 | 16 | public Person(String name, Integer age) { 17 | this.name = name; 18 | this.age = age; 19 | } 20 | 21 | public String getId() { 22 | return id; 23 | } 24 | 25 | public void setId(String id) { 26 | this.id = id; 27 | } 28 | 29 | public String getName() { 30 | return name; 31 | } 32 | 33 | public void setName(String name) { 34 | this.name = name; 35 | } 36 | 37 | public Integer getAge() { 38 | return age; 39 | } 40 | 41 | public void setAge(Integer age) { 42 | this.age = age; 43 | } 44 | 45 | @Override 46 | public String toString() { 47 | return "Person [id=" + id + ", name=" + name + ", age=" + age + "]"; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch10/spring-web-flux/src/main/java/com/apress/messaging/repository/PersonRepository.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.repository; 2 | 3 | import java.util.stream.Stream; 4 | 5 | import org.springframework.data.mongodb.repository.MongoRepository; 6 | import org.springframework.data.mongodb.repository.Query; 7 | 8 | import com.apress.messaging.domain.Person; 9 | 10 | public interface PersonRepository extends MongoRepository{ 11 | 12 | //CompletableFuture getById(String id); 13 | 14 | @Query("{}") 15 | Stream getAll(); 16 | } -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch10/spring-web-flux/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/spring-boot-messaging/02b8fff85fbfe7082e36872b73631af1dc3671bc/Pro Spring Messaging Source Code/ch10/spring-web-flux/src/main/resources/application.properties -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch10/spring-web-flux/src/test/java/com/apress/messaging/SpringWebFluxApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class SpringWebFluxApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch10/web-emitter/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch10/web-emitter/src/main/java/com/apress/messaging/WebEmitterApplication.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class WebEmitterApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(WebEmitterApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch10/web-emitter/src/main/java/com/apress/messaging/config/EmitterProperties.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | @ConfigurationProperties(prefix = "emitter") 6 | public class EmitterProperties { 7 | 8 | private String directory; 9 | private String filePattern; 10 | 11 | public String getDirectory() { 12 | return directory; 13 | } 14 | 15 | public void setDirectory(String directory) { 16 | this.directory = directory; 17 | } 18 | 19 | public String getFilePattern() { 20 | return filePattern; 21 | } 22 | 23 | public void setFilePattern(String filePattern) { 24 | this.filePattern = filePattern; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch10/web-emitter/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | ## 2 | emitter.directory=${HOME}/Desktop/Names 3 | emitter.file-pattern=*.txt -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch10/web-emitter/src/test/java/com/apress/messaging/WebEmitterApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class WebEmitterApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch11/circuit-breaker-service-demo/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch11/circuit-breaker-service-demo/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | security.basic.enabled=false 2 | management.security.enabled=false -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch11/circuit-breaker-service-demo/src/test/java/com/apress/messaging/CircuitBreakerServiceDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class CircuitBreakerServiceDemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch11/config-client-demo/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch11/config-client-demo/src/main/java/com/apress/messaging/ConfigClientDemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | @RestController 10 | @SpringBootApplication 11 | public class ConfigClientDemoApplication { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(ConfigClientDemoApplication.class, args); 15 | } 16 | 17 | // This variable must be in the Github repository in the simple-config-client.properties file. 18 | @Value("${hello-world-message}") 19 | String message; 20 | 21 | @GetMapping("/") 22 | public String famousHelloWorld(){ 23 | return message; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch11/config-client-demo/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=simple-config-client 2 | 3 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch11/config-client-demo/src/test/java/com/apress/messaging/ConfigClientDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class ConfigClientDemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch11/config-server-demo/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch11/config-server-demo/src/main/java/com/apress/messaging/ConfigServerDemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.config.server.EnableConfigServer; 6 | 7 | @SpringBootApplication 8 | @EnableConfigServer 9 | public class ConfigServerDemoApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(ConfigServerDemoApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch11/config-server-demo/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # Default port 2 | server.port=${port:8888} 3 | 4 | # Spring Config Server 5 | spring.cloud.config.server.git.uri=https://github.com//your-repo-app-config.git 6 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch11/config-server-demo/src/test/java/com/apress/messaging/ConfigServerDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class ConfigServerDemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch11/service-registry-client-demo/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch11/service-registry-client-demo/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/spring-boot-messaging/02b8fff85fbfe7082e36872b73631af1dc3671bc/Pro Spring Messaging Source Code/ch11/service-registry-client-demo/src/main/resources/application.properties -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch11/service-registry-client-demo/src/test/java/com/apress/messaging/ServiceRegistryClientDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class ServiceRegistryClientDemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch11/service-registry-server-demo/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch11/service-registry-server-demo/src/main/java/com/apress/messaging/ServiceRegistryDemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; 6 | 7 | @SpringBootApplication 8 | @EnableEurekaServer 9 | public class ServiceRegistryDemoApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(ServiceRegistryDemoApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch11/service-registry-server-demo/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # Defautl Server Port 2 | server.port=${port:8761} 3 | 4 | # Eureka Configuration 5 | eureka.instance.hostname=localhost 6 | eureka.client.register-with-eureka=false 7 | eureka.client.fetch-registry=false 8 | eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/ 9 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch11/service-registry-server-demo/src/test/java/com/apress/messaging/ServiceRegistryDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class ServiceRegistryDemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch11/service-registry-service-demo/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch11/service-registry-service-demo/src/main/java/com/apress/messaging/ServiceRegistryServiceDemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | @RestController 10 | @SpringBootApplication 11 | @EnableDiscoveryClient 12 | public class ServiceRegistryServiceDemoApplication { 13 | 14 | public static void main(String[] args) { 15 | SpringApplication.run(ServiceRegistryServiceDemoApplication.class, args); 16 | } 17 | 18 | @GetMapping("/message") 19 | public String getMessage(){ 20 | return "Hello World from a Service Discovery"; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch11/service-registry-service-demo/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=8181 2 | 3 | spring.application.name=simple-service -------------------------------------------------------------------------------- /Pro Spring Messaging Source Code/ch11/service-registry-service-demo/src/test/java/com/apress/messaging/ServiceRegistryServiceDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.apress.messaging; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class ServiceRegistryServiceDemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Apress Source Code 2 | 3 | This repository accompanies [*Spring Boot Messaging*](http://www.apress.com/9781484212257) by Felipe Gutierrez (Apress, 2017). 4 | 5 | [comment]: #cover 6 | 7 | 8 | Download the files as a zip using the green button, or clone the repository to your machine using Git. 9 | 10 | ## Releases 11 | 12 | Release v1.0 corresponds to the code in the published book, without corrections or updates. 13 | 14 | ## Contributions 15 | 16 | See the file Contributing.md for more information on how you can contribute to this repository. 17 | -------------------------------------------------------------------------------- /contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing to Apress Source Code 2 | 3 | Copyright for Apress source code belongs to the author(s). However, under fair use you are encouraged to fork and contribute minor corrections and updates for the benefit of the author(s) and other readers. 4 | 5 | ## How to Contribute 6 | 7 | 1. Make sure you have a GitHub account. 8 | 2. Fork the repository for the relevant book. 9 | 3. Create a new branch on which to make your change, e.g. 10 | `git checkout -b my_code_contribution` 11 | 4. Commit your change. Include a commit message describing the correction. Please note that if your commit message is not clear, the correction will not be accepted. 12 | 5. Submit a pull request. 13 | 14 | Thank you for your contribution! --------------------------------------------------------------------------------