Thursday, June 11, 2020

Initializing git repo and setting remote

I have been creating a lot of git repos recently. I am tired of looking up the same information again and again.

I have been creating a lot of Java projects as I experiment with Spring Boot. After creating a repo, I experiment with it a bit, then decide if I want to keep working in it.

The first step is to change to the project directory and and a .gitignore file. I have been using Java on a Mac and this is the file I use.

HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**
!**/src/test/**

### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache

### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/

### VS Code ###
.vscode/
 
# Compiled class file
*.class

# Log file
*.log

# BlueJ files
*.ctxt

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

# Mac OS $
.DS_Store


Execute git init in the project folder. This creates the .git folder that is the local repo.

I am using GitHub to store remote copies of the repo. Create a new, empty repo and issue the commands:

git commit -m "first commit"
git remote add origin https://git-username@github.com/git-username/git-repo.git
git push -u origin master
 
After these commands, I can use git push to commit changes.

Monday, June 8, 2020

Creating webapp using Spring Boot and Maven

I created a base Spring Boot project to see all the dependencies I needed for a simple web application.

I created a simple Spring Boot project using the Initializr. It had no extra packages added.

I added the spring-boot-starter-web package, which included tomcat. Tomcat had type 'provided'. If I omitted the version, the war did not work when deployed, but worked locally.

I created a simple home controller using the Controller annotation and the GetMapping annotation.

The default view resolver is to the /src/main/resources/static folder without an extension. I created home.html in the static package and the page was found. Static is copied to WEB-INF/classes.

I wanted to deploy the app to an external tomcat installation. I extended the application class from SpringBootServletInitializer to create a war file and identify the starting application.

I added a view resolver and set the view class to JSTL. I had to add a dependency for jstl. I had to add a webapp folder for the JSPs, /src/main/webapp. The path is to the root of the web app. I did not want my JSPs in the classes folder.

Be sure that the path to the JSTL library is http and not https.

These are all the updated files to get it working:

@SpringBootApplication
public class DemoApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }             
        @Override
        protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
           return application.sources(DemoApplication.class);
        }
        
        @Bean
        public ViewResolver internalResourceViewResolver() {
            InternalResourceViewResolver bean = new InternalResourceViewResolver();
            bean.setViewClass(JstlView.class);
            bean.setPrefix("/WEB-INF/jsp/");
            bean.setSuffix(".jsp");
            return bean;
        }

}

pom.xml


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.3.0.RELEASE</version>
            <type>jar</type>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <version>9.0.35</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
index.jsp

<%-- 
    Document   : index
    Created on : Jun 8, 2020, 1:01:38 PM
--%>

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
        <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

    <c:choose>
        <c:when test="${not empty param.name}">
            <h1>Hello ${param.name}</h1>
        </c:when>
        <c:otherwise>
            <h1>Hello Stranger</h1>
        </c:otherwise>
    </c:choose>
    
</body>
</html>



Wednesday, June 3, 2020

HttpClient Daemon Threads

I have discovered that java.net.http.HttpClient.send leaves daemon threads that do not terminate when interrupted.

I am using
  • Maven 1.6
  • Java 1.14
  • NetBeans 11.3
When I make a simple HTTP request using HttpClient.send using the maven goal exec.java, the code runs, but pauses and I get these warnings after 15 seconds, and then the app stops:

thread Thread[HttpClient-1-Worker-0,5,org.sonatype.mavenbook.ch07.simple.weather.oauth.lone.WeatherYdnJava] was interrupted but is still alive after waiting at least 14997msecs
thread Thread[HttpClient-1-Worker-0,5,org.sonatype.mavenbook.ch07.simple.weather.oauth.lone.WeatherYdnJava] will linger despite being asked to die via interruption
thread Thread[HttpClient-1-Worker-1,5,org.sonatype.mavenbook.ch07.simple.weather.oauth.lone.WeatherYdnJava] will linger despite being asked to die via interruption
thread Thread[HttpClient-1-Worker-2,5,org.sonatype.mavenbook.ch07.simple.weather.oauth.lone.WeatherYdnJava] will linger despite being asked to die via interruption
NOTE: 3 thread(s) did not finish despite being asked to  via interruption. This is not a problem with exec:java, it is a problem with the running code. Although not serious, it should be remedied.
Couldn't destroy threadgroup org.codehaus.mojo.exec.ExecJavaMojo$IsolatedThreadGroup[name=org.sonatype.mavenbook.ch07.simple.weather.oauth.lone.WeatherYdnJava,maxpri=10]


It is interesting that if I use the Play button in NetBeans to run the code, it works without any warnings. NetBeans uses exec:exec instead of exec:java. One difference between exec:java and exec:exec is how daemon threads are handled. With exec:java, after maven is done doing its work, maven sends an interrupt to all the daemon threads, hoping that they will terminate nicely. The exec:java goal also runs the code in the same VM as maven.

The exec:exec goal does not show the warning. I do not know the reason, but it could be that it terminates the threads unceremoniously or it waits for them to finish.

Some properties for the exec:java goal control how daemon threads are handled.
  • daemonThreadJoinTimeout - if I set this to 60 seconds or more, then the daemon threads terminate on there own. I assume that the TCP connection was closed by one side, so the threads terminate.
  • cleanupDaemonThreads - if this is set to false, then the threads are not interrupted and the timeout is not used. I assume that the threads are killed.
  • stopUnresponsiveDaemonThreads - this is a bad idea for this example. If I set this to true, the app will never end. As soon as one is killed, another pops up in its place. I assume this would continue for a minute in this case, waiting for the TCP connection to close.
Conclusion: I will use exec:exec. The downside of using exec:exec is that it creates a separate VM to run the java program. If that becomes a problem, I will set cleanUpDaemonThreads to false in the exec:java goal.

Followers