启动后,Spring启动应用程序(不是Web)停止

时间:2018-01-21 19:08:23

标签: spring-boot

我有google cloud pubsub订阅者应用程序(问题与pubsub无关,我相信与jms监听器有相同的行为)。 它不需要像tomcat或其他这样的网络容器(有很多问题,问题是缺少容器依赖,这里我不需要webcontainer)。它应该启动并处理消息。问题:它在启动后停止。

应用程序非常简单,这里是build.gradle文件:

buildscript {
    ext {
        springBootVersion = '1.5.8.RELEASE'
    }
    repositories {
        mavenLocal()
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'

sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
    mavenLocal()
    mavenCentral()
}

dependencies {
    compile 'org.springframework.boot:spring-boot-starter'
}

这是应用程序启动器:

@SpringBootApplication
public class CommunicationApplication {

    public static void main(String[] args) throws IOException {
        SpringApplication.run(CommunicationApplication.class, args);

        //waiting data from system input to prevent stop after start
        //System.in.read();
    }

}

这是pubsub manager bean(它创建了pubsub监听器)

@Component
public class PubsubManager {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private MessageReceiver messageReceiver;

    private Subscriber subscriber;

    @PostConstruct
    protected void start() throws Exception {
        createTopic();
        createSubscriber();
    }

    private void createTopic() throws Exception {
        TopicName topic = TopicName.of(ServiceOptions.getDefaultProjectId(), "COMMUNICATION_TOPIC_NAME");
        try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) {
            topicAdminClient.createTopic(topic);
            logger.info("Topic {}:{} created", topic.getProject(), topic.getTopic());
        } catch (ApiException e) {
            if (e.getStatusCode().getCode() == StatusCode.Code.ALREADY_EXISTS) {
                logger.info("Topic {}:{} already exist", topic.getProject(), topic.getTopic());
            } else {
                logger.error("Error create topic: {}", e.getStatusCode().getCode());
            }
            logger.info("isRetryable: {}", e.isRetryable());
        }
    }

    private void createSubscriber() throws Exception {
        SubscriptionName subscriptionName = SubscriptionName.of(ServiceOptions.getDefaultProjectId(),
                MessagingConstants.COMMUNICATION_SUBSCRIPTION_NAME);
        // create a subscriber bound to the asynchronous message receiver
        try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {
            TopicName topicName = TopicName.of(ServiceOptions.getDefaultProjectId(),
                    "COMMUNICATION_TOPIC_NAME");
            Subscription subscription = subscriptionAdminClient.createSubscription(
                            subscriptionName, topicName, PushConfig.getDefaultInstance(), 0);
        } catch (Exception e) {
            logger.info("subscription already created:", e);
        }
        subscriber = Subscriber.newBuilder(subscriptionName, messageReceiver).build();
        subscriber.startAsync().awaitRunning();
        logger.info("subscriber start receiving messages");
    }

    @PreDestroy
    protected void close() throws Exception {
        logger.info("subscriber stop receiving messages");
        subscriber.stopAsync();
    }
}

如果我取消注释System.in.read(); - 它适用于本地环境,但在云端它不起作用。你能建议正确的解决方法吗?感谢。

1 个答案:

答案 0 :(得分:1)

如果您只想创建PubSub Listener,以下内容对我有用:

  1. git clone https://github.com/spring-guides/gs-messaging-gcp-pubsub
  2. cd gs-messaging-gcp-pubsub/complete
  3. 将build.gradle文件更改为下面的build.gradle文件。
  4. cd gs-messaging-gcp-pubsub/complete/src/main/resources进入后,您可以删除静态文件夹。
  5. 转到gs-messaging-gcp-pubsub / complete / src / main / java / hello;在那里你应该有两个文件:PubSubApplication.java和WebAppController.java。删除WebAppController.java并将PubSubApplication.java更改为以下文件:
  6. 的build.gradle:

    buildscript { 
        repositories {
            mavenCentral()
        }
        dependencies {
            classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.9.RELEASE")
        }    
    }
    
    apply plugin: 'java'
    apply plugin: 'eclipse'
    apply plugin: 'org.springframework.boot'
    
    jar {
        baseName = 'gs-spring-cloud-gcp'
        version =  '0.1.0'
    }
    
    repositories {
        mavenCentral()
        maven {
            url "http://repo.spring.io/snapshot"
        }
    }
    
    sourceCompatibility = 1.8
    targetCompatibility = 1.8
    
    dependencies {
        compile("org.springframework.cloud:spring-cloud-gcp-starter-pubsub:1.0.0.BUILD-SNAPSHOT")
        compile("org.springframework.cloud:spring-integration-gcp:1.0.0.BUILD-SNAPSHOT")
    }
    

    pubSubApplication.java

    package hello;
    
    import java.io.IOException;
    
    import com.google.cloud.pubsub.v1.AckReplyConsumer;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.gcp.pubsub.core.PubSubOperations;
    import org.springframework.cloud.gcp.pubsub.core.PubSubTemplate;
    import org.springframework.cloud.gcp.pubsub.support.GcpHeaders;
    import org.springframework.context.annotation.Bean;
    import org.springframework.integration.annotation.MessagingGateway;
    import org.springframework.integration.annotation.ServiceActivator;
    import org.springframework.integration.channel.DirectChannel;
    import org.springframework.integration.gcp.pubsub.AckMode;
    
    import org.springframework.integration.gcp.pubsub.inbound.PubSubInboundChannelAdapter;
    import org.springframework.integration.gcp.pubsub.outbound.PubSubMessageHandler;
    import org.springframework.messaging.MessageChannel;
    import org.springframework.messaging.MessageHandler;
    
    @SpringBootApplication
    public class PubSubApplication {
    
      private static final Log LOGGER = LogFactory.getLog(PubSubApplication.class);
    
      public static void main(String[] args) throws IOException {
        SpringApplication.run(PubSubApplication.class, args);
      }
    
    
      @Bean
      public MessageChannel pubsubInputChannel() {
        return new DirectChannel();
      }
    
      @Bean
      public PubSubInboundChannelAdapter messageChannelAdapter(
          @Qualifier("pubsubInputChannel") MessageChannel inputChannel,
          PubSubOperations pubSubTemplate) {
        PubSubInboundChannelAdapter adapter =
            new PubSubInboundChannelAdapter(pubSubTemplate, "testSubscription");
        adapter.setOutputChannel(inputChannel);
        adapter.setAckMode(AckMode.MANUAL);
    
        return adapter;
    
    
          }
    
      @Bean
      @ServiceActivator(inputChannel = "pubsubInputChannel")
      public MessageHandler messageReceiver() {
        return message -> {
          LOGGER.info("Message arrived! Payload: " + message.getPayload());
          AckReplyConsumer consumer =
              (AckReplyConsumer) message.getHeaders().get(GcpHeaders.ACKNOWLEDGEMENT);
          consumer.ack();
        };
    
      }
    
    }
    

    更改“testSubscription”to the Subscription you are using

    现在在文件夹gs-messaging-gcp-pubsub / complete中,如果运行./gradlew bootRun,应用程序hello.PubSubApplication应该在本地运行。您发布到订阅主题的任何消息都应显示在运行应用程序的位置。

    如果您在凭据/认证方面遇到问题,请更改以下参数:

    GS-消息传递的GCP-发布订阅/完整/ SRC /主/资源/ application.properties