I previously blogged about a demo using Spring Boot and Feign making an external based REST call to a service I had created. The real purpose of that demo "http://theblasfrompas.blogspot.com.au/2016/12/spring-boot-feign-client-accessing.html" was to use Twitter Typeahead for auto completion which is the demo on Github below. The returned data is now used in an INPUT text input for auto completion as the user types in the Country Name
https://github.com/papicella/FeignClientExternalSpringBoot
Search This Blog
Showing posts with label Feign. Show all posts
Showing posts with label Feign. Show all posts
Wednesday, 14 December 2016
Friday, 9 December 2016
Spring Boot / Feign Client accessing external service
Previously we used Feign to create clients for our own services, which are registered on our Eureka Server using a service name as shown in the previous blog post http://theblasfrompas.blogspot.com.au/2016/11/declarative-rest-client-feign-with_8.html. It's not unusual that you'd want to implement an external rest endpoint, basically an endpoint that's not discoverable by Eureka. In that case, you can use the url property on the @FeignClient annotation,
which gracefully supports property injection. His an example of this.
Full example on GitHub as follows
https://github.com/papicella/FeignClientExternalSpringBoot
1. Start by adding the correct maven dependencies and the one you need is as follows, there would be others if you want to use a web based spring boot project etc.
2. We are going to consume this external service as follows
http://country.io/names.json
To do that we create a simple interface as follows
3. In this example I have created a RestController to consume this REST service and test it because it's the easiest way to do this. We simply AutoWire the CountryServiceClient interface into the RestController to make those external calls through FEIGN.
4. Of course we will have our main class to boot strap the application and it includes the "spring-boot-starter-web" maven repo to start a tomcat server for us.
5. Ensure your application.properties or application.yml has the following properties to disable timeouts.
feign:
hystrix:
enabled: false
hystrix:
command:
choose:
default:
execution:
timeout:
enabled: false
6. Run the main class "FeignClientExternalSpringBootApplication"
Access as follows
http://localhost:8080/countries
which gracefully supports property injection. His an example of this.
Full example on GitHub as follows
https://github.com/papicella/FeignClientExternalSpringBoot
1. Start by adding the correct maven dependencies and the one you need is as follows, there would be others if you want to use a web based spring boot project etc.
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency>
2. We are going to consume this external service as follows
http://country.io/names.json
To do that we create a simple interface as follows
package pas.au.pivotal.feign.external;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@FeignClient(name = "country-service-client", url = "http://country.io")
public interface CountryServiceClient {
@RequestMapping(method = RequestMethod.GET, value = "/names.json")
String getCountries();
}
3. In this example I have created a RestController to consume this REST service and test it because it's the easiest way to do this. We simply AutoWire the CountryServiceClient interface into the RestController to make those external calls through FEIGN.
package pas.au.pivotal.feign.external.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.json.JsonParser;
import org.springframework.boot.json.JsonParserFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import pas.au.pivotal.feign.external.CountryServiceClient;
import java.util.Map;
@RestController
public class CountryRest
{
Logger logger = LoggerFactory.getLogger(CountryRest.class);
private static final JsonParser parser = JsonParserFactory.getJsonParser();
@Autowired
private CountryServiceClient countryServiceClient;
@RequestMapping(value = "/countries", method = RequestMethod.GET,
produces = "application/json")
public String allCountries()
{
String countries = countryServiceClient.getCountries();
return countries;
}
@RequestMapping(value = "/country_names", method = RequestMethod.GET)
public String[] countryNames ()
{
String countries = countryServiceClient.getCountries();
Map<String, Object> countryMap = parser.parseMap(countries);
String countryArray[] = new String[countryMap.size()];
logger.info("Size of countries " + countryArray.length);
int i = 0;
for (Map.Entry<String, Object> entry : countryMap.entrySet()) {
countryArray[i] = (String) entry.getValue();
i++;
}
return countryArray;
}
}
4. Of course we will have our main class to boot strap the application and it includes the "spring-boot-starter-web" maven repo to start a tomcat server for us.
package pas.au.pivotal.feign.external;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients
public class FeignClientExternalSpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(FeignClientExternalSpringBootApplication.class, args);
}
}
5. Ensure your application.properties or application.yml has the following properties to disable timeouts.
feign:
hystrix:
enabled: false
hystrix:
command:
choose:
default:
execution:
timeout:
enabled: false
6. Run the main class "FeignClientExternalSpringBootApplication"
Access as follows
http://localhost:8080/countries
Tuesday, 8 November 2016
Declarative REST Client Feign with Spring Boot
Feign is a declarative web service client. It makes writing web service clients easier. To use Feign create an interface and annotate it. It has pluggable annotation support including Feign annotations and JAX-RS annotations. Feign also supports pluggable encoders and decoders.
In this example I show how to use Spring Cloud / Spring Boot application with Feign. The source code for this is as follows
https://github.com/papicella/SpringBootEmployeeFeignClient
1. Include the required maven dependency for Feign as shown below
2. Assuming your going to lookup a service using Service Discovery with Spring Cloud then include this dependency as well, the example below is doing this using Spring Cloud Service Discovery.
See the Spring Cloud Project page for details on setting up your build system with the current Spring Cloud Release Train
3. To enable Feign we simple add the annotation @EnableFeignClients as shown below
4. Next we have to create an interface to call our service methods. The interface methods must match the service method signatures as shown below. In this example we use Spring Cloud service discovery to find our service and invoke the right implementation method, Feign can do more then just call registered services through spring cloud service discovery BUT this example does that.
EmployeeServiceClient Interface
So what does the actual service method look like?
5. It's important to note that the Feign client is calling a service method using Spring Cloud service discovery , the screen shot below shows how it looks inside Pivotal Cloud Foundry when we select out service registry instance and click on Manage
6. Finally we just need to call our service using the Feign client interface and do do that with Autowire as required. In this example below we use a class annotated with @Controller as shown below which then using the returned data to display the results to a web page using Thymeleaf
7. The Web page "employees.html" fragment accessing the returned List of employees is as follows.
More Information
1. Spring Cloud
http://projects.spring.io/spring-cloud/
2. Declarative REST Client: Feign
http://cloud.spring.io/spring-cloud-netflix/spring-cloud-netflix.html#spring-cloud-feign
In this example I show how to use Spring Cloud / Spring Boot application with Feign. The source code for this is as follows
https://github.com/papicella/SpringBootEmployeeFeignClient
1. Include the required maven dependency for Feign as shown below
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency>
2. Assuming your going to lookup a service using Service Discovery with Spring Cloud then include this dependency as well, the example below is doing this using Spring Cloud Service Discovery.
<dependency> <groupId>io.pivotal.spring.cloud</groupId> <artifactId>spring-cloud-services-starter-service-registry</artifactId> </dependency>
See the Spring Cloud Project page for details on setting up your build system with the current Spring Cloud Release Train
3. To enable Feign we simple add the annotation @EnableFeignClients as shown below
package pas.au.scs.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class SpringBootEmployeeFeignClientApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootEmployeeFeignClientApplication.class, args);
}
}
4. Next we have to create an interface to call our service methods. The interface methods must match the service method signatures as shown below. In this example we use Spring Cloud service discovery to find our service and invoke the right implementation method, Feign can do more then just call registered services through spring cloud service discovery BUT this example does that.
EmployeeServiceClient Interface
package pas.au.scs.demo.employee;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.util.List;
@FeignClient("SPRINGBOOT-EMPLOYEE-SERVICE")
public interface EmployeeServiceClient
{
@RequestMapping(method = RequestMethod.GET, value = "/emps")
List<Employee> listEmployees();
}
So what does the actual service method look like?
@RestController
public class EmployeeRest
{
private static Log logger = LogFactory.getLog(EmployeeRest.class);
private EmployeeRepository employeeRepository;
@Autowired
public EmployeeRest(EmployeeRepository employeeRepository)
{
this.employeeRepository = employeeRepository;
}
@RequestMapping(value = "/emps",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
public List<Employee> listEmployees()
{
logger.info("REST request to get all Employees");
List<Employee> emps = employeeRepository.findAll();
return emps;
}
.....
5. It's important to note that the Feign client is calling a service method using Spring Cloud service discovery , the screen shot below shows how it looks inside Pivotal Cloud Foundry when we select out service registry instance and click on Manage
6. Finally we just need to call our service using the Feign client interface and do do that with Autowire as required. In this example below we use a class annotated with @Controller as shown below which then using the returned data to display the results to a web page using Thymeleaf
package pas.au.scs.demo.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import pas.au.scs.demo.employee.EmployeeServiceClient;
@Controller
public class EmployeeFeignController
{
Logger logger = LoggerFactory.getLogger(EmployeeFeignController.class);
@Autowired
private EmployeeServiceClient employeeServiceClient;
@RequestMapping(value = "/", method = RequestMethod.GET)
public String homePage(Model model) throws Exception
{
model.addAttribute("employees", employeeServiceClient.listEmployees());
return "employees";
}
}
7. The Web page "employees.html" fragment accessing the returned List of employees is as follows.
<div class="col-xs-12">
<table id="example" class="table table-hover table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Job</th>
<th>Mgr</th>
<th>Salary</th>
</tr>
</thead>
<tbody>
<tr th:each="employee : ${employees}">
<td th:text="${employee.id}"></td>
<td th:text="${employee.name}"></td>
<td th:text="${employee.job}"></td>
<td th:text="${employee.mgr}"></td>
<td th:text="${employee.salary}"></td>
</tr>
</tbody>
</table>
</div>
More Information
1. Spring Cloud
http://projects.spring.io/spring-cloud/
2. Declarative REST Client: Feign
http://cloud.spring.io/spring-cloud-netflix/spring-cloud-netflix.html#spring-cloud-feign
Subscribe to:
Posts (Atom)


