Granny's Programming Pearls
"inside of every large program is a small program struggling to get out"
JavaRanch.com/granny.jsp
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Liutauras Vilda
  • Bear Bibeault
  • Junilu Lacar
  • Martin Vashko
Sheriffs:
  • Jeanne Boyarsky
  • Tim Cooke
  • Knute Snortum
Saloon Keepers:
  • Ron McLeod
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
Bartenders:
  • Scott Selikoff
  • salvin francis
  • Piet Souris

Unable to Start Tomcat9 Programmatically - Stops at 'Creation of SecureRandom instance ...'

 
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Greetings,

I am trying to create a basic web application to start building upon. I started from scratch with only Maven and the pom.xml. I am trying to embed Tomcat9 to bundle the whole application as a single JAR. The problem I am having is Tomcat doesn't seem to fully start. I'm not very knowledgable when it comes to setting up the logging, so in this scenario I'm not sure where to get more details on what's happening.

The last line in the log reads 'WARNING: Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [175] milliseconds.' After this, nothing else happens.

I followed this tutorial (link below) for comparison and it ran successfully, so I tried to apply it to my program, but it's just not happening.
https://devcenter.heroku.com/articles/create-a-java-web-application-using-embedded-tomcat

I would appreciate any input on this, thanks!
The repo link for the project is below:
https://github.com/Wawawarrior/ddshop
Tomcat 9.0.10
Java Compiler 1.9


Here is the Main.java for quick reference:

 
Saloon Keeper
Posts: 21306
140
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Technically this is known as "embedded Tomcat", because the Tomcat server is embedded inside another application.

These days, you're actually probably better off using Spring Boot, since that's exactly what Spring Boot is for, so the work is mostly done for you.

However, check the logs. Not just stdout/stderr (catalina.out), but also look for logs/localhost logfiles. Many failures early in Tomcat startup are recorded there.
 
Wayne Woodrow
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you for the response, I will try that. Right now there are no log files so I think I need to figure out how to get that first. I assume they would be in the circled area (attachment) if they were being generated?

tomcatempty.png
[Thumbnail for tomcatempty.png]
 
Tim Holloway
Saloon Keeper
Posts: 21306
140
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I don't know. In stand-alone tomcat, there's a conf/logging.properties file that defines where the logfiles go. In its factory version, they're placed under ${catalina.base}/logs.

catalina.base is assigned from the environment variable CATALINA_BASE, which is defined in the Tomcat startup scripts.

However, it's less clear how an embedded Tomcat would define logging. If it falls back to the JDK logging configuration, logging would go to the home directory of the user running the Tomcat application server.
 
Wayne Woodrow
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello again,

I started reading up on how to access the logging and tried a few different things, but I'm still not having any luck getting more information on why the startup ends where it does.

The code for my latest attempt is below. I retrieved the LogManager to get a list of all loggers. After checking that the loggers are not null, I set the level to ALL for each of the loggers listed, which seems to work okay. However, once I run the application, it doesn't seem to have any effect. I still get the usual INFO: and WARNING: messages but nothing else. I feel like there's another instance of a logger somewhere that I need to set to ALL, but if the LogManager doesn't see it then where would it be?

Any ideas would be appreciated. Attached is a screenshot of the console

console.png
[Thumbnail for console.png]
 
Tim Holloway
Saloon Keeper
Posts: 21306
140
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I believe that in the normal course of events there should be a log message telling how long it took Tomcat to start.

As a precaution, I'd add a log message after the Tomcat "await()" call, just to ensure you know when Tomcat has shut down and returned to you.

Beyond that, it looks maybe hung up, so just wait a while and see if something times out and reports an error. And by "a while", I'm suggesting go make coffee or something, because it might be a LONG while!
 
Wayne Woodrow
Greenhorn
Posts: 22
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Good afternoon,

So I have still been trying intermittently to get this to work, pulling from various examples (all on Tomcat versions other than 9), but I'm still getting the same result.

However, I had some slight success today in finding that the code below works with Tomcat 8.5, but not with Tomcat 9. So I guess there's an extra step or something different I need to do on version 9 to get this running, and I'm a little frustrated about that. But I am glad to at least have something working so I know I'm not completely off base.

See the attached images to compare the output. I think I'm going to keep messing with Tomcat 9 because I want to know why it's not working, so if you still have any tips I would be grateful for your input, thanks!


success.png
[Thumbnail for success.png]
failure.png
[Thumbnail for failure.png]
 
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I was facing the same problem. I changed to embedded tomcat 8.5.23
Thank you so much buddy.  I wonder whats the problem with 9.0.10 though?
 
Sheriff
Posts: 6439
172
Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Wayne Woodrow,

Just a note about posting that will get you more help and quicker: don't post screenshots of text.  Instead, copy and paste the text.
 
Tim Holloway
Saloon Keeper
Posts: 21306
140
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I noticed this earlier, but now I'm wondering. "Global web.xml not found."

You might want to research that.

Tomcat has a clever way to deal with URLs that have no explicit handler in a webapp. For example, directory listing and fetching images and other static content. It does that by using a built-in "default servlet" which contains the code that constructs the index pages and copies image resources to the response stream (with appropriate headers). A default servlet implies a default web.xml, so maybe there's something missing here. As I recall, in earlier versions of Tomcat, the default servlet was assigned from something in the Tomcat "conf" directory, and while I'm too lazy to check, it could have been an actual default web.xml file.

Yes, I know, recent enhancements have made it possible to code webapps that "don't have" a web.xml file, but web.xml is simply a spec file that gets digested into a collection of application resources, including the sub-URL routings, the security templates and so forth. Just because you can now do most of this stuff via annotations doesn't mean that the web.xml equivalent structure has gone away.
 
Wayne Woodrow
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for all your replies, and Noel I feel a little better knowing I wasn't alone on this.

Tim thanks for the additional information. I'm still trying to understand everything you said and how to go about figuring this stuff out... You referred to earlier versions of Tomcat, but I just wanted to mention quickly that 8.5 also shows the 'Global web.xml not found' message, but then continues to work. Below is the console output with the app starts:


 
Greenhorn
Posts: 1
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I had the same problem. This answer by Christopher Schultz got my tomcat server working again.
was all I needed to add. Tomcat 8 did this automatically, version 9 does not.
 
Wayne Woodrow
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

James Kieliszek wrote:I had the same problem. This answer by Christopher Schultz got my tomcat server working again.
was all I needed to add. Tomcat 8 did this automatically, version 9 does not.



Thanks for the information. This got me a step further!

Unfortunately, I just came back to this a year later, and I'm trying to set up another simple example. I made the addition that you showed me above, and would like to serve a simple index.html file from the webapp folder. However, whenever I try to access http://localhost:8080 or http://localhost:8080/index.html, I get a 404 error.

File Structure (attached)
App.java


2019-11-25-16_24_19-Window.png
[Thumbnail for 2019-11-25-16_24_19-Window.png]
 
Tim Holloway
Saloon Keeper
Posts: 21306
140
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I haven't studied the embedded Tomcat bean so I'm not sure about the convenience functions, but this is how Tomcat itself works. Tomcat creates within a Server object one or more Host objects - the default one is named "localhost". Each Host has one or more Connectors. A Connector object (bean) has a port number and a protocol type. So the standard Tomcat server.xml file, for example, defines the default Host with a Connector for http on port 8080, one for https on 8443, and about 2 more having to do with proxy and control functions.

I'll take it as a given that the functions that have been shown basically set or query those properties as shortcuts so you don't have to grind your way up and down the object graph that is the actual Tomcat server.

In the case of webapps, however, the Tomcat webapps directory is not where you dump your webapp files. The webapps directory can hold multiple webapps. So each webapp appears as a subdirectory under TOMCAT_HOME/webapps.

Each of those subdirectories is an exploded (unzipped) WAR file. And by default, tomcat will assign a URL context to that webapp based on the name of the exploded WAR directory. So, for example, TOMCAT_HOME/webapps/mywebapp would have a base URL of http://localhost:8080/mywebapp/.

The one exception to this is the root URL - http://localhost:8080/. Since neither (nothing) nor "/" are valid directory names on most OS's, the root webapp exists in a directory named ROOT. So if you request http://localhost:8080/index.jsp, the file location in an exploded WAR would be TOMCAT_HOME/webapps/ROOT/index.jsp.

If you are trying to serve Tomcat out of a Maven project directory, the path you want isn't src/main/webapp. That's where the static assets used to BUILD the WAR are held, but none of the classes or dependent JARs (if any). For Maven, you'd do a "mvn compile war:war" to compile the source code and build a WAR, and Maven would place the WAR in its target/warname directory exploded, along with a target/warname.war directory for the unexploded WAR. Where "warname" is the name you defined in the pom.xml file.

So, assuming you wanted to run embedded Tomcat against a maven project copy of a WAR, your context would be set something like this:


I'm pretty sure you need "/", not "" as the context path there. Note I used addWebapp. The Tomcat bean allows you to build up a webapp piece by piece on the fly, and if you do that, I think you'd use addContext(), but if you have a ready-to-run WAR, I think you need addWebapp, which handles all the odds and ends for you. Note that both methods have an optional Host parameter. If you don't use it, the localhost Host is assumed.

The webappDir is the root of an exploded WAR, so what Tomcat actually builds will work identically to what you'd get if you copied the entire WAR directory to TOMCAT_HOME/webapps. And to repeat, it's the webapp directory itself, not just its separate contents.
 
Tim Holloway
Saloon Keeper
Posts: 21306
140
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I just re-read the initial post. Actually, if you're just starting out with webapps, an embedded Tomcat is making things too complicated. Use a regular (stand-alone) Tomcat, build your WAR with Maven, deploy it to the stand-alone Tomcat and start Tomcat (or start Tomcat and deploy, either way works).

If you really wanted an all-on-one executable embedded Tomcat+application JAR, the best bet is to use Spring Boot. It's all the rage these days.
 
Wayne Woodrow
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Tim, thanks for the response and the explanation on the webapp directories. I always have to go back and reference that.

I have some good news as well... It's finally working.

The link below has a good example for the embedded Tomcat, and they provide a download of the project files. Although, I had to switch back to JDK 8 for the example, as I was getting a 404 error when doing the 'mvn clean package' using JDK 13.
https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/basic_app_embedded_tomcat/basic_app-tomcat-embedded.html#overview

So then I switched back to my own application, and after making some adjustments it's now serving the index.html page.

Here's what I adjusted:
- Added the directory and targetPath values to the POM
+

- Copied the Main method contents from the example, with the addition of the 'tomcat.getConnector()' line as mentioned in one of the earlier comments.
 + After some experimenting, the key was setting the appBase with the function 'tomcat.getHost().setAppBase(appBase)'. Also, I had to change the 'tomcat.addContext' function to 'tomcat.addWebapp(contextPath, appBase)'.

- Added the function 'tomcat.getConnector()' that James mentioned ealier in the thread (for Tomcat 9).

Interestingly, it doesn't seem to matter where appBase is set, as long as the folder exists. In the code it's set to '.', but I also tried 'C:/' and 'C:/dev' and it worked just fine.

What's still bugging me is that I don't know how to use 'tomcat.addContext(..., ...)'. It seems like one should be able to use that to serve up a static file. I can almost die happy, but I guess I'll let that go for right now. Perhaps it will become clear a bit further down the road.

Here are the pom and app files in all their glory:
App.java


pom.xml
 
Saloon Keeper
Posts: 2791
367
Android Eclipse IDE Angular Framework MySQL Database TypeScript Redhat Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Tim Holloway wrote:If you really wanted an all-on-one executable embedded Tomcat+application JAR, the best bet is to use Spring Boot.

If you want a JEE environment, TomEE works well.  I have used it on a few projects as an embedded server or a single zip file distribution.  Integrates well with Maven too.
 
Tim Holloway
Saloon Keeper
Posts: 21306
140
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If your POM is setup to build a WAR instead of a JAR, you don't need to add resource "from" and "to" locations. The default "from" copy location is src/main/webapp, and the default "to" copy location is the root of the WAR that Maven creates in the target directory. Everything is taken care of properly. To put a /WEB-INF/classes/log4j.xml file into a WAR, you'd create its source in src/main/webapp/WEB-INF/classes/log4j.xml.

Tomcat does not "serve pages". It serves webapps. It has no concept of free-floating resources, only WARs. The addContext method is intended to map a URL context path to a WAR. The difference between addContext() and addWebapp() is that addWebapp() invokes addContext() as one of a number of functions involved in deploying a WAR. You'd only use addContext() if you were deploying a WAR by sheer brute force and wanted to manually call the functions that addWebapp() calls automatically.
 
I found a beautiful pie. And a tiny ad:
Java file APIs (DOC, XLS, PDF, and many more)
https://products.aspose.com/total/java
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!