home.

tagged: java

Docker: install Java8 automatically on ubuntu/debian

If you want to create a docker image with Java, then there's a problem: it'll ask you manually confirm that you agree to the terms and conditions.
 
To automatically do this, add some debconf-set-selections to your script.
 
So the steps are now update, install software properties utils, add the webupd8team repo, set the debconf selections, update again, install java.

apt-get update
apt-get -y install software-properties-common
add-apt-repository -y ppa:webupd8team/java
echo debconf shared/accepted-oracle-license-v1-1 select true | debconf-set-selections
echo debconf shared/accepted-oracle-license-v1-1 seen true | debconf-set-selections
apt-get update
apt-get -y install oracle-java8-installer

docker java


Gradle: Hello world Java with a fat jar

Create your build.gradle with your dependencies and a jar section that collects all your libraries into the jar and sets the Main class file.

apply plugin: 'java'

repositories {
   mavenCentral()
}

dependencies {
    compile 'org.mindrot:jbcrypt:0.3m'
}

jar {
    from {
        (configurations.runtime).collect {
            it.isDirectory() ? it : zipTree(it)
        }
    }
    manifest {
        attributes("Main-Class": "Main" )
    }
}

Now create a basic hello world, using the library we imported:

import org.mindrot.jbcrypt.BCrypt;

public class Main {
        public static void main(String[] args) {
                String password = BCrypt.hashpw("password", BCrypt.gensalt(10));
                System.out.println(password);
        }
}

Now build and run your jar:

$ gradle clean build && java -jar build/libs/THE_NAME_OF_YOUR_JAR.jar
...
$2a$10$R6q8LOed8LqXCOIhBnzhMecyebv/8v1urKjU76JMJGUctnZ8VkyZu

java gradle fat-jar jar bcrypt


A single page Java/Jetty/Jersey REST app with no web.xml descriptor

First create the build.gradle file in your directory:

apply plugin: 'war'
apply plugin: 'eclipse'

repositories {
   mavenCentral()
}

dependencies {
    compile 'org.glassfish.jersey.media:jersey-media-json-jackson:2.16'
    compile 'org.glassfish.jersey.bundles:jaxrs-ri:2.16'
}

compileJava {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}

Then, in src/main/java/com/example, create App.java:

package com.example;

import java.util.ArrayList;
import java.util.List;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import org.glassfish.jersey.server.ResourceConfig;

@ApplicationPath("rest") 
public class App extends ResourceConfig {
  public App() { packages("com.example"); }

  @Path("example")
  public static class Hello {
    
      @GET
      @Produces(MediaType.APPLICATION_JSON)
      public List<String> example() {
        List<String> l = new ArrayList<>();
        l.add("one"); l.add("two");
        return l; 
      }

  }  
  
}

Now
  1. Create the war file with gradle
  2. Download the Jetty runner jar
  3. Run the war file with the jetty runner (takes about 15 seconds to init usually)
  4. Use curl to test the app

From the command line:

gradle build war
wget http://central.maven.org/maven2/org/eclipse/jetty/jetty-runner/9.3.0.M1/jetty-runner-9.3.0.M1.jar
java -jar jetty-runner-9.3.0.M1.jar --port 8081 build/libs/your-directory-name.war
curl localhost:8081/rest/example && echo
    

The above curl command should print:

["one","two"]

jetty jersey gradle java


Java Servlet: Servering static content

If you want to server static content -- like PNGs, Javascript, etc -- you need to explicitly tell your server this in its web.xml
 
Edit: I've changed this article due to an error and infelicitiy:
 
Add this file somewhere, and, voila, all the files in your res/ directory (in src/main/webapp/res in the gradle directory structure, that is) will be served.

@WebServlet("res/*")
public class ResourcesServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    RequestDispatcher rd = getServletContext().getNamedDispatcher("default");
    HttpServletRequest wrapped = new HttpServletRequestWrapper(req) {
      public String getServletPath() {
        return "/res/";
      }
    };
    rd.forward(wrapped, resp);
  }
}

java java-servlet java-servlet-static-content


Java: Accessing MANIFEST.MF fields in web projects

Let's say you have a MANIFEST.MF file of the form

Manifest-Version: 1.0
SomeVar: SomeValue

In a directory such as src/main/resources/META-INF, in the case of War projects files in Gradle, then when your WAR file is compiled it'll be in WEB-INF/classes/META-INF/.
 
When your application starts you can start a listener that parses this file, e.g. in your web.xml file define a listener that starts a class, which should be the first listener incase any subsequent listeners want to use the parsed variables:

<web-app>
        ...
        <listener>
                <listener-class>com.example.ManifestVars</listener-class>
        </listener>
        ...
 </web-app>

In the ManifestVars class, which must implement ServletContextListener since it's a listener, you can then parse the MANIFEST.MF file, giving the rest of your app static access to the fields therein.

package com.example;

import java.io.InputStream;
import java.util.jar.Attributes;
import java.util.jar.Manifest;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

/** 
 * Reads the war's manifest from /META-INF/MANIFEST.MF on application startup.
 * 
 * Must be included as the first <listener></listener> in the web.xml file.
 */
public class ManifestVars implements ServletContextListener {

	private static Attributes sMainManifestAttributes;
	
	/**
	 * Read the manifest from /META-INF/MANIFEST.MF
	 */
	@Override
	public void contextInitialized(ServletContextEvent sce) {
		try {
			InputStream inputStream = getClass().getClassLoader().getResourceAsStream("META-INF/MANIFEST.MF");
			Manifest manifest = new Manifest(inputStream);
			sMainManifestAttributes = manifest.getMainAttributes();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}	
	}

	@Override
	public void contextDestroyed(ServletContextEvent sce) {
		sMainManifestAttributes = null;
	}

	/**
	 * Generic querying of the manifest.
	 * @return The result, as run through String.trim()
	 */
	public static String getValue(String name) {
		return sMainManifestAttributes.getValue(name).trim();
	}

}


In this class we get an InputStream of META-INF/MANIFEST.MF, and since our WAR file classes's directory is at WEB-INF/classes, then in this context, we're accessing WEB-INF/classes/META-INF/MANIFEST.MF.
 
It's probably a good idea, in this class, to define new static variables for parts of your MANIFEST.MF file, for example a getter and setter for 'SomeVar' in the MANIFEST.MF file.
 
Now in rest of your application, you can simple call somthing like ManifestVars.getSomeVar(), should you have defined that variable

java java-manifest

Page 1 of 9
next