> ## 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.

# Microservices in the cloud, part one

> Microservices are a software architecture, where the systems are a collection of several independent services. Each service has a specific b

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: "2019-08-13", image: "/images/posts/unknown/microservices-in-the-cloud-part-one/microservices-in-the-cloud-part-one.webp" }} />

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

Microservices are a software architecture, where the systems are a collection of several independent services. Each service has a specific business focus and communicates with the others with a language-agnostic protocol, such as REST. The Eclipse MicroProfile initiative optimizes Enterprise Java for the microservices architecture. It’s based on a subset of Jakarta EE APIs. This post will give an overview of some best practices for working with Java microservices on Platform.sh.

## Show me the context

To celebrate the [Oracle GroundBreakers Tour](/posts/unknown/eclipse-microprofiles-gain-agility-release-faster) through Latin America, we'll create a microservices architecture based on the context of the cities, sessions, and speakers where the Oracle GroundBreaker Tour is hosted.

Oracle Groundbreakers Tour - Latin America

* Chile – August 2
* Uruguay – August 5
* Argentina – August 6
* Paraguay – August 8
* Brazil – August 10
* Ecuador – August 13
* Colombia – August 15-16
* Panama – August 19
* Costa Rica – August 21
* Mexico – August 23
* Guatemala – August 26
* Peru – August 28

To manage the conferences into the Latin America trip, we’ll have three microservices:

* Speaker. The speaker service that handles the name, bio, and social media links for each speaker.
* Conference. The conference service that works with lectures, which handles the name, city, and year of the conference trip.
* Session: The session service that handles the name, title, description, and both conference and speaker information.

## Databases

Each database has its proposal, structure, and particular behavior, so we'll use different databases according to each service. Indeed, that’s the advantage of microservices; each service can use any technology that conforms to its requirements without impacting the other services. Each microservice uses an appropriate database for its particular use case:

<img src="https://mintcdn.com/upsun-c9761871/XkTGutbb3_ExMu0d/images/posts/unknown/microservices-in-the-cloud-part-one/PostgreSQ.webp?fit=max&auto=format&n=XkTGutbb3_ExMu0d&q=85&s=5579a4d7e716a7fcf1d2cfaf5d08e8eb" alt="PostgreSQ" width="220" height="227" data-path="images/posts/unknown/microservices-in-the-cloud-part-one/PostgreSQ.webp" />

**PostgreSQL (also known as Postgres).** Free and open-source relational database management system that emphasizes extensibility and technical standards compliance. It’s  designed to handle a range of workloads, from single machines to data warehouses or web services with many concurrent users.

<img src="https://mintcdn.com/upsun-c9761871/XkTGutbb3_ExMu0d/images/posts/unknown/microservices-in-the-cloud-part-one/mongodb.webp?fit=max&auto=format&n=XkTGutbb3_ExMu0d&q=85&s=db24fb5ca7a91db92d8d05bba066c240" alt="MongoDB" width="210" height="60" data-path="images/posts/unknown/microservices-in-the-cloud-part-one/mongodb.webp" />

**MongoDB.** Cross-platform document-oriented database program. Classified as a NoSQL database program, MongoDB uses JSON-like documents with schema.

<img src="https://mintcdn.com/upsun-c9761871/XkTGutbb3_ExMu0d/images/posts/unknown/microservices-in-the-cloud-part-one/elasticsearch.webp?fit=max&auto=format&n=XkTGutbb3_ExMu0d&q=85&s=a13ed338fc79845ca7a9e1391679a76f" alt="elasticsearch" width="688" height="236" data-path="images/posts/unknown/microservices-in-the-cloud-part-one/elasticsearch.webp" />

**Elasticsearch.** A search engine based on the Lucene library. Elasticsearch provides a distributed, multitenant-capable, full-text search engine, with an HTTP web interface and schema-free JSON documents. Elasticsearch is developed in Java.

### Eclipse MicroProfile implementations

The relatively new MicroProfile community dedicates itself to optimizing the Enterprise Java mission for microservice-based architectures. Their goal? A microservices application platform that’s portable across multiple runtimes. Currently, IBM, Red Hat, Tomitribe, Payara, the London Java Community (LJC), and SouJava lead the pack in this group.

<img src="https://mintcdn.com/upsun-c9761871/XkTGutbb3_ExMu0d/images/posts/unknown/microservices-in-the-cloud-part-one/thorntail.webp?fit=max&auto=format&n=XkTGutbb3_ExMu0d&q=85&s=d2d1a2b229866abe33c36bcad58628f2" alt="Thorntail" width="601" height="480" data-path="images/posts/unknown/microservices-in-the-cloud-part-one/thorntail.webp" />

**Thorntail** offers an innovative approach to packaging and running Java EE applications by packaging them with just enough of the server runtime to "java -jar" your application.

<img src="https://mintcdn.com/upsun-c9761871/XkTGutbb3_ExMu0d/images/posts/unknown/microservices-in-the-cloud-part-one/payara.webp?fit=max&auto=format&n=XkTGutbb3_ExMu0d&q=85&s=5c46eb61047261be16538a119052895d" alt="Payara Micro" width="686" height="279" data-path="images/posts/unknown/microservices-in-the-cloud-part-one/payara.webp" />

**Payara Micro** Less than 70MB in size, open source, lightweight middleware platform of choice for containerized Java EE (Jakarta EE)—microservices deployments requires no installation or configuration and no need for code rewrites.

<img src="https://mintcdn.com/upsun-c9761871/XkTGutbb3_ExMu0d/images/posts/unknown/microservices-in-the-cloud-part-one/KumuluzEE.webp?fit=max&auto=format&n=XkTGutbb3_ExMu0d&q=85&s=6b0d4760e8fab9688c961e11a53ce3fc" alt="KumuluzEE" width="280" height="174" data-path="images/posts/unknown/microservices-in-the-cloud-part-one/KumuluzEE.webp" />

**KumuluzEE** develops microservices with Java EE/Jakarta EE technologies and extends them with Node.js, Go and other languages. It migrates existing Java EE applications to microservices and cloud-native architecture.

<img src="https://mintcdn.com/upsun-c9761871/XkTGutbb3_ExMu0d/images/posts/unknown/microservices-in-the-cloud-part-one/apachetomee.webp?fit=max&auto=format&n=XkTGutbb3_ExMu0d&q=85&s=336027a8184279c4668455aa20d5d643" alt="Apache TomEE" width="137" height="98" data-path="images/posts/unknown/microservices-in-the-cloud-part-one/apachetomee.webp" />

**Apache TomEE** is the Eclipse MicroProfile flavor that uses several Apache Project flavors, including Apache Tomcat and Apache OpenWebBeans.

## Join technologies together

<img src="https://mintcdn.com/upsun-c9761871/XkTGutbb3_ExMu0d/images/posts/unknown/microservices-in-the-cloud-part-one/blog-microservices-in-the-cloud-diagram.webp?fit=max&auto=format&n=XkTGutbb3_ExMu0d&q=85&s=110b8afd07b0f8294c4adafb1afc36cc" alt="microservices in the cloud" width="700" height="500" data-path="images/posts/unknown/microservices-in-the-cloud-part-one/blog-microservices-in-the-cloud-diagram.webp" />

Our project has four components:

* KumuluzEE will handle the Session microservice. Users will want to search for session details, such as finding sessions that talk about either Eclipse Microprofile or Jakarta EE. To work with this requirement, the project will use a NoSQL that’s also a powerful search engine (yes, we're talking about Elasticsearch).
* Thorntail will handle the Speaker microservice, the most uncomplicated service that will manage the speaker information. This service will work with PostgreSQL.
* Payara Micro will handle the Conference microservice. This service is strongly related to KumuluzEE and Thorntail. To create a conference, we need both sessions and speakers. MongoDB seems to fit easily with this service because we can use the concept of subdocuments to put a list of presentations and speakers into the Conference entity, instead of making the relationship as in a relational database.
* Apache TomEE is the client browser using HTML 5 as the front end.

## Eclipse MicroProfile and Jakarta to the rescue

The significant benefits of the Eclipse MicroProfile? Well, first, it uses standards on Jakarta EE, such as CDI, JAX-RS, and JSON-P.

To connect to PostgreSQL or any relational database, there’s a [JPA](https://projects.eclipse.org/projects/ee4j.jpa) specification that describes the management of relational data in applications using the Java platform. To communicate to the NoSQL databases, we'll use the [Jakarta NoSQL](https://projects.eclipse.org/projects/ee4j.nosql) specification (not a final version yet, but hopefully will come out soon).

On the client-side, we'll use [Eclipse Krazo](https://projects.eclipse.org/projects/ee4j.krazo) with an [HTML 5](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5) extension, using [Thymeleaf](https://www.thymeleaf.org/) as the template engine. At the moment, the client doesn’t have a database; it will only communicate with the services to organize the values, then show them in the browser. Therefore, it will use [Eclipse MicroProfile Rest Client](https://github.com/eclipse/microprofile-rest-client), which provides a type-safe approach to invoke RESTful services over HTTP.

## Layers, layers, and more layers

The number of layers in an application is always a colossal discussion when we talk about microservices. Layers are essential to split responsibility and write clean code, while maintaining the several patterns built following this approach, like the [MVC](https://www.tutorialspoint.com/mvc_framework/mvc_framework_introduction).

However, a vast number of layers is also hard to keep and to maintain; we need to pay attention to the delay layers. Otherwise, instead of an MVC, we're creating the onion pattern, where you cry each time you go through a layer. There is no magic formula to determine the number of layers you’ll need. Rather, it will be based on the complexity of the business rules, and how the infrastructure code can give us the [cleanest architecture](https://pusher.com/tutorials/clean-architecture-introduction).

In our sample, we have three layers:

* The [entity](https://static.olivergierke.de/lectures/ddd-and-spring/#ddd.building-blocks.entites). The first instance of the business and where the domain lives. These entities, for best practice, should follow a [rich model](https://dzone.com/articles/designing-a-bulletproof-code). We can make [these entities agnostic to a database](https://dzone.com/articles/orms-heroes-or-villains-indoors-the-architecture), but this time, let's keep it simple and use the entity highly coupled with the database.
* The data transfer object (DTO). Just a dump class to allow transfer values between the controller and the entity. Its most prominent goal is to prevent that entity from becoming an [anemic model](https://martinfowler.com/bliki/AnemicDomainModel.html), because some frameworks might require getter and setter methods to serialization, which usually means weak encapsulation.
* The controller. The bridge between the view and the model. It only manipulates the flow among them. With some exceptions, it must be kept as clean as possible–you remember the [high cohesion rule](https://en.wikipedia.org/wiki/Cohesion_\(computer_science\)), right?
  <img src="https://mintcdn.com/upsun-c9761871/XkTGutbb3_ExMu0d/images/posts/unknown/microservices-in-the-cloud-part-one/architecture.webp?fit=max&auto=format&n=XkTGutbb3_ExMu0d&q=85&s=ce67154e814d14220c96d8cb4e4ba91b" alt="UMD" width="740" height="555" data-path="images/posts/unknown/microservices-in-the-cloud-part-one/architecture.webp" />

## Is there a cloud? Or is there just someone’s computer?

Managing databases, code, and integrations is always hard, even on the cloud. Indeed, the server is still there, and someone needs to watch it, run installations and backups, and maintain health in general. And the [twelve-factor APP](https://12factor.net/) requires a strict separation of config from code.

Thankfully, Platform.sh provides a PaaS that manages services, such as databases and message queues, with support for several languages, including Java. Everything is built on the concept of Infrastructure as Code (IaC), managing and provisioning services through [YAML](https://yaml.org/) files.

In [previous posts](/posts/unknown/java-hello-world-at-platform.sh), we mentioned how this is done on Platform.sh primarily with three files:

One to define the services used by the applications ([services.yaml](https://docs.platform.sh/configuration/services.html)).

```yaml theme={null}
elasticsearch:
  type: elasticsearch:6.5
  disk: 512
  size: S
mongodb:
  type: mongodb:3.6
  disk: 512
  size: S
postgresql:
  type: postgresql:11
  disk: 512
  size: S
```

One to define public routes ([routes.yaml](https://docs.platform.sh/configuration/routes.html)).

```yaml theme={null}
"https://{default}/conferences":
  id: conference
  type: upstream
  upstream: "conference:http"

"https://{default}/sessions":
  id: session
  type: upstream
  upstream: "session:http"

"https://{default}/speakers":
  id: speaker
  type: upstream
  upstream: "speaker:http"

"https://{default}/":
  type: upstream
  upstream: "client:http"

"https://www.{default}/":
  type: redirect
  to: "https://{default}/"
```

It's important to stress that the routes are for applications that we want to share publicly. Therefore, if we want the client to only access these microservices, we can remove their access to the conferences, sessions, and speakers from the routes.yaml file.

Platform.sh makes [configuring single applications](https://docs.platform.sh/configuration/app-containers.html) and microservices simple with the `.platform.app.yaml` file. Unlike single applications, each microservice application will have its own directory in the project root and its own `.platform.app.yaml` file associated with that single application. Each application will describe its language and the services it will connect to. Since the client application will coordinate each of the microservices of our application, it will specify those connections using the `relationships` block of its `.platform.app.yaml` file.

```yaml theme={null}
name: client
type: "java:8"

disk: 800

# The hooks executed at various points in the lifecycle of the application.
hooks:
  build: |
    mvn -Dhttp.port=8888 -Dspeaker.service=http://speaker.internal/ -Dconference.service=http://conference.internal/ -Dsession.service=http://session.internal/ -DskipTests clean install tomee:exec

relationships:
  speaker: speaker:http
  conference: conference:http
  session: session:http

web:
  commands:
    start: |
      mv target/ROOT-exec.jar app/ROOT-exec.jar
      java -Xmx1024m -jar  app/ROOT-exec.jar
```

With the requirements set on the application <a href="https://docs.platform.sh/overview/yaml/what-is-yaml.html">YAML file</a>, we can extract the information from the environment. Yes, we're following the twelve factors splitting the code from the config.

```bash theme={null}

echo $PLATFORM_RELATIONSHIPS | base64 --decode | json_pp

{
   "session" : [
   {
      "service" : "session",
      "rel" : "http",
      "scheme" : "http",
      "cluster" : "dvtam6qrvyjwi-master-7rqtwti",
      "port" : 80,
      "ip" : "169.254.159.17",
      "host" : "session.internal",
      "hostname" : "owh4yp4z3tbt3x7fajdexvndpe.session.service._.eu-3.platformsh.site",
      "type" : "java:8"
   }
   ],
   "speaker" : [
   {
      "scheme" : "http",
      "rel" : "http",
      "service" : "speaker",
      "type" : "java:8",
      "hostname" : "4edz7hoi7xx4bnb7vkeopzltc4.speaker.service._.eu-3.platformsh.site",
      "host" : "speaker.internal",
      "port" : 80,
      "cluster" : "dvtam6qrvyjwi-master-7rqtwti",
      "ip" : "169.254.245.54"
   }
   ],
   "conference" : [
   {
      "service" : "conference",
      "rel" : "http",
      "scheme" : "http",
      "port" : 80,
      "cluster" : "dvtam6qrvyjwi-master-7rqtwti",
      "ip" : "169.254.81.85",
      "host" : "conference.internal",
      "hostname" : "3aora24tymelzobulrvgc5rscm.conference.service._.eu-3.platformsh.site",
      "type" : "java:8"
   }
   ]
}
```

The good news about this information is that we don't need to manipulate or extract the data manually, and that’s why we have the configuration reader.

```yaml theme={null}
name: conference

type: "java:8"

disk: 800

relationships:
  mongodb: "mongodb:mongodb"

web:
  commands:
    start: java -jar -Xmx1024m target/conference-microbundle.jar --port $PORT
```

Using the [Java configuration reader](https://github.com/platformsh/config-reader-java), we can read from the environment and return a client such as MongoDB, Datasource, or Elasticsearch. For example, on the conference application.yaml, we require access to MongoDB, from which we can extract and convert this information into a MongoClient instance and make it available for [CDI](https://www.cdi-spec.org/).

```java theme={null}
import com.mongodb.MongoClient;
import jakarta.nosql.document.DocumentCollectionManager;
import org.jnosql.diana.mongodb.document.MongoDBDocumentCollectionManagerFactory;
import org.jnosql.diana.mongodb.document.MongoDBDocumentConfiguration;
import sh.platform.config.Config;
import sh.platform.config.MongoDB;

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

@ApplicationScoped
public class MongoConfig {

 @Produces
 public DocumentCollectionManager getManager() {
     Config config = new Config();
     final MongoDB mongo = config.getCredential("mongodb", MongoDB::new);
     final MongoClient mongoClient = mongo.get();
     MongoDBDocumentConfiguration configuration = new MongoDBDocumentConfiguration();
     MongoDBDocumentCollectionManagerFactory factory = configuration.get(mongoClient);
     return factory.get(mongo.getDatabase());
 }
}
```

Wait?! Where is the code?

To prevent this post from becoming a book, let's split it into a few parts. The first was an overview of the advantages of using microservices—why you should use them and how [Eclipse MicroProfile](https://microprofile.io/) and Platform.sh can help you make it happen. We’ve already talked about [Eclipse MicroProfile, JPA](/posts/unknown/eclipse-microprofiles-gain-agility-release-faster), [Eclipse Krazo, and Eclipse JNoSQL](/posts/unknown/jakarta-ee-generation-iv-a-new-hope). You can review those posts, and, if you don’t care about spoilers, check out the code for this entire series on [GitHub](https://github.com/EventosJEspanol/latin-america-micro-profile).

Otherwise, stay tuned for part two, where we’ll go down to the design of the code and explain it step by step.
