Getting Started
JPA beans are some of the most important code in any Elide project. Your beans are the view of your data model that youwish to expose. In this example we will be modeling a software artifact repository since most developers have ahigh-level familiarity with artifact repositories such as Maven, Artifactory, npm, and the like. If you are interested, is tagged for each step so you can follow along.
The first bean we’ll need is the bean, for brevity we will omit package names and import statements. Thiswill represent the <groupId>
in Maven’s dependency coordinates.
So now we have a bean, but without an API it is not do very useful. Before we add the API component of the we need tocreate the schema in the database that our beans will use. Download and run the demo setup script; thisdemo uses MySQL, feel free to modify the setup script if you are using a different database provider.
You may notice that there are more tables that just ArtifactGroup
, and that the ArtifactGroup
table has more fieldsthat our bean. Not only will our bean work just fine, we expect that beans will normally expose only a subset of thefields present in the database. Elide is an ideal tool for building micro-services, each service in your system canexpose only the slice of the database that it requires.
Bringing life to our API is trivially easy. We need two new classes: Main and Settings.
public class Main {
public static void main(String[] args) throws Exception {
ElideStandalone app = new ElideStandalone(new Settings());
app.start();
}
}
public class Settings implements ElideStandaloneSettings {
@Override
public String getModelPackageName() {
}
}
With these new classes you have two options for running your project, you can either run the Main
class using yourfavorite IDE, or we can add the following snippet to our gradle build script and run our project with ./gradlew run
plugins {
...
id 'application'
}
mainClassName = 'com.example.repository.Main' // the actual path to your Main class should go here
With the Main
and Settings
classes we can now run our API. If you navigate to in your browser you can see some of the sample data that the bootstrapscript added for us. Exciting!
{"data":[{"type":"artifactGroup","id":"com.example.repository"},{"type":"artifactGroup","id":"com.yahoo.elide"}]}
Adding More Data
Now that we have an API that returns data, let’s add some more interesting behavior. Let’s update ArtifactGroup
, andadd the ArtifactProduct
and classes–which will be the <artifactId>
and <version>
tagsrespectively.
@Include
@Entity
public class ArtifactProduct {
@Id
public String name = "";
public String commonName = "";
public String description = "";
@ManyToOne
public ArtifactGroup group = null;
@OneToMany(mappedBy = "artifact")
public List<ArtifactVersion> versions = new ArrayList<>();
}
@Include
@Entity
public class ArtifactVersion {
public String name = "";
public Date createdAt = new Date();
@ManyToOne
public ArtifactProduct artifact;
}
We add the missing fields to ArtifactGroup
since we anticipate user will want to add some informative metadata to helpusers find the products and artifacts they are interested in. If we restart the API and request we’llsee the other metadata we just added.
{"data":[{"type":"artifactGroup","id":"com.example.repository","attributes":{"commonName":"Example Repository","description":"The code for this project"},"relationships":{"products":{"data":[]}}},{"type":"artifactGroup","id":"com.yahoo.elide","attributes":{"commonName":"Elide","description":"The magical library powering this project"},"relationships":{"products":{"data":[{"type":"artifactProduct","id":"elide-core"},{"type":"artifactProduct","id":"elide-standalone"},{"type":"artifactProduct","id":"elide-datastore-hibernate5"}]}}}]}
So now we have an API that can display information for a full <group>:<product>:<version>
set. We can fetch data fromour API in the following ways:
List groups: /artifactGroup/
Show a group: /artifactGroup/<group id>
List a group's products: /artifactGroup/<group id>/products/
Show a product: /artifactGroup/<group id>/products/<product id>
List a product's versions: /artifactGroup/<group id>/products/<product id>/versions/
Show a version: /artifactGroup/<group id>/products/<product id>/versions/<version id>
Now, instead of making a call to http://localhost:8080/api/v1/artifactGroup
to fetch our data, we make a request to. Our API returns the same data as before, mostly. The types of our objects nowreflect our preferences from the
Include
annotations.
{"data":[{"type":"group","id":"com.example.repository",...},{"type":"group","id":"com.yahoo.elide",..."relationships":{"products":{"data":[{"type":"product","id":"elide-core"},...]}}}]}
So far we have defined our views on the database and exposed those views over HTTP. This is great progress, but so farwe have only read data from the database.
Fortunately for us adding data is just as easy as reading data. For now let’s use cURL to put data in the database.
curl -X POST http://localhost:8080/api/v1/group/com.example.repository/products \
-H"Content-Type: application/vnd.api+json" -H"Accept: application/vnd.api+json" \
-d '{"data": {"type": "product", "id": "elide-demo"}}'
When you run that cURL call you should see a bunch of json returned, that is our newly inserted object! If we queryhttp://localhost:8080/api/v1/group/com.example.repository/products/
{"data":[{"type":"product","id":"elide-demo","attributes":{"commonName":"","description":""},"relationships":{"group":{"data":{"type":"group","id":"com.example.repository"}},"versions":{"data":[]}}}]}
Modifying Data
Notice that, when we created it, we did not set any of the attributes of our new product record. Unfortunately for ourusers this leaves the meaning of our elide-demo product ambiguous. What does it do, why should they use it? Updating ourdata to help our users is just as easy as it is to add new data. Let’s update our bean with the following cURL call.
curl -X PATCH http://localhost:8080/api/v1/group/com.example.repository/products/elide-demo \
-H"Content-Type: application/vnd.api+json" -H"Accept: application/vnd.api+json" \
-d '{
"data": {
"type": "product",
"id": "elide-demo",
"attributes": {
"commonName": "demo application",
"description": "An example implementation of an Elide web service that showcases many Elide features"
}
}
}'