= Reading Data from an Infinispan Based Source

This article shows an example to read/write data from Infinispan Cache. Basically, when a user defines a Proto Definition file and registers with the Infinispan cache, then Teiid can be used to read/write Messages defined in the protobuf file as JPA entities. Care must be taken such that each high level Message is defined in its own cache. Please see Teiid documention on Infinispan on how to annotate the Message in protobuf file. 

=== What you’ll need

* About 15 minutes
* A favorite text editor or IDE
* JDK 1.8 or later
* Maven 3.0+

=== Build With Maven
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 link:https://spring.io/guides/gs/maven[Building Java Projects with Maven].

Go to link:http://start.spring.io/[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


[source,xml]
.*spring-boot-starter-data-jpa*
----
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
----

The following are the Teiid related dependencies
[source,xml]
.*teiid-spring-boot-starter,data-infinispan*
----
<dependency>
   <groupId>org.teiid</groupId>
   <artifactId>teiid-spring-boot-starter</artifactId>
</dependency>
<dependency>
    <groupId>org.teiid.spring</groupId>
    <artifactId>spring-data-infinispan</artifactId>
</dependency>
----


=== Define View/Entity Class
Now it is time to define the main Entity or View class. Since we are reading a `Employee` information, let's call it Employee class

[source,java]
.src/main/java/com/example/Employee.java
----
@Entity
public class Employee {
	@Id
    private int ROW_ID;
    @Column(name="firstname")
    private String firstName;
    @Column(name="lastname")
    private String lastName;
    private int age;
    
    // rest of the class ignored for brevity. create all the getters and setters. See example code.
----

Here you have a Employee class with four attributes, the ROW_ID, firstname, lastname and age. The ROW_ID is used as @id of your JPA entity and also as cache key.

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.

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.

[source,text]
.*src/main/resources/application.properties*
----
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.

[source,text]
.*src/main/resources/application.properties*
----
spring.teiid.data.infinispan.accounts.url=localhost:11222
spring.teiid.data.infinispan.accounts.importer.ProtobufName=accounts.proto
----

The above properties define the location of your Infinispan cache. Where 'accounts' is bean name of data source as described below.

=== Create DataSource class

To create a connection to the Infinispan cache, we need to create connection class, in Spring Boot it can be done as

----
@Configuration
public class DataSources {

    @Bean(name="accounts")
    public InfinispanConnectionFactory accounts(@Autowired @Qualifier("ispnConfig") InfinispanConfiguration config) {
        return new InfinispanConnectionFactory(config);
    }

    @Bean(name="ispnConfig")
    @ConfigurationProperties("spring.teiid.data.infinispan.accounts")
    public InfinispanConfiguration ispnConfig() {
        return new InfinispanConfiguration();
    }
}
----

Please note the bean name as 'accounts' matches with the configuration name.

=== Create Spring Data Repository class

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. Here we extended the same feature to work with Excel based data.

To see how this works, create a repository interface that works with Employee entities:

[source,java]
.src/main/java/org/example/EmployeeRepository.java
----
@Repository
public interface EmployeeRepository extends CrudRepository<Employee, Integer>{

}  
----

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!

=== Create an Application class

Here you create an Application class with all the components.

[source,java]
.src/main/java/org/example/Application.java
----
package org.example;

@SpringBootApplication
public class Application implements CommandLineRunner {

    @Autowired
    private EmployeeRepository employeeRepository;
    
	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.

----
Employee [ROW_ID=2, firstName=John, lastName=Doe, age=23]
Employee [ROW_ID=3, firstName=Jane, lastName=Smith, age=40]
Employee [ROW_ID=4, firstName=Matt, lastName=Liek, age=13]
Employee [ROW_ID=5, firstName=Sarah, lastName=Byne, age=10]
Employee [ROW_ID=6, firstName=Rocky, lastName=Dog, age=3]
----

You can instead of calling `employeeRepository.findAll()` call any other query or use `JDBCTemplate` class to issue a custom query, and Teiid engine will treat the Excel document data exactly any RDBMS data and apply any filters or aggregations for you and return the data.

Note: You can always integrate data from multiple different types of data sources using Teiid.
