> ## Documentation Index
> Fetch the complete documentation index at: https://developer.upsun.com/llms.txt
> Use this file to discover all available pages before exploring further.

# What’s new with Jakarta NoSQL? (Part II)

> Discover cloud-native with Jakarta EE, best practices, and deploying applications with Jakarta EE NoSQL. Move to the cloud with Platform.sh.

export const PostMeta = ({data = {}}) => {
  const {author, date, image} = data;
  const authors = Array.isArray(author) ? author : author ? [author] : [];
  const resolveAuthor = slug => {
    const entry = AUTHOR_MAP[slug] || ({});
    const name = entry.name || slug;
    const github = entry.github || null;
    const linkedin = entry.linkedin || null;
    const url = github ? `https://github.com/${github}` : linkedin || null;
    const avatarUrl = github ? `https://github.com/${github}.png?size=64` : null;
    return {
      name,
      url,
      avatarUrl
    };
  };
  const formattedDate = date ? new Date(date).toLocaleDateString('en-US', {
    year: 'numeric',
    month: 'long',
    day: 'numeric'
  }) : null;
  if (!image && authors.length === 0 && !formattedDate) return null;
  const AUTHOR_MAP = {
    "aaron-collier": {
      "name": "Aaron Collier"
    },
    "aaron-dudenhofer": {
      "name": "Aaron Dudenhofer"
    },
    "aaron-porter": {
      "name": "Aaron Porter"
    },
    "adriaan-odendaal": {
      "name": "Adriaan Odendaal"
    },
    "ajmal": {
      "name": "Ajmal Siddiqui"
    },
    "akalipetis": {
      "name": "Antonis Kalipetis"
    },
    "alexander-varwijk": {
      "name": "Alexander Varwijk"
    },
    "alicia-bevilacqua": {
      "name": "Alicia Bevilacqua"
    },
    "amelie-deguerry": {
      "name": "Amelie Deguerry"
    },
    "anacidre": {
      "name": "Ana Cidre",
      "linkedin": "https://www.linkedin.com/in/ana-cidre"
    },
    "andoni": {
      "name": "Andoni Auzmendi"
    },
    "andrei-taranu": {
      "name": "Andrei (Alex) Taranu",
      "linkedin": "https://www.linkedin.com/in/andrei-alex-taranu/"
    },
    "andrew-baxter": {
      "name": "Andrew Baxter"
    },
    "andrew-melck": {
      "name": "Andrew Melck"
    },
    "antoine-crochet-damais": {
      "name": "Antoine Crochet Damais"
    },
    "augustin-delaporte": {
      "name": "Augustin Delaporte",
      "linkedin": "https://www.linkedin.com/in/augustindelaporte/"
    },
    "branislav-bujisic": {
      "name": "Branislav Bujisic"
    },
    "carl-smith": {
      "name": "Carl Smith"
    },
    "caroline-leroy": {
      "name": "Caroline Leroy"
    },
    "cati-mayer": {
      "name": "Cati Mayer"
    },
    "catplat": {
      "name": "C Trinkwon"
    },
    "ceelolulu": {
      "name": "Celeste van der Watt"
    },
    "chadwcarlson": {
      "name": "Chad Carlson",
      "github": "chadwcarlson",
      "linkedin": "https://www.linkedin.com/in/chadwcarlson"
    },
    "chris-ward": {
      "name": "Chris Ward"
    },
    "chris-yates": {
      "name": "Chris Yates"
    },
    "christian-sieber": {
      "name": "Christian Sieber"
    },
    "christopher-lockheardt": {
      "name": "Christopher Lockheardt"
    },
    "christopher-skene": {
      "name": "Christopher Skene"
    },
    "chuck-morgan": {
      "name": "Chuck Morgan"
    },
    "corey-dockendorf": {
      "name": "Corey Dockendorf"
    },
    "crell": {
      "name": "Crell"
    },
    "damz": {
      "name": "Damz"
    },
    "dan-morrison": {
      "name": "Dan Morrison"
    },
    "davidbonachera": {
      "name": "David Bonachera",
      "github": "davidbonachera",
      "linkedin": "https://www.linkedin.com/in/davidbonachera"
    },
    "dereliahmet1": {
      "name": "Ahmet Faruk Dereli"
    },
    "devicezero": {
      "name": "Jonas Kröger",
      "github": "devicezero",
      "linkedin": "https://www.linkedin.com/in/jonaskroeger/"
    },
    "doug-goldberg": {
      "name": "Doug Goldberg"
    },
    "duncan-naves": {
      "name": "Duncan Naves",
      "github": "duncannaves",
      "linkedin": "https://www.linkedin.com/in/duncan-naves-a94423aa"
    },
    "erika-bustamante": {
      "name": "Erika Bustamante"
    },
    "fabpot": {
      "name": "Fabien Potencier"
    },
    "flovntp": {
      "name": "Florent Huck",
      "github": "flovntp",
      "linkedin": "https://www.linkedin.com/in/florenthuck"
    },
    "fred-plais": {
      "name": "Fred Plais"
    },
    "gauthier-garnier": {
      "name": "Gauthier Garnier"
    },
    "gilzow": {
      "name": "Paul Gilzow"
    },
    "gmoigneu": {
      "name": "Guillaume Moigneu",
      "github": "gmoigneu",
      "linkedin": "https://www.linkedin.com/in/guillaumemoigneu/"
    },
    "gregqualls": {
      "name": "Greg Qualls"
    },
    "guguss": {
      "name": "Augustin Delaporte"
    },
    "haylee-millar": {
      "name": "Haylee Millar"
    },
    "ivana-kotur": {
      "name": "Ivana Kotur"
    },
    "jackrabbithanna": {
      "name": "Mark Hanna"
    },
    "jared-wright": {
      "name": "Jared Wright",
      "github": "jww-sh",
      "linkedin": "https://www.linkedin.com/in/jaredwaynewright"
    },
    "jessica-orozco": {
      "name": "Jessica Orozco"
    },
    "joey-stanford": {
      "name": "Joey Stanford"
    },
    "john-grubb": {
      "name": "John Grubb"
    },
    "jonas-kruger": {
      "name": "Jonas Kruger"
    },
    "kathryn-frazer": {
      "name": "Kathryn Frazer"
    },
    "kemiojo": {
      "name": "Kemi Elizabeth Ojogbede"
    },
    "kieronsambrook-smith": {
      "name": "Kieronsambrook Smith"
    },
    "laurent-arnoud": {
      "name": "Laurent Arnoud"
    },
    "letoya-boyne": {
      "name": "Letoya Boyne"
    },
    "lolautruche": {
      "name": "Jérôme Vieilledent"
    },
    "lyly-lepinay": {
      "name": "Lyly Lepinay"
    },
    "manauwar-alam": {
      "name": "Manauwar Alam"
    },
    "marc-antoine-porri": {
      "name": "Marc Antoine Porri"
    },
    "maria-antinkaapo": {
      "name": "Maria Antinkaapo"
    },
    "maria-de-anton": {
      "name": "Maria De Anton"
    },
    "mark-dorison": {
      "name": "Mark Dorison"
    },
    "markus-hausammann": {
      "name": "Markus Hausammann"
    },
    "mary-thomas": {
      "name": "Mary Thomas"
    },
    "mathias-bolt-lesniak": {
      "name": "Mathias Bolt Lesniak"
    },
    "mathieu-strauch": {
      "name": "Mathieu Strauch"
    },
    "matthias-van-woensel": {
      "name": "Matthias Van Woensel",
      "linkedin": "https://www.linkedin.com/in/matthias-van-woensel-267a069"
    },
    "michael-sharp": {
      "name": "Michael Sharp"
    },
    "mupsi": {
      "name": "Marine Gandy"
    },
    "natalie-harper": {
      "name": "Natalie Harper"
    },
    "ngommenginger": {
      "name": "Nicolas Gommenginger",
      "linkedin": "https://www.linkedin.com/in/nicolas-gommenginger"
    },
    "nicholas-bennison": {
      "name": "Nicholas Bennison"
    },
    "nicholas-vahalik": {
      "name": "Nicholas Vahalik"
    },
    "nick-hardiman": {
      "name": "Nick Hardiman"
    },
    "nickanderegg": {
      "name": "Nickanderegg"
    },
    "nicolas-grekas": {
      "name": "Nicolas Grekas",
      "github": "nicolas-grekas",
      "linkedin": "https://www.linkedin.com/in/nicolasgrekas/"
    },
    "niti-malwade": {
      "name": "Niti Malwade"
    },
    "opensocialteam": {
      "name": "Opensocialteam"
    },
    "ori-pekelman": {
      "name": "Ori Pekelman"
    },
    "otavio-santana": {
      "name": "Otavio Santana"
    },
    "palwandi": {
      "name": "Pawan Alwandi",
      "github": "pawpy",
      "linkedin": "https://www.linkedin.com/in/pawanalwandi"
    },
    "patrick-boest": {
      "name": "Patrick Boest"
    },
    "patrick-dawkins": {
      "name": "Patrick Dawkins",
      "github": "pjcdawkins",
      "linkedin": "https://www.linkedin.com/in/patrickdawkins"
    },
    "patrick-klima": {
      "name": "Patrick Klima"
    },
    "pjcdawkins": {
      "name": "Pjcdawkins"
    },
    "prineet-kaurbhurji": {
      "name": "Prineet Kaurbhurji"
    },
    "quentin-sinig": {
      "name": "Quentin Sinig"
    },
    "ralt": {
      "name": "Florian Margaine",
      "github": "ralt",
      "linkedin": "https://www.linkedin.com/in/florian-margaine-43971136"
    },
    "ramanathanramakrishnamurthy": {
      "name": "Ramanathanramakrishnamurthy"
    },
    "remi-lejeune": {
      "name": "Rémi Lejeune"
    },
    "ribel": {
      "name": "Taras Kruts"
    },
    "robert-douglass": {
      "name": "Robert Douglass"
    },
    "rudy-weber": {
      "name": "Rudy Weber"
    },
    "ryan-hicks": {
      "name": "Ryan Hicks"
    },
    "sabri-helal": {
      "name": "Sabri Helal"
    },
    "savannah-bergeron": {
      "name": "Savannah Bergeron"
    },
    "shannon-vettes": {
      "name": "Shannon Vettes"
    },
    "shawn-ogasawara": {
      "name": "Shawn Ogasawara",
      "linkedin": "https://www.linkedin.com/in/shawn-ogasawara-83a9a0/"
    },
    "shawna-spoor": {
      "name": "Shawna Spoor"
    },
    "shedrack-akintayo": {
      "name": "Shedrack Akintayo"
    },
    "simon-ruggier": {
      "name": "Simon Ruggier"
    },
    "sophie-van-der-kindere": {
      "name": "Sophie Van Der Kindere"
    },
    "stefanos-thampis": {
      "name": "Stefanos Thampis"
    },
    "stephen-weinberg": {
      "name": "Stephen Weinberg"
    },
    "sukhman-virk": {
      "name": "Sukhman Virk"
    },
    "sumaira-nazir": {
      "name": "Sumaira Nazir"
    },
    "sumer": {
      "name": "Sümer Cip"
    },
    "syed-raza": {
      "name": "Syed Raza"
    },
    "tamara-bacchia": {
      "name": "Tamara Bacchia"
    },
    "tara-arnold": {
      "name": "Tara Arnold"
    },
    "theosakamg": {
      "name": "Mickael Gaillard",
      "github": "theosakamg"
    },
    "thomasdiluccio": {
      "name": "Thomas di Luccio"
    },
    "tim-anderson": {
      "name": "Tim Anderson"
    },
    "tom-helmer-hansen": {
      "name": "Tom Helmer Hansen"
    },
    "tylermills": {
      "name": "Tyler Mills"
    },
    "upsun": {
      "name": "Upsun"
    },
    "veronika-tolkachova": {
      "name": "Veronika Tolkachova",
      "linkedin": "https://www.linkedin.com/in/veronika-tolkachova-169167a2"
    },
    "vince-parker": {
      "name": "Vince Parker"
    },
    "vinnie-russo": {
      "name": "Vincenzo Russo"
    },
    "vrobert78": {
      "name": "Vincent Robert",
      "github": "vrobert78",
      "linkedin": "https://www.linkedin.com/in/vincent-robert-498a883"
    },
    "yuriy-babenko": {
      "name": "Yuriy Babenko"
    },
    "yuriy-gerasimov": {
      "name": "Yuriy Gerasimov"
    }
  };
  return <div className="post-meta">
      {(authors.length > 0 || formattedDate) && <div className="post-meta-info">
          {authors.length > 0 && <div className="post-meta-authors">
              {authors.map(slug => {
    const {name, url, avatarUrl} = resolveAuthor(slug);
    const inner = <>
                    {avatarUrl && <img src={avatarUrl} alt={name} className="post-meta-avatar" />}
                    <span className="post-meta-author-name">{name}</span>
                  </>;
    return url ? <a key={slug} href={url} target="_blank" rel="noopener noreferrer" className="post-meta-author">
                    {inner}
                  </a> : <span key={slug} className="post-meta-author">{inner}</span>;
  })}
            </div>}
          {authors.length > 0 && formattedDate && <span className="post-meta-separator" aria-hidden="true">·</span>}
          {formattedDate && <span className="post-meta-date">{formattedDate}</span>}
        </div>}
      {image && <img src={image} alt="" className="post-meta-image" aria-hidden="true" />}
    </div>;
};

<PostMeta data={{ author: ["otavio-santana"], date: "2020-01-08", image: "/images/posts/unknown/what-is-new-with-jakarta-nosql-part-II/what-is-new-with-jakarta-nosql-part-II.webp" }} />

<Tip>
  This post was originally published on the Platform.sh blog and reflects information from the time of publication.
</Tip>

## Moving to cloud-native

Cloud computing has brought many methodologies and techniques that have revolutionized both the business and technical worlds. Among the terms that came up was cloud-native. To meet and cover these expectations in the Java universe, Jakarta EE emerged. The purpose of this post is to talk about the concept of cloud-native and to run an application with this concept using the latest milestone version of Jakarta EE NoSQL.

## What’s cloud-native?

Like any new concept, there are several concepts with the same name; if you read books or articles about cloud-native, you may not find consensus about it. For example:

<div class="emphasize">
  <div class="inner">
    <p>
      Cloud-native is an approach to building and running applications that exploits the advantages of the cloud computing model.
      <cite><a href="https://pivotal.io/de/cloud-native" title="Pivotal">Pivotal</a></cite>
    </p>
  </div>

  <div class="accent" />
</div>

<div class="emphasize">
  <div class="inner">
    <p>
      Cloud-native is a different way of thinking and reasoning about software systems. It embodies the following concepts: powered by disposable infrastructure, composed of bounded, scales globally, embraces disposable architecture.
      <cite><a href="https://www.amazon.com/Architecting-Cloud-Native-Applications-high-performing-ebook/dp/B07QTJ8WW8/ref=sr_1_4?keywords=cloud+native+applications&qid=1575059989&sr=8-4" title="Architecting Cloud Native Applications: Design high-performing and cost-effective applications for the cloud">Architecting Cloud Native Applications: Design high-performing and cost-effective applications for the cloud</a></cite>
    </p>
  </div>

  <div class="accent" />
</div>

<div class="emphasize">
  <div class="inner">
    <p>
      In general usage, “cloud-native” is an approach to building and running applications that exploits the advantages of the cloud-computing delivery model. “Cloud-native” is about how applications are created and deployed, not where.
      <cite><a href="https://www.infoworld.com/article/3281046/what-is-cloud-native-the-modern-way-to-develop-software.html" title="Infoworld">Infoworld</a></cite>
    </p>
  </div>

  <div class="accent" />
</div>

In a mutual consensus around the definitions from several articles, we can say that [cloud-native](https://thenewstack.io/10-key-attributes-of-cloud-native-applications/) is a term used to describe container-based environments. So cloud-native isn't related to specific programming languages or frameworks or even to a cloud provider company, but to [containers](https://www.ibm.com/cloud/learn/containers).

## What are cloud-native best practices?

When we start to learn a new concept, we usually run to read about best practices to avoid mistakes and any [code smell](https://en.wikipedia.org/wiki/Code_smell). With Object-Oriented Programming ([OOP](https://en.wikipedia.org/wiki/Object-oriented_programming)), we have the [design patterns from the gang of four](https://www.amazon.com/Design-Patterns-Object-Oriented-Addison-Wesley-Professional-ebook/dp/B000SEIBB8/ref=sr_1_1?keywords=Design+Patterns\&qid=1575065213\&s=digital-text\&sr=1-1), in Java we have [Effective Java](https://www.amazon.com/Effective-Java-Joshua-Bloch-ebook/dp/B078H61SCH/ref=sr_1_1?keywords=effective+java\&qid=1575065238\&s=digital-text\&sr=1-1), and when talking about architecture, we have both [Clean Code](https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship-ebook/dp/B001GSTOAM/ref=sr_1_1?keywords=clean+code\&qid=1575065245\&s=digital-text\&sr=1-1) and [Clean Architecture](https://www.amazon.com/Clean-Architecture-Craftsmans-Software-Structure-ebook/dp/B075LRM681/ref=sr_1_1?crid=3QV4OX59QPYOQ\&keywords=clean+architecture\&qid=1575065251\&s=digital-text\&sprefix=clean+arq%2Cdigital-text%2C260\&sr=1-1). So the question is: what are the best practices for cloud-native?

As far as we know, there aren't best practices related specifically to cloud-native. But since the cloud is close to Agile methodology, there are several practices we can leverage to have a healthy, pain-free application:

* [Manifesto for Agile Software Development](https://agilemanifesto.org/)
* [Continuous integration](https://www.atlassian.com/continuous-delivery/continuous-integration)
* [Continuous delivery](https://continuousdelivery.com/)
* [Domain-Driven Design](https://www.infoq.com/minibooks/domain-driven-design-quickly/)

The most well-known practices related to any application that includes cloud computing are inspired by Martin Fowler’s [Patterns of Enterprise Application Architecture and Refactoring](https://books.google.com.br/books/about/Patterns_of_enterprise_application_archi.html?id=FyWZt5DdvFkC\&redir_esc=y).

## [The Twelve-Factor App](https://12factor.net/)

1. [Codebase](https://12factor.net/codebase): One codebase tracked in revision control, many deploys
2. [Dependencies](https://12factor.net/dependencies): Explicitly declare and isolate dependencies
3. [Config](https://12factor.net/config): Store config in the environment
4. [Backing services](https://12factor.net/backing-services): Treat backing services as attached resources
5. [Build, release, run](https://12factor.net/build-release-run): Strictly separate build and run stages
6. [Processes](https://12factor.net/processes): Execute the app as one or more stateless processes
7. [Port binding](https://12factor.net/port-binding): Export services via port binding
8. [Concurrency](https://12factor.net/concurrency): Scale out via the process model
9. [Disposability](https://12factor.net/disposability): Maximize robustness with fast startup and graceful shutdown
10. [Dev/prod parity](https://12factor.net/dev-prod-parity): Keep development, staging, and production as similar as possible
11. [Logs](https://12factor.net/logs): Treat logs as event streams
12. [Admin processes](https://12factor.net/admin-processes): Run admin/management tasks as one-off processes

In summary, there aren't specific best practices for cloud-native yet, but there are patterns from Agile, microservices, and the twelve-factor app that are useful to follow.

## Back to the code

In the introduction we explained in detail what cloud-native means, now let's return to our application and convert it as a cloud-native application. In the first post, we explained the model, the entity, and how Jakarta NoSQL works. So we'll take it from here and use the easiest way to handle queries with NoSQL and MongoDB with a repository.

```java theme={null}

import jakarta.nosql.mapping.Column;
import jakarta.nosql.mapping.Entity;
import jakarta.nosql.mapping.Id;

import javax.json.bind.annotation.JsonbVisibility;
import java.io.Serializable;
import java.util.Objects;
import java.util.Set;

@Entity
@JsonbVisibility(FieldPropertyVisibilityStrategy.class)
public class Hero implements Serializable {

 @Id
 private String name;

 @Column
 private Integer age;

 @Column
 private Set<String> powers;

}

import jakarta.nosql.mapping.Page;
import jakarta.nosql.mapping.Pagination;
import jakarta.nosql.mapping.Repository;

import java.util.stream.Stream;

public interface HeroRepository extends Repository<Hero, String> {

 Stream<Hero> findAll();

 Page<Hero> findAll(Pagination pagination);

 Stream<Hero> findByPowersIn(String powers);

 Stream<Hero> findByAgeGreaterThan(Integer age);

 Stream<Hero> findByAgeLessThan(Integer age);
}

```

To make these services available, we'll create a rest application with JAX-RS as a resource class.

```java theme={null}

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List;
import java.util.function.Supplier;

import static java.util.stream.Collectors.toList;

@ApplicationScoped
@Path("heroes")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class HeroResource {

 private static final Supplier<WebApplicationException> NOT_FOUND =
         () -> new WebApplicationException(Response.Status.NOT_FOUND);

 @Inject
 private HeroRepository repository;

 @GET
 public List<Hero> findAll() {
     return repository.findAll()
             .collect(toList());
 }

 @GET
 @Path("/{id}")
 public Hero findById(@PathParam("id") String id) {
     return repository.findById(id).orElseThrow(NOT_FOUND);
 }

 @GET
 @Path("seniors/{age}")
 public List<Hero> findByOlder(@PathParam("age") Integer age) {
     return repository.findByAgeGreaterThan(age)
             .collect(toList());
 }

 @GET
 @Path("youngs/{age}")
 public List<Hero> findByYounger(@PathParam("age") Integer age) {
     return repository.findByAgeLessThan(age)
             .collect(toList());
 }

 @POST
 public void save(Hero hero) {
     repository.save(hero);
 }

 @PUT
 @Path("/{id}")
 public void update(@PathParam("id") String id, Hero hero) {
     repository.save(hero);
 }

 @Path("/{id}")
 @DELETE
 public void delete(@PathParam("id") String name) {
     repository.deleteById(name);
 }
}

```

The application is ready; the last step we'll create is the configuration class that allows the connection with MongoDB. This is simple, we'll use [Eclipse MicroProfile Configuration](https://microprofile.io/project/eclipse/microprofile-config) that has tight integration capabilities with Eclipse JNoSQL, the reference implementation of Jakarta NoSQL. The Eclipse MicroProfile Config is a solution to externalize configuration from Java applications and makes the [third factor](https://12factor.net/config) easy to follow.

```java theme={null}
import jakarta.nosql.document.DocumentCollectionManager;
import org.eclipse.microprofile.config.inject.ConfigProperty;

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Disposes;
import javax.enterprise.inject.Produces;
import javax.inject.Inject;

@ApplicationScoped
class DocumentManagerProducer {

 @Inject
 @ConfigProperty(name = "document")
 private DocumentCollectionManager manager;

 @Produces
 public DocumentCollectionManager getManager() {
     return manager;
 }

 public void destroy(@Disposes DocumentCollectionManager manager) {
     manager.close();
 }
}

```

The current configuration of an application can be accessed via ConfigProvider#getConfig().

A Config consists of the information collected from the registered org.eclipse.microprofile.config.spi.ConfigSource s. These ConfigSource s get sorted according to their ordinal. That way we can overwrite the configuration with lower importance from outside.

By default there are 3 ConfigSources:

* System.getProperties() (ordinal=400)
* System.getenv() (ordinal=300)
* all META-INF/microprofile-config.properties files on the ClassPath. (default ordinal=100, separately configurable via a config\_ordinal property inside each file)

Therefore, the default values can be specified in the above files packaged with the application and the value can be overwritten later for each deployment. A higher ordinal number takes precedence over a lower number.

That implies we can have the configuration for the local environment as a file, one to test also as a file, and finally we can override all this information when we move it to the cloud.

```
document=document
document.database=conferences
document.settings.jakarta.nosql.host=localhost:27017
document.provider=org.eclipse.jnosql.diana.mongodb.document.MongoDBDocumentConfiguration
```

We now have a local configuration, so let's move our application with Jakarta EE based on the cloud-native approach. To make it really easy, we'll use a Platform-as-a-Service (PaaS) because you can move your application [container-based](https://docs.platform.sh/overview/structure.html) style in cloud through [infrastructure as code](https://www.amazon.com.br/Infrastructure-Code-Managing-Servers-English-ebook/dp/B01GUG9ZNU) (IaC).

[Infrastructure as code](https://www.thoughtworks.com/insights/blog/infrastructure-code-reason-smile), or programmable infrastructure, means writing code, which can be done using a high-level language or any descriptive language to manage configurations and automate the provisioning of the infrastructure in addition to deployments.

## Platform.sh structure

The Java application is ready to go! The next step is to set the Platform.sh files required to manage and [deploy the application](https://devcenter.upsun.com/posts/best-practices-in-deploying-web-apps-updated-for-2020/). In our [first Java post](/posts/unknown/java-hello-world-at-platform.sh), we took a deep dive into each of these three files in detail:

* One Router (.platform/routes.yaml). Platform.sh allows you to define the [routes](https://docs.platform.sh/configuration/routes.html).
* Zero or more service containers (.platform/services.yaml). Platform.sh allows you to completely define and configure the topology and services you want to use on your [project](https://docs.platform.sh/configuration/services.html).
* One or more application containers (.platform.app.yaml). You control your application and the way it will be built and deployed on Platform.sh via a [single configuration file](https://docs.platform.sh/configuration/app-containers.html).

The file that will change on this post is the [service file](https://docs.platform.sh/configuration/services.html), allowing you to define a database, search engine, cache, and so on. For this project, we'll set [MongoDB](https://docs.platform.sh/configuration/services/mongodb.html) instead of [MySQL](https://docs.platform.sh/configuration/services/mysql.html).

```yaml theme={null}
mongodb:
  type: mongodb:3.6
  disk: 1024
```

To read the environment configuration, Platform.sh supports the [configuration-reader](https://github.com/platformsh?utf8=%E2%9C%93\&q=config-reader\&type=\&language=) that allows easy integration. Platform.sh also supports an array frameworks and languages, including Java. In this post, we'll override the [MongoDB](https://docs.platform.sh/configuration/services/mongodb.html) configuration with the Java properties that will add transparency to the application—thanks to the Eclipse MicroProfile Configuration. With these files ready and pushed to the master, Platform.sh will [create a set of containers within a cluster](https://docs.platform.sh/overview/structure.html).

```yaml theme={null}
# This file describes an application. You can have multiple applications
# in the same project.
#
# See https://docs.platform.sh/user_guide/reference/platform-app-yaml.html

# The name of this app. Must be unique within a project.
name: app

# The runtime the application uses.
type: "java:8"

disk: 800

# The hooks executed at various points in the lifecycle of the application.
hooks:
  build: |
  wget https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64
  mv jq-linux64 jq
  chmod +x jq
  mvn -U -DskipTests clean package payara-micro:bundle

# The relationships of the application with services or other applications.
#
# The left-hand side is the name of the relationship as it will be exposed
# to the application in the PLATFORM_RELATIONSHIPS variable. The right-hand
# side is in the form `<service name>:<endpoint name>`.
relationships:
  mongodb: 'mongodb:mongodb'

# The configuration of app when it is exposed to the web.
web:
  commands:
    start: |
      export MONGO_PORT=`echo $PLATFORM_RELATIONSHIPS|base64 -d|json_pp|./jq -r ".mongodb[0].port"`
      export MONGO_HOST=`echo $PLATFORM_RELATIONSHIPS|base64 -d|json_pp|./jq -r ".mongodb[0].host"`
      export MONGO_ADDRESS="${MONGO_HOST}:${MONGO_PORT}"
      export MONGO_PASSWORD=`echo $PLATFORM_RELATIONSHIPS|base64 -d|json_pp|./jq -r ".mongodb[0].password"`
      export MONGO_USER=`echo $PLATFORM_RELATIONSHIPS|base64 -d|json_pp|./jq -r ".mongodb[0].username"`
      export MONGO_DATABASE=`echo $PLATFORM_RELATIONSHIPS|base64 -d|json_pp|./jq -r ".mongodb[0].path"`
      java -jar -Xmx1024m -Ddocument.settings.jakarta.nosql.host=$MONGO_ADDRESS \
      -Ddocument.database=$MONGO_DATABASE -Ddocument.settings.jakarta.nosql.user=$MONGO_USER \
      -Ddocument.settings.jakarta.nosql.password=$MONGO_PASSWORD \
      -Ddocument.settings.mongodb.authentication.source=$MONGO_DATABASE \
      target/heroes-microbundle.jar --port $PORT
```

The application is now ready, so it’s time to move it to the cloud with Platform.sh using the following [steps](https://docs.platform.sh/gettingstarted/first-project.html):

* Create a new [free trial account](https://auth.api.platform.sh/register?trial_type=general).
* Sign up with a new username and password, or login using a current GitHub, Bitbucket, or Google account. If you use a third-party login, you’ll be able to set a password for your Platform.sh account later.
* Select the region of the world where your site should live.
* Select the blank template.

After this wizard, Platform.sh will provision the whole infrastructure to you, and it will offer your project a remote [Git repository](https://docs.platform.sh/development/private-repository.html). The Platform.sh Git-driven infrastructure means it will automatically manage everything your application needs to push it to the master remote repository. After you set up your [SSH keys](https://docs.platform.sh/development/ssh.html#using-ssh-keys), you only need to write your code—including a few <a href="https://docs.platform.sh/overview/yaml/what-is-yaml.html">YAML files</a> that specify your desired infrastructure—then commit it to Git, and push.

```
git remote add platform <platform.sh@gitrepository>
git commit -m "Initial project"
git push -u platform master
```

In this post, we talked about the [principles and best practices around cloud-native](https://github.com/platformsh/java-quick-start/tree/master/jakarta/mongodb-nosql-m1), which is still an area that needs improvement when we’re talking about a new software development technique. Cloud facilitates software development, and we can see an application running quite simply through Platform.sh and integrated with Jakarta EE. All to say, it’s a great time (happy new year!) to bring your project to a mature cloud PaaS like Platform.sh.
