Platform.sh User Documentation

Java

Try for 30 days
Flexible, version-controlled infrastructure provisioning and development-to-production workflows
Activate your trial

Java is a general-purpose programming language, and one of the most popular in the world today. Platform.sh supports Java runtimes that can be used with build management tools such as Gradle, Maven, and Ant.

Supported versions Anchor to this heading

You can select the major version. But the latest compatible minor version is applied automatically and canโ€™t be overridden.

Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches.

OpenJDK versions: Anchor to this heading

Grid and Dedicated Gen 3 Dedicated Gen 2
  • 21
  • 19
  • 18
  • 17
  • 11
  • 8
  • 17
  • 11
  • 8

These versions refer to the headless packages of OpenJDK. To save space and reduce potential vulnerabilities, they don’t contain GUI classes, which can’t be used on the server.

Specify the language Anchor to this heading

To use Java, specify java as your app’s type:

.platform.app.yaml
type: 'java:<VERSION_NUMBER>'

For example:

.platform.app.yaml
type: 'java:21'

Support build automation Anchor to this heading

Platform.sh supports the most common project management tools in the Java ecosystem, including:

Manage Maven versions Anchor to this heading

Java containers come with a version of Maven already installed. You may need to use a specific different version to manage your project. If the version you need differs from the version on your container, you can install the specific version that you need.

Add something like the following to your app configuration:

.platform.app.yaml
variables:
  env:
    MAVEN_VERSION: DESIRED_VERSION_NUMBER

hooks:
  build: |
    curl -sfLO "https://dlcdn.apache.org/maven/maven-3/$MAVEN_VERSION/binaries/apache-maven-$MAVEN_VERSION-bin.tar.gz"
    tar -zxf apache-maven-$MAVEN_VERSION-bin.tar.gz
    export PATH="$PWD/apache-maven-$MAVEN_VERSION/bin:$PATH"
    mvn --version
    mvn clean package    

Other JVM languages Anchor to this heading

Itโ€™s worth remembering that the JVM by its specification doesn’t read Java code, but bytecode. So within the JVM, itโ€™s possible to run several languages. Platform.sh supports several of them, such as Kotlin, Groovy, and Scala, so long as that language works with any build automation that Platform.sh supports.

Article Link
Kotlin and Spring Source
Scala and Spring Source

Accessing services Anchor to this heading

To access various services with Java, see the following examples. The individual service pages have more information on configuring each service.

package sh.platform.languages.sample;

import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
import org.elasticsearch.action.admin.indices.refresh.RefreshResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import sh.platform.config.Config;
import sh.platform.config.Elasticsearch;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;

import static java.util.concurrent.ThreadLocalRandom.current;

public class ElasticsearchSample implements Supplier<String> {

    @Override
    public String get() {
        StringBuilder logger = new StringBuilder();

        // Create a new config object to ease reading the Platform.sh environment variables.
        // You can alternatively use getenv() yourself.
        Config config = new Config();

        Elasticsearch elasticsearch = config.getCredential("elasticsearch", Elasticsearch::new);

        // Create an Elasticsearch client object.
        RestHighLevelClient client = elasticsearch.get();

        try {

            String index = "animals";
            String type = "mammals";
            // Index a few document.
            final List<String> animals = Arrays.asList("dog", "cat", "monkey", "horse");
            for (String animal : animals) {
                Map<String, Object> jsonMap = new HashMap<>();
                jsonMap.put("name", animal);
                jsonMap.put("age", current().nextInt(1, 10));
                jsonMap.put("is_cute", current().nextBoolean());

                IndexRequest indexRequest = new IndexRequest(index, type)
                        .id(animal).source(jsonMap);
                client.index(indexRequest, RequestOptions.DEFAULT);
            }

            RefreshRequest refresh = new RefreshRequest(index);

            // Force just-added items to be indexed
            RefreshResponse refreshResponse = client.indices().refresh(refresh, RequestOptions.DEFAULT);

            // Search for documents.
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            sourceBuilder.query(QueryBuilders.termQuery("name", "dog"));
            SearchRequest searchRequest = new SearchRequest();
            searchRequest.indices(index);
            searchRequest.source(sourceBuilder);

            SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);

            logger.append("<p>");
            for (SearchHit hit : search.getHits()) {
                String id = hit.getId();
                final Map<String, Object> source = hit.getSourceAsMap();
                logger.append(String.format("Result: id: <code>%s</code> source: <code>%s</code>", id, source)).append('\n');
            }
            logger.append("</p>");

            // Delete documents.
            for (String animal : animals) {
                client.delete(new DeleteRequest(index, type, animal), RequestOptions.DEFAULT);
            }
        } catch (IOException exp) {
            throw new RuntimeException("An error when execute Elasticsearch: " + exp.getMessage());
        }
        return logger.toString();
    }
}
package sh.platform.languages.sample;

import org.apache.kafka.clients.consumer.Consumer;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.clients.producer.RecordMetadata;
import sh.platform.config.Config;
import sh.platform.config.Kafka;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;

public class KafkaSample implements Supplier<String> {

    @Override
    public String get() {
        StringBuilder logger = new StringBuilder();

        // Create a new config object to ease reading the Platform.sh environment variables.
        // You can alternatively use getenv() yourself.
        Config config = new Config();

        try {
            // Get the credentials to connect to the Kafka service.
            final Kafka kafka = config.getCredential("kafka", Kafka::new);
            Map<String, Object> configProducer = new HashMap<>();
            configProducer.putIfAbsent(ProducerConfig.CLIENT_ID_CONFIG, "animals");
            final Producer<Long, String> producer = kafka.getProducer(configProducer);

            logger.append("<ul>");
            // Sending data into the stream.
            RecordMetadata metadata = producer.send(new ProducerRecord<>("animals", "lion")).get();
            logger.append("<li>Record sent with to partition <code>").append(metadata.partition())
                    .append("</code> with offset <code>").append(metadata.offset()).append("</code></li>");

            metadata = producer.send(new ProducerRecord<>("animals", "dog")).get();
            logger.append("<li>Record sent with to partition <code>").append(metadata.partition())
                    .append("</code> with offset <code>").append(metadata.offset()).append("</code></li>");

            metadata = producer.send(new ProducerRecord<>("animals", "cat")).get();
            logger.append("<li>Record sent with to partition <code>").append(metadata.partition())
                    .append("</code> with offset <code>").append(metadata.offset()).append("</code></li>");
            logger.append("</ul>");

            // Consumer, read data from the stream.
            final HashMap<String, Object> configConsumer = new HashMap<>();
            configConsumer.put(ConsumerConfig.GROUP_ID_CONFIG, "consumerGroup1");
            configConsumer.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");

            Consumer<Long, String> consumer = kafka.getConsumer(configConsumer, "animals");
            ConsumerRecords<Long, String> consumerRecords = consumer.poll(Duration.ofSeconds(3));

            logger.append("<ul>");
            // Print each record.
            consumerRecords.forEach(record -> {
                logger.append("<li>Record: Key <code>" + record.key());
                logger.append("</code> value <code>" + record.value());
                logger.append("</code> partition <code>" + record.partition());
                logger.append("</code> offset <code>" + record.offset()).append("</code></li>");
            });
            logger.append("</ul>");

            // Commits the offset of record to broker.
            consumer.commitSync();

            return logger.toString();
        } catch (Exception exp) {
            throw new RuntimeException("An error when execute Kafka", exp);
        }
    }
}
package sh.platform.languages.sample;

import net.spy.memcached.MemcachedClient;
import sh.platform.config.Config;

import java.util.function.Supplier;

import sh.platform.config.Memcached;

public class MemcachedSample implements Supplier<String> {

    @Override
    public String get() {
        StringBuilder logger = new StringBuilder();

        // Create a new config object to ease reading the Platform.sh environment variables.
        // You can alternatively use getenv() yourself.
        Config config = new Config();

        // Get the credentials to connect to the Memcached service.
        Memcached memcached = config.getCredential("memcached", Memcached::new);

        final MemcachedClient client = memcached.get();

        String key = "cloud";
        String value = "platformsh";

        // Set a value.
        client.set(key, 0, value);

        // Read it back.
        Object test = client.get(key);

        logger.append("<p>");
        logger.append(String.format("Found value <code>%s</code> for key <code>%s</code>.", test, key));
        logger.append("</p>");

        return logger.toString();
    }
}
package sh.platform.languages.sample;

import com.mongodb.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import sh.platform.config.Config;
import sh.platform.config.MongoDB;

import java.util.function.Supplier;

import static com.mongodb.client.model.Filters.eq;

public class MongoDBSample implements Supplier<String> {

    @Override
    public String get() {
        StringBuilder logger = new StringBuilder();

        // Create a new config object to ease reading the Platform.sh environment variables.
        // You can alternatively use getenv() yourself.
        Config config = new Config();

        // The 'database' relationship is generally the name of primary database of an application.
        // It could be anything, though, as in the case here here where it's called "mongodb".
        MongoDB database = config.getCredential("mongodb", MongoDB::new);
        MongoClient mongoClient = database.get();
        final MongoDatabase mongoDatabase = mongoClient.getDatabase(database.getDatabase());
        MongoCollection<Document> collection = mongoDatabase.getCollection("scientist");
        Document doc = new Document("name", "Ada Lovelace")
                .append("city", "London");

        collection.insertOne(doc);
        Document myDoc = collection.find(eq("_id", doc.get("_id"))).first();
        logger.append("<p>");
        logger.append(myDoc.toJson()).append('\n');
        logger.append(collection.deleteOne(eq("_id", doc.get("_id"))));
        logger.append("</p>");
        return logger.toString();
    }
}
package sh.platform.languages.sample;

import sh.platform.config.Config;
import sh.platform.config.MySQL;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.function.Supplier;

public class MySQLSample implements Supplier<String> {

    @Override
    public String get() {
        StringBuilder logger = new StringBuilder();

        // Create a new config object to ease reading the Platform.sh environment variables.
        // You can alternatively use getenv() yourself.
        Config config = new Config();

        // The 'database' relationship is generally the name of primary SQL database of an application.
        // That's not required, but much of our default automation code assumes it.
        MySQL database = config.getCredential("database", MySQL::new);
        DataSource dataSource = database.get();

        // Connect to the database
        try (Connection connection = dataSource.getConnection()) {

            // Creating a table.
            String sql = "CREATE TABLE IF NOT EXISTS People (" +
                    " id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY," +
                    "name VARCHAR(30) NOT NULL," +
                    "city VARCHAR(30) NOT NULL)";

            final Statement statement = connection.createStatement();
            statement.execute(sql);

            // Insert data.
            sql = "INSERT INTO People (name, city) VALUES" +
                    "('Neil Armstrong', 'Moon')," +
                    "('Buzz Aldrin', 'Glen Ridge')," +
                    "('Sally Ride', 'La Jolla')";

            statement.execute(sql);

            // Show table.
            sql = "SELECT * FROM People";
            final ResultSet resultSet = statement.executeQuery(sql);
            logger.append("<table><thead><tr><th>Name</th><th>City</th></tr></thhead><tbody>");
            while (resultSet.next()) {
                String name = resultSet.getString("name");
                String city = resultSet.getString("city");
                logger.append(String.format("<tr><td>%s</td><td>%s</td></tr>", name, city));
                logger.append('\n');
            }
            logger.append("</tbody></table>");
            statement.execute("DROP TABLE People");
            return logger.toString();
        } catch (SQLException exp) {
            throw new RuntimeException("An error when execute MySQL", exp);
        }
    }
}
package sh.platform.languages.sample;

import sh.platform.config.Config;
import sh.platform.config.MySQL;
import sh.platform.config.PostgreSQL;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.function.Supplier;

public class PostgreSQLSample implements Supplier<String> {

    @Override
    public String get() {
        StringBuilder logger = new StringBuilder();

        // Create a new config object to ease reading the Platform.sh environment variables.
        // You can alternatively use getenv() yourself.
        Config config = new Config();

        // The 'database' relationship is generally the name of primary SQL database of an application.
        // It could be anything, though, as in the case here here where it's called "postgresql".
        PostgreSQL database = config.getCredential("postgresql", PostgreSQL::new);
        DataSource dataSource = database.get();

        // Connect to the database
        try (Connection connection = dataSource.getConnection()) {

            // Creating a table.
            String sql = "CREATE TABLE JAVA_FRAMEWORKS (" +
                    " id SERIAL PRIMARY KEY," +
                    "name VARCHAR(30) NOT NULL)";

            final Statement statement = connection.createStatement();
            statement.execute(sql);

            // Insert data.
            sql = "INSERT INTO JAVA_FRAMEWORKS (name) VALUES" +
                    "('Spring')," +
                    "('Jakarta EE')," +
                    "('Eclipse JNoSQL')";

            statement.execute(sql);

            // Show table.
            sql = "SELECT * FROM JAVA_FRAMEWORKS";
            final ResultSet resultSet = statement.executeQuery(sql);
            logger.append("<ul>");
            while (resultSet.next()) {
                int id = resultSet.getInt("id");
                String name = resultSet.getString("name");
                logger.append(String.format("<li>id <code>%d</code> has a name of <code>%s</code>", id, name));
                logger.append("</li>");
            }
            logger.append("</ul>");
            statement.execute("DROP TABLE JAVA_FRAMEWORKS");
            return logger.toString();
        } catch (SQLException exp) {
            throw new RuntimeException("An error when execute PostgreSQL", exp);
        }
    }
}
package sh.platform.languages.sample;

import sh.platform.config.Config;
import sh.platform.config.RabbitMQ;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import java.util.function.Supplier;

public class RabbitMQSample implements Supplier<String> {

    @Override
    public String get() {
        StringBuilder logger = new StringBuilder();

        // Create a new config object to ease reading the Platform.sh environment variables.
        // You can alternatively use getenv() yourself.
        Config config = new Config();
        try {
            // Get the credentials to connect to the RabbitMQ service.
            final RabbitMQ credential = config.getCredential("rabbitmq", RabbitMQ::new);
            final ConnectionFactory connectionFactory = credential.get();

            // Connect to the RabbitMQ server.
            final Connection connection = connectionFactory.createConnection();
            connection.start();
            final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            Queue queue = session.createQueue("cloud");
            MessageConsumer consumer = session.createConsumer(queue);

            // Sending a message into the queue.
            TextMessage textMessage = session.createTextMessage("Platform.sh");
            textMessage.setJMSReplyTo(queue);
            MessageProducer producer = session.createProducer(queue);
            producer.send(textMessage);

            // Receive the message.
            TextMessage replyMsg = (TextMessage) consumer.receive(100);

            logger.append("<p>");
            logger.append("Message: ").append(replyMsg.getText());
            logger.append("</p>");

            // close connections.
            producer.close();
            consumer.close();
            session.close();
            connection.close();
            return logger.toString();
        } catch (Exception exp) {
            throw new RuntimeException("An error when execute RabbitMQ", exp);
        }
    }
}
package sh.platform.languages.sample;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import sh.platform.config.Config;
import sh.platform.config.Redis;

import java.util.Set;
import java.util.function.Supplier;

public class RedisSample implements Supplier<String> {

    @Override
    public String get() {
        StringBuilder logger = new StringBuilder();

        // Create a new config object to ease reading the Platform.sh environment variables.
        // You can alternatively use getenv() yourself.
        Config config = new Config();

        // The 'database' relationship is generally the name of primary database of an application.
        // It could be anything, though, as in the case here here where it's called "redis".
        Redis database = config.getCredential("redis", Redis::new);
        JedisPool dataSource = database.get();

        // Get a Redis Client
        final Jedis jedis = dataSource.getResource();

        // Set a values
        jedis.sadd("cities", "Salvador");
        jedis.sadd("cities", "London");
        jedis.sadd("cities", "Sรฃo Paulo");

        // Read it back.
        Set<String> cities = jedis.smembers("cities");
        logger.append("<p>");
        logger.append("cities: " + cities);
        logger.append("</p>");
        jedis.del("cities");
        return logger.toString();
    }
}
package sh.platform.languages.sample;

import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.impl.XMLResponseParser;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.UpdateResponse;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;
import sh.platform.config.Config;
import sh.platform.config.Solr;

import java.io.IOException;
import java.util.function.Supplier;

public class SolrSample implements Supplier<String> {

    @Override
    public String get() {

        StringBuilder logger = new StringBuilder();

        // Create a new config object to ease reading the Platform.sh environment variables.
        // You can alternatively use getenv() yourself.
        Config config = new Config();

        Solr solr = config.getCredential("solr", Solr::new);

        try {

            final HttpSolrClient solrClient = solr.get();
            solrClient.setParser(new XMLResponseParser());

            // Add a document
            SolrInputDocument document = new SolrInputDocument();
            final String id = "123456";
            document.addField("id", id);
            document.addField("name", "Ada Lovelace");
            document.addField("city", "London");
            solrClient.add(document);
            final UpdateResponse response = solrClient.commit();
            logger.append("Adding one document. Status (0 is success): ")
                    .append(response.getStatus()).append('\n');

            SolrQuery query = new SolrQuery();
            query.set("q", "city:London");
            QueryResponse queryResponse = solrClient.query(query);

            logger.append("<p>");
            SolrDocumentList results = queryResponse.getResults();
            logger.append(String.format("Selecting documents (1 expected):  %d \n", results.getNumFound()));
            logger.append("</p>");

            // Delete one document
            solrClient.deleteById(id);

            logger.append("<p>");
            logger.append(String.format("Deleting one document. Status (0 is success):  %s \n",
                    solrClient.commit().getStatus()));
            logger.append("</p>");
        } catch (SolrServerException | IOException exp) {
            throw new RuntimeException("An error when execute Solr ", exp);
        }

        return logger.toString();
    }
}

Configuration reader Anchor to this heading

While you can read the environment directly from your app, you might want to use the Java configuration reader library. It decodes service credentials, the correct port, and other information for you.

If your Java framework allows, you can instead overwrite configuration following the twelve-factor app. That removes the need for an additional dependency.

Project templates Anchor to this heading

The following list shows templates available for Java apps.

A template is a starting point for building your project. It should help you get a project ready for production.

Templates in development.

Is this page helpful?