Search This Blog

Showing posts with label Rest Repositories. Show all posts
Showing posts with label Rest Repositories. Show all posts

Monday, 22 May 2017

Using HTTPIE with Spring Boot Rest Repositories

I recently got introduced to HTTPIE as a command line alternative to CURL for testing RESTful api endpoints created using @RestController annotated classes. For more information on httpie follow this link

Before we test this out lets create a very basic Spring Boot Application with classes/interfaces to verify HTTPIE. The following assumes you have a Spring Boot application already created and it has maven dependancies as follows to enable JPA, Rest Repositories, H2 and Web support

Note: We are using Spring Boot 1.5.3 here
  
<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>1.5.3.RELEASE</version>
  <relativePath/> <!-- lookup parent from repository -->
 </parent>

 <properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  <java.version>1.8</java.version>
 </properties>

 <dependencies>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-rest</artifactId>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-jpa</artifactId>
  </dependency>
  <dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-entitymanager</artifactId>
  </dependency>
  <dependency>
   <groupId>com.h2database</groupId>
   <artifactId>h2</artifactId>
   <scope>runtime</scope>
  </dependency>
 </dependencies>

1. Create classes/interfaces as follows

Employee.java
  
package pivotal.io.boot.httpie.demo;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Employee
{
    @Id
    @GeneratedValue (strategy = GenerationType.AUTO)
    private Long id;

    private String firstName;
    private String lastName;
    private String job;

    public Employee()
    {
    }

    public Employee(String firstName, String lastName, String job) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.job = job;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                ", job='" + job + '\'' +
                '}';
    }
}

EmployeeRepository.java
  
package pivotal.io.boot.httpie.demo;

import org.springframework.data.jpa.repository.JpaRepository;

public interface EmployeeRepository extends JpaRepository <Employee, Long> {
}  

EmployeeRest.java
  
package pivotal.io.boot.httpie.demo;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping ("/api/employee")
public class EmployeeRest
{
    private static Log logger = LogFactory.getLog(EmployeeRest.class);

    @Autowired
    private EmployeeRepository employeeRepository;

    @GetMapping("/emps")
    public List<Employee> allEmployees()
    {
        return employeeRepository.findAll();
    }

    @GetMapping("/emp/{employeeId}")
    public Employee findEmployee (@PathVariable Long employeeId)
    {
        Employee emp = employeeRepository.findOne(employeeId);

        return emp;
    }

    @PostMapping("/emps")
    public Employee createEmployee(@RequestBody Employee employee)
    {
        return employeeRepository.save(employee);
    }

    @DeleteMapping("/emps/{employeeId}")
    public void deleteEmployee(@PathVariable Long employeeId)
    {
        Employee emp = employeeRepository.findOne(employeeId);
        employeeRepository.delete(emp);
        logger.info("Employee with id " + employeeId + " deleted...");
    }

}

2. Run the Spring Boot Application which will run on port localhost:8080


  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.5.3.RELEASE)

2017-05-22 13:39:22.910  INFO 8875 --- [           main] p.i.b.h.d.HttpieSpringbootApplication    : Starting HttpieSpringbootApplication on pas-macbook with PID 8875 (/Users/pasapicella/pivotal/DemoProjects/spring-starter/pivotal/httpie-springboot/target/classes started by pasapicella in /Users/pasapicella/pivotal/DemoProjects/spring-starter/pivotal/httpie-springboot)

...

2017-05-22 13:39:25.948  INFO 8875 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2017-05-22 13:39:25.952  INFO 8875 --- [           main] p.i.b.h.d.HttpieSpringbootApplication    : Started HttpieSpringbootApplication in 3.282 seconds (JVM running for 3.676)

Now we can test HTTPIE and here are some endpoints

3. Here are some examples with output

** All Employees **

pasapicella@pas-macbook:~$ http http://localhost:8080/api/employee/emps
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
Date: Mon, 22 May 2017 01:26:43 GMT
Transfer-Encoding: chunked

[
    {
        "firstName": "pas",
        "id": 1,
        "job": "CEO",
        "lastName": "Apicella"
    },
    {
        "firstName": "lucia",
        "id": 2,
        "job": "CIO",
        "lastName": "Apicella"
    },
    {
        "firstName": "lucas",
        "id": 3,
        "job": "MANAGER",
        "lastName": "Apicella"
    },
    {
        "firstName": "siena",
        "id": 4,
        "job": "CLERK",
        "lastName": "Apicella"
    }
]

** Find Employee by {employeeId} **

pasapicella@pas-macbook:~$ http http://localhost:8080/api/employee/emp/1
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
Date: Mon, 22 May 2017 01:31:32 GMT
Transfer-Encoding: chunked

{
    "firstName": "pas",
    "id": 1,
    "job": "CEO",
    "lastName": "Apicella"
}

** POST new employee **

pasapicella@pas-macbook:~$ http POST http://localhost:8080/api/employee/emps firstName=john lastName=black job=CLERK
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
Date: Mon, 22 May 2017 02:32:34 GMT
Transfer-Encoding: chunked

{
    "firstName": "john",
    "id": 5,
    "job": "CLERK",
    "lastName": "black"
}

** POST with updated employee object **

pasapicella@pas-macbook:~$ http POST http://localhost:8080/api/employee/emps id:=5 firstName=john lastName=black job=CLEANER
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
Date: Mon, 22 May 2017 02:36:06 GMT
Transfer-Encoding: chunked

{
    "firstName": "john",
    "id": 5,
    "job": "CLEANER",
    "lastName": "black"
}

** Delete employee with {employeeId} 5 **

pasapicella@pas-macbook:~$ http DELETE http://localhost:8080/api/employee/emps/5
HTTP/1.1 200
Content-Length: 0
Date: Mon, 22 May 2017 02:36:56 GMT