This example shows an example to read JSON based data from REST endpoint. There may be many examples doing the similar task of reading JSON data into a POJO model using the many data binding libraries like com.fasterxml.databinding
libraries. However this example is little different, it does similar task of reloading, however at the end of the example you will end up a JPA entity class that can be used exactly as RDBMS based entity, i.e. you can issue queries against it. Yes, that is correct!, you can issue JPA queries against a JSON document to filter the data, or join the entity with another entity to integrate data. For example, join the JSON data with RDBMS based data. See there is another example on this topic.
First you set up a basic build script. You can use any build system you like when building apps with Spring, but the code you need to work with Maven is included here. If you’re not familiar with Maven, refer to Building Java Projects with Maven.
Go to Spring Initializer and type in "JPA" in dependencies and generate a project. Then open the generated code in your favorite IDE, and edit the pom.xml to add the below dependencies.
Otherwise, in a project directory of your choosing, create the following sub-directory structure; for example, with
mkdir -p src/main/java/example on *nix systems:
and create pom.xml file of your choosing and add following maven dependencies Spring Boot
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
The following are the Teiid related dependencies
<dependency>
<groupId>org.teiid</groupId>
<artifactId>teiid-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.teiid</groupId>
<artifactId>spring-data-rest</artifactId>
</dependency>
in this example, we will create Entity class that can read JSON data from web service from
http://dummy.restapiexample.com/api/v1/employees
which returns JSON data like below. Note that JSON can be complex, for example sake a simple format has been selected.
{ "status":"success", "data":[ { "id":"1", "employee_name":"Tiger Nixon", "employee_salary":"320800", "employee_age":"61", "profile_image":"" }, { "id":"2", "employee_name":"Garrett Winters", "employee_salary":"170750", "employee_age":"63", "profile_image":"" }] }
Now it is time to define the main Entity or View class. Since we are reading a Employee
let’s call it Employee class
@JsonTable(endpoint = "webCallBean", source = "rest", root = "/data")
@Entity
public class Employee {
@Id
private Integer id;
private String employee_name;
public Employee() {
}
public Employee(int id, String name) {
this.id = id;
this.employee_name = name;
}
public Integer getId() {
return this.id;
}
public String getName() {
return this.employee_name;
}
public void setId(Integer id) {
this.id = id;
}
public void setName(String quote) {
this.employee_name = quote;
}
@Override
public String toString() {
return "Value{" + "id=" + id + ", Name='" + employee_name + '\'' + '}';
}
}
Here you have a Employee class with two attributes, the id, employee_name. You also have two constructors. The default constructor only exists for the sake of JPA. You won’t use it directly. The other constructor is the one you’ll use to create instances of Quote.
The Employee class is annotated with @Entity
, indicating that it is a JPA entity. For @Table
annotation, is optional, but use it to give a different name. Sometimes @Table also need to be used to avoid the naming conflicts.
The Employee’s id property is annotated with @Id
so that JPA will recognize it as the object’s identity. The id property.
The other property, quote is left with out any annotation. It is assumed that they’ll be mapped to columns that share the same name as the properties themselves.
@JsonTable annotation is where most of the magic of Teiid occurring. This defines a query that reading the data from web service, and creating the entity. Note, the source
attribute must be set to rest
and endpoint
attribute needs to be set to the location of the service. If there are custom headers need to be defined use @RestConfigutaion annotation and set required properties on it on this entity class.
At application boot time, Teiid Spring Boot scans the application’s packages for these annotations and builds the respective metadata required to create a virtual database internally and deploys to server. To do this scan, define the application package name in this property to the application.properties
file.
spring.teiid.model.package=org.example
In absence of this property entire classpath is scanned, that could take significant time depending upon all the libraries in your application.
For more available annotations, refer to Reference Guide.
The convenient toString() method will print out the Quote’s properties.
Spring Data JPA focuses on using JPA to store data in a relational database. Its most compelling feature is the ability to create repository implementations automatically, at runtime, from a repository interface.
To see how this works, create a repository interface that works with Quote entities:
@Repository
public class EmployeeRepository {
@Autowired
private JdbcTemplate jdbcTemplate;
public List<Employee> findAll() {
List<Employee> result = jdbcTemplate.query("SELECT id, employee_name FROM Employee",
(rs, rowNum) -> new Employee(rs.getInt("id"), rs.getString("employee_name")));
return result;
}
}
EmployeeRepository uses JDBCTemplate interface to work with JPA entities.
Spring Data JPA also allows you to define other query methods by simply declaring their method signature. In a typical Java application, you’d expect to write a class that implements EmployeeRepository. But that’s what makes Spring Data JPA so powerful: You don’t have to write an implementation of the repository interface. Spring Data JPA creates an implementation on the fly when you run the application.
Let’s wire this up and see what it looks like!
Here you create an Application class with all the components.
package org.example;
@SpringBootApplication
public class Application implements CommandLineRunner {
@Autowired
private EmployeeRepository employeeRepository;
@Autowired
RestTemplate restTemplate;
public static void main(String[] args) {
SpringApplication.run(Application.class, args).close();
}
@Override
public void run(String... args) throws Exception {
employeeRepository.findAll().forEach(c -> System.out.println("***" + c));
}
}
Now when you execute this application, you should see results like below.
***Value{id=1, Name='Tiger Nixon'} ***Value{id=2, Name='Garrett Winters'} ***Value{id=3, Name='Ashton Cox'}