001/* 002 * Copyright 2012-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.boot.actuate.jms; 018 019import java.util.concurrent.CountDownLatch; 020import java.util.concurrent.TimeUnit; 021 022import javax.jms.Connection; 023import javax.jms.ConnectionFactory; 024import javax.jms.JMSException; 025 026import org.apache.commons.logging.Log; 027import org.apache.commons.logging.LogFactory; 028 029import org.springframework.boot.actuate.health.AbstractHealthIndicator; 030import org.springframework.boot.actuate.health.Health; 031import org.springframework.boot.actuate.health.HealthIndicator; 032 033/** 034 * {@link HealthIndicator} for a JMS {@link ConnectionFactory}. 035 * 036 * @author Stephane Nicoll 037 * @since 2.0.0 038 */ 039public class JmsHealthIndicator extends AbstractHealthIndicator { 040 041 private final Log logger = LogFactory.getLog(JmsHealthIndicator.class); 042 043 private final ConnectionFactory connectionFactory; 044 045 public JmsHealthIndicator(ConnectionFactory connectionFactory) { 046 super("JMS health check failed"); 047 this.connectionFactory = connectionFactory; 048 } 049 050 @Override 051 protected void doHealthCheck(Health.Builder builder) throws Exception { 052 try (Connection connection = this.connectionFactory.createConnection()) { 053 new MonitoredConnection(connection).start(); 054 builder.up().withDetail("provider", 055 connection.getMetaData().getJMSProviderName()); 056 } 057 } 058 059 private final class MonitoredConnection { 060 061 private final CountDownLatch latch = new CountDownLatch(1); 062 063 private final Connection connection; 064 065 MonitoredConnection(Connection connection) { 066 this.connection = connection; 067 } 068 069 public void start() throws JMSException { 070 new Thread(() -> { 071 try { 072 if (!this.latch.await(5, TimeUnit.SECONDS)) { 073 JmsHealthIndicator.this.logger.warn( 074 "Connection failed to start within 5 seconds and will be closed."); 075 closeConnection(); 076 } 077 } 078 catch (InterruptedException ex) { 079 Thread.currentThread().interrupt(); 080 } 081 }, "jms-health-indicator").start(); 082 this.connection.start(); 083 this.latch.countDown(); 084 } 085 086 private void closeConnection() { 087 try { 088 this.connection.close(); 089 } 090 catch (Exception ex) { 091 // Continue 092 } 093 } 094 095 } 096 097}