I'm learning about Swagger and how to generate REST Client using Swagger codegen. I know how to do documentation with Swagger, also I know how to generate a simple REST Server with Swagger, but I don't know how to generate a simple REST Client with Swagger codegen.
For example, I have a simple app, it is a REST Server and I want to generate REST Client. Can I do that with Swagger codegen?
The controller for the REST Server:
package com.dgs.spring.springbootswagger.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
@RestController
@RequestMapping("/api/v1")
@Api(value = "Employee Management System", description = "Operations pertaining to employee in Employee Management System")
public class EmployeeController {
@Autowired
private EmployeeRepository employeeRepository;
@ApiOperation(value = "View a list of available employees", response = List.class)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Successfully retrieved list"),
@ApiResponse(code = 401, message = "You are not authorized to view the resource"),
@ApiResponse(code = 403, message = "Accessing the resource you were trying to reach is forbidden"),
@ApiResponse(code = 404, message = "The resource you were trying to reach is not found")
})
@GetMapping("/employees")
public List<Employee> getAllEmployees() {
return employeeRepository.findAll();
}
@ApiOperation(value = "Get an employee by Id")
@GetMapping("/employees/{id}")
public ResponseEntity<Employee> getEmployeeById(
@ApiParam(value = "Employee id from which employee object will retrieve", required = true) @PathVariable(value = "id") Long employeeId)
throws ResourceNotFoundException {
Employee employee = employeeRepository.findById(employeeId)
.orElseThrow(() -> new ResourceNotFoundException("Employee not found for this id :: " + employeeId));
return ResponseEntity.ok().body(employee);
}
@ApiOperation(value = "Add an employee")
@PostMapping("/employees")
public Employee createEmployee(
@ApiParam(value = "Employee object store in database table", required = true) @Valid @RequestBody Employee employee) {
return employeeRepository.save(employee);
}
@ApiOperation(value = "Update an employee")
@PutMapping("/employees/{id}")
public ResponseEntity<Employee> updateEmployee(
@ApiParam(value = "Employee Id to update employee object", required = true) @PathVariable(value = "id") Long employeeId,
@ApiParam(value = "Update employee object", required = true) @Valid @RequestBody Employee employeeDetails) throws ResourceNotFoundException {
Employee employee = employeeRepository.findById(employeeId)
.orElseThrow(() -> new ResourceNotFoundException("Employee not found for this id :: " + employeeId));
employee.setEmail(employeeDetails.getEmail());
employee.setLastName(employeeDetails.getLastName());
employee.setFirstName(employeeDetails.getFirstName());
final Employee updatedEmployee = employeeRepository.save(employee);
return ResponseEntity.ok(updatedEmployee);
}
@ApiOperation(value = "Delete an employee")
@DeleteMapping("/employees/{id}")
public Map<String, Boolean> deleteEmployee(
@ApiParam(value = "Employee Id from which employee object will delete from database table", required = true) @PathVariable(value = "id") Long employeeId)
throws ResourceNotFoundException {
Employee employee = employeeRepository.findById(employeeId)
.orElseThrow(() -> new ResourceNotFoundException("Employee not found for this id :: " + employeeId));
employeeRepository.delete(employee);
Map<String, Boolean> response = new HashMap<>();
response.put("deleted", Boolean.TRUE);
return response;
}
}
After that I've developed a simple REST Client:
package com.dgs.restclient.controllers;
@Controller
public class UpdateController {
@Autowired
private EmployeeRestClient restClient;
@GetMapping("/showStartUpdate")
public String showStartCheckin() {
return "startUpdate";
}
@PostMapping("/startUpdate")
public String startCheckIn(@RequestParam("employeeId") Long employeeId, ModelMap modelMap) {
Employee employee = restClient.findEmployee(employeeId);
modelMap.addAttribute("employee", employee);
return "displayEmployeeDetails";
}
@PostMapping("/completeUpdate")
public String completeCheckIn(@RequestParam("employeeId") Long employeeId,
@RequestParam("employeeFirstName") String employeeFirstName,
@RequestParam("employeeLastName") String employeeLastName,
@RequestParam("employeeEmail") String employeeEmail) {
EmployeeUpdateRequest employeeUpdateRequest = new EmployeeUpdateRequest();
employeeUpdateRequest.setId(employeeId);
employeeUpdateRequest.setFirstName(employeeFirstName);
employeeUpdateRequest.setLastName(employeeLastName);
employeeUpdateRequest.setEmail(employeeEmail);
restClient.updateEmployee(employeeUpdateRequest);
return "updateConfirmation";
}
}
The EmployeeRestClient:
package com.dgs.restclient.integration;
@Component
public class EmployeeRestClientImpl implements EmployeeRestClient {
private static final String EMPLOYEE_REST_URL =
"http://localhost:8080/api/v1/employees/";
@Override
public Employee findEmployee(Long id) {
RestTemplate restTemplate = new RestTemplate();
Employee employee = restTemplate
.getForObject(EMPLOYEE_REST_URL + id, Employee.class);
return employee;
}
@Override
public Employee updateEmployee(EmployeeUpdateRequest request) {
RestTemplate restTemplate = new RestTemplate();
restTemplate
.put(EMPLOYEE_REST_URL + request.getId(), request, Employee.class);
Employee employee = restTemplate
.getForObject(EMPLOYEE_REST_URL + request.getId(), Employee.class);
return employee;
}
}
This REST Client is developed by me and I want to know if I can do this REST Client development with Swagger codegen and how? Do I need just to add the swagger-codegen-maven-plugin in the pom.xml? I've heard about adding this plugin and a yml file and Swagger will create the REST Client. Any feedback will be appreciated!
Swagger Codegen is an open source project which allows generation of API client libraries (SDK generation), server stubs, and documentation automatically from an OpenAPI Specification.
Generate API code with swagger codegen tool To further generate source code, this swagger. yaml file will be the source of input. To facilitate it, Swagger CodeGen tool is used. Swagger provides utility jar to generate client REST clients for different programming languages and framework.
Yes. You can use swagger-codegen-maven-plugin
to generate a REST client. But before that , you need to describe the REST API in YAML or JSON in OpenAPI Specification
mainly because swagger-codegen-maven-plugin
only can generate a REST client from a file written in this specification.
Other answers assume that you need to write the specification manually while my solution take a step further to automatically generating the specification from the REST controller source codes.
The latest OpenAPI version is 3.0 .But based on the package of your imported swagger annotation , you are using version 2.0 (or before). So my solution assume you are using OpenAPI 2.0.
Generating Open API Specification
First, you can use swagger-maven-plugin to generate an OpenAPI spec from the RestController source codes. It basically analyses the Swagger annotations annotated in the @RestController
classes that specified in <locations>
and dump the OpenAPI spec to /src/main/resources/swagger.json
:
<plugin>
<groupId>com.github.kongchen</groupId>
<artifactId>swagger-maven-plugin</artifactId>
<version>3.1.5</version>
<configuration>
<apiSources>
<apiSource>
<springmvc>true</springmvc>
<locations>
<location>com.dgs.spring.springbootswagger.controller.EmployeeController</location>
<location>com.dgs.spring.springbootswagger.controller.FooController</location>
</locations>
<schemes>
<scheme>http</scheme>
</schemes>
<host>127.0.0.1:8080</host>
<basePath>/</basePath>
<info>
<title>My API</title>
<version>1.1.1</version>
</info>
<swaggerDirectory>${basedir}/src/main/resources/</swaggerDirectory>
</apiSource>
</apiSources>
</configuration>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
Execute the followings maven command to start generation:
mvn clean compile
Generating Rest Client
After swagger.json
is generated, you can copy and paste it to your client project (e.g. /src/main/resources/swagger.json) . We can then use swagger-codegen-maven-plugin
to generate a HTTP client .
By default , it will generate the whole maven project which includes test cases and other documentation stuff. But what I want is just the HttpClient 's source codes without other things. After several trial and error , I settle down to the following configuration :
<plugin>
<groupId>io.swagger</groupId>
<artifactId>swagger-codegen-maven-plugin</artifactId>
<version>2.4.7</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${basedir}/src/main/resources/swagger.json</inputSpec>
<language>java</language>
<library>resttemplate</library>
<output>${project.basedir}/target/generated-sources/</output>
<apiPackage>com.example.demo.restclient.api</apiPackage>
<modelPackage>com.example.demo.restclient.model</modelPackage>
<invokerPackage>com.example.demo.restclient</invokerPackage>
<generateApiTests>false</generateApiTests>
<generateModelTests>false</generateModelTests>
<generateApiDocumentation>false</generateApiDocumentation>
<generateModelDocumentation>false</generateModelDocumentation>
<configOptions>
<dateLibrary>java8</dateLibrary>
<sourceFolder>restclient</sourceFolder>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
The generated HTTP client is based on RestTemplate and will be generated to the folder target/generated-sources/restclient
. You may have to configure your IDE to import the generated client in order to use it . (In case of Eclipse, you can configure in Project Properties ➡️ Java Build Path ➡️ Add the folder of the generated rest client)
To start generating the client , just execute the maven command :
mvn clean compile
To use the generated HTTP client :
ApiClient apiClient = new ApiClient();
//Override the default API base path configured in Maven
apiClient.setBasePath("http://api.example.com/api");
EmployeeManagementSystemApi api = new EmployeeManagementSystemApi(apiClient);
api.getEmployeeById(1l);
Note :
javax/xml/bind/annotation/XmlRootElement
exception during generation when using java8+ , you may need to refer to this.Updated:
Your question was answered in another post. Take a look at: related post
...
There is a good tutorial at baeldung about it: how to create rest client with swagger codegen
E.g. Execute command:
java -jar swagger-codegen-cli.jar generate \
-i http://mydomain/v2/swagger.json \
--api-package com.mypackage.api \
--model-package com.mypackage.model \
--invoker-package com.mypackage.invoker \
--group-id com.mygroup \
--artifact-id spring-swagger-codegen-api-client \
--artifact-version 0.0.1-SNAPSHOT \
-l java \
--library resttemplate \
-o spring-swagger-codegen-api-client
Swagger Codegen supports the following Client implementations:
P.S. As you can see, the rest client is generated from swagger spec definition and it is definided with “-i” argument.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With