0

I have a java app that is just takes a jar from another project, the jar is using an infinite loop to poll for messages on AWS SQS topic.

The loop looks for methods annotated with @subscriber in my client application.

I have a bean that will return a class which has a method annotated. When I remove the bean that is calling a class with an annotation method my tomcat is started on a port. When i add it in again there is no port hosted.

In the pom file I have these 2 dependencies added (along with some others but these should be the relevant ones)

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

My main class looks like this

@SpringBootApplication
@ComponentScan(basePackages = {"com.mypackage.reuse", "com.mypackage.sample.subscriber"})
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

The logs I get when I start my app

2020-03-12 14:32:56.228  INFO 2429 --- [           main] c.l.g.e.f.sample.subscriber.Application  : The following profiles are active: development
2020-03-12 14:32:57.580  INFO 2429 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 1339 (http)
2020-03-12 14:32:57.586  INFO 2429 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2020-03-12 14:32:57.587  INFO 2429 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.29]
2020-03-12 14:32:57.650  INFO 2429 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2020-03-12 14:32:57.651  INFO 2429 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1363 ms
2020-03-12 14:32:58.038  INFO 2429 --- [           main] org.reflections.Reflections              : Reflections took 111 ms to scan 2 urls, producing 23 keys and 53 values 

there is no log after that I would expect something like this which is what I get if I remove the loop. When i remove the loop i get something like below but the problem is i need the loop to continuously poll.

Exposing 2 endpoint(s) beneath base path '/actuator'
Tomcat started on port(s): 1339 (http) with context path ''
AnonymousAlias
  • 1,149
  • 2
  • 27
  • 68

2 Answers2

1

Since there is no error,

Spring boot probably does something, and it might take time... When the initialization of the application context is done spring boot finally writes "tomcat started on port 1339 message"

I don't know what exactly happens when "reflections API to find methods annotated with @subscirber" but if implemented inefficiently - this can definitely take some time.

So I suggest taking a thread dump and trying to analyze the running threads when you reach the point in log where you feel that the application gets stuck.

Another suspicious point is what you wrote:

When I remove the bean that is calling a class with an annotation method my tomcat is started on a port.

What is this bean exactly? what is the class with an annotation method? Does it try to connect to AWS? If so what if the definitions are wrong and it gets stuck trying to connect? Again the stack trace will clarify a lot of things here.

Update

Threas dump (you should read it from the bottom to the top - it shows the current calls execution chsin) shows that in the SubscriberFactory's constructor you're trying to connect to SQS of Aws and it gets stuck...

This is abnormal situation. Probably you did something wrong with connection parameters.

From the point of view of spring initialization it stucks the whole initialization process, because spring creates the beans one by one in one thread

Anyway, proper connection to sqs will probably resolve the issue.

Update 2

Answering the question of running the bean in different thread.

You dont run the bean but rather the method in the bean.

It should not be a constructor or method annotated with @PostConstruct because these are methods called by spring during the initialization

You can use @Async method in listener that will run when the application is ready.

You can read about asynchronous methods here, in this tutorial (note, you also need @EnableAsync)

The method should be called/implemented im the listener and be public void

The concept of listeners is easy to grasp - these are hooks to application context initialization lifecycle. You'll need to follow thos thread

Mark Bramnik
  • 39,963
  • 4
  • 57
  • 97
  • Yes it does try connect to AWS but it is successful it will use the jar and pull messages from the AWS account. I ran with debug I will update my answer now. – AnonymousAlias Mar 12 '20 at 23:16
  • Updated my question – AnonymousAlias Mar 12 '20 at 23:19
  • tcnative is a tomcat native library that is supposed to facilitate OS native features in tomcat. Apparently there is no library like this, but usually its not an issue. As for the first exception, read: https://stackoverflow.com/questions/50436108/javax-management-instancenotfoundexception-org-springframework-boottype-admin – Mark Bramnik Mar 13 '20 at 05:30
  • I am on a mac i tried lsof -i:1339 to get the pid so i could try a thread dump (not familiar with thread dumping) Apparently there is no process running on that port ? – AnonymousAlias Mar 13 '20 at 08:34
  • Try one of these methods: https://dzone.com/articles/how-to-take-thread-dumps-7-options you should end up with an output that shows what does each threas actually do at the moment of time. – Mark Bramnik Mar 13 '20 at 08:58
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/209560/discussion-between-anonymousalias-and-mark-bramnik). – AnonymousAlias Mar 13 '20 at 09:56
  • Please see the update on my answer (i dont have an access to the pc now so can't really help much - writing from cellphone) – Mark Bramnik Mar 13 '20 at 09:59
  • Thanks for updating I can look into this some more, its strange though i would think if there was a connection issue with SQS then I wouldn't receive the messages – AnonymousAlias Mar 13 '20 at 10:02
  • Update I have managed to debug some more, the jar i am using has an infinite loop it uses to keep polling for messages. If i remove that loop it will receive one message and then come back and initialise tomcat properly. Is there a way to run this bean on a separate thread – AnonymousAlias Mar 13 '20 at 11:53
  • Cool, looks like you've almost solved this riddle :) please see update 2 in the answer – Mark Bramnik Mar 13 '20 at 12:35
  • Excellent answer, unfortunately i've just realised it won't matter if I run the bean async it is actually just importing the jar that causes the issues as it will run the infinite loop. I am going to accept this answer regardless, but do you know if there is way to import via maven dependency only once the other dependencies have loaded? – AnonymousAlias Mar 13 '20 at 13:02
  • Creating a new question will link here – AnonymousAlias Mar 13 '20 at 13:13
  • It doesnt work like this. Jar itself doesnt load anything. Its a bunch of binaries (like dll) and its up to you to call that code in the jar (directly or via spring). Maven works in build time and spring is in runtime.. – Mark Bramnik Mar 13 '20 at 13:16
  • Year, creating another question and link here is a great idea :) – Mark Bramnik Mar 13 '20 at 13:17
  • https://stackoverflow.com/questions/60671212/can-we-add-a-maven-dependency-only-after-one-another-has-been-loaded – AnonymousAlias Mar 13 '20 at 13:18
  • Solved it by running the infinite loop in its own thread in the background. Feel free to comment this as an answer in the link I will accept. – AnonymousAlias Mar 13 '20 at 13:34
0

You override the default Tomcat HTTP port with your application.properties file and that's why you don't see it starting at 8080:

server:
  port: 1339

change it to

server:
  port: 8080

or remove it completly to have the default configuration

rieckpil
  • 10,470
  • 3
  • 32
  • 56
  • No this isn't the case I have tried both ports and removing the port. It is not being advertised it would mention in the logs – AnonymousAlias Mar 12 '20 at 22:16