spring-cloud-starter-openfeign: Invalid HTTP method: PATCH executing PATCH - spring-cloud-feign

Context
I have a spring boot (version 2.2.6.RELEASE) web project.
From this web application (I call "APP1") I want to call another URI using the PATCH method from another web application (Let's call it "APP2").
In my pom.xml, I have the following dependency:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
Here is how I call the PATCH method of the other web application.
#FeignClient(name = "clientName", url = "base-uri")
public interface MyInterface{
#PatchMapping(value = "/target-uri")
void callClientMethod(Map<String, Object> args);
Problem
The APP2's PATCH method is effectively being called
But then APP1 throws the following error:
feign.RetryableException: Invalid HTTP method: PATCH executing PATCH
I looked on the Internet for a solution, and added the following snipet to my pom.xml
<dependency>
<groupId>com.netflix.feign</groupId> <!-- Also tried io.github.openfeign -->
<artifactId>feign-httpclient</artifactId>
<version>8.18.0</version>
</dependency>
After that, APP2's PATCH method is stille properly called but in APP1 I got the following error :
java.lang.NoSuchMethodError: feign.Response.create(ILjava/lang/String;Ljava/util/Map;Lfeign/Response$Body;)Lfeign/Response;
Question
Does anyone know how to solve this error ?
Thanks in advance for your help !

I had the same problem and spent a lot of time for understand and resolve this problem.
First what you need to understand that is the Feign doesn't support PATCH http method for call from the box!
And if you can change methods in both services use PUT for update instead PATCH...
But if you integrate with third party implementation you should add some configurations:
1. Add dependency which support PATCH http method:
// https://mvnrepository.com/artifact/io.github.openfeign/feign-okhttp
compile group: 'io.github.openfeign', name: 'feign-okhttp', version:
'10.2.0'
Add configuration:
#Configuration
public class FeignConfiguration {
#Bean
public OkHttpClient client() {
return new OkHttpClient();
}
}
And example for PATCH request with Feign:
#FeignClient(name = "someapi", url = "${client.someapi.url}")
#Component
#RequestMapping("/users")
public interface SomeClient {
#RequestMapping(value = "/{id}",
method = RequestMethod.PATCH,
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
FeignUser update(#PathVariable("id") Long id, #RequestBody Map<String, Object> fields);
}
Hope it helps someone.

Just Add:
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>

If you are adding Feign with the following dependency:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId> <!-- has dependecy on spring-cloud-openfeign-core inside, which already maintains version of feign-okhttp artifact -->
</dependency>
you can add okhttp client (without hardcoding artifact version) to fix the issue with PATCH request:
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId> <!-- Required to use PATCH -->
</dependency>
No other steps needed. The okhttp client will be applied automatically by auto configuration.
Also, this way you don't need to manage feign-okhttp artifact version. Spring Cloud will manage version for you.
Tested with Spring Boot 2.7.6

The following config works for me:
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-jackson</artifactId>
<version>${feign.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
<version>${feign.version}</version>
</dependency>
Where:
feign.version - 11.0
Spring Boot - 2.3.0.RELEASE
Spring-cloud.version - 2.2.3.RELEASE

Related

Open Liberty and Jersey servlet - 415 Unsupported Media Type

I'm working with OpenLiberty version 22.0.0.2 (no Jakarta Restful Web Services enabled).
I'm trying to implement a document upload API using the Multipart Feature Provided by Jersey.
I have tried numerous suggestions, but cannot get it to work.
API
#POST
#Path("/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces(MediaType.APPLICATION_JSON)
public Response upload(
#FormDataParam("file") InputStream uploadedInputStream,
#FormDataParam("file") FormDataContentDisposition fileDetail)
Application
#ApplicationPath("/")
public class RestApplication extends ResourceConfig {
public RestApplication() {
register(MultiPartFeature.class);
packages("com.packages.to.scan");
}
pom.xml
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.28</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.28</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>2.28</version>
</dependency>
The error I'm getting in OL when uploading a file via Postman:
[INFO] [ERROR] No message body reader has been found for class org.glassfish.jersey.media.multipart.FormDataContentDisposition, ContentType: multipart/form-data;boundary=--------------------------814467839830640328856820
Postman outputs
What am I missing in the setup?

can't set up swagger with jax-rs

I can't understand, why swagger doesn't work with my spring boot jax-rs app.
I add this dependencies to pom.xml:
<!-- Swagger -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-service-description-swagger</artifactId>
<version>3.3.4</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>swagger-ui</artifactId>
<version>3.1.5</version>
</dependency>
also I set up -> cxf.jaxrs.component-scan=true in application properties,my rest requests:
#Path("/")
#Api("/")
#Service
public interface IService {
#GET
#Path("/health")
#ApiOperation("/health")
#Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Status getStatus();
#GET
#Path("/info")
#ApiOperation("/info")
#Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Info getInfo();
}
work as I expected, but I can't get documentation, when I call:
http://localhost:8000/swagger-ui.html
get -> Whitelabel Error Page.
Maybe someone can help me?
just in case here is my properties file:
#cxf url mapping
cxf.path=/api
cxf.jaxrs.component-scan=true
cxf.jaxrs.classes-scan-packages=com,org.apache.cxf.jaxrs.swagger.Swagger2Feature,org.codehaus.jackson.jaxrs,org.apache.cxf.jaxrs.swagger.ui.SwaggerUiResourceLocator
#port
server.port=8000
server.servlet.context-path=/
Can you please share the complete project?
You'll find working samples in https://github.com/apache/cxf/tree/cxf-3.3.4/distribution/src/main/release/samples/jax_rs, if you start a new project I suggest to go with OpenAPI v3 instead of Swagger.

SqsListner not listening to messages

I have below application.properties for connection:
cloud.aws.credentials.instanceProfile=true
cloud.aws.credentials.useDefaultAwsCredentialsChain=true
cloud.aws.region.static=us-east-2
cloud.aws.stack.auto=false
I have written listener with SqsListner and running my application with below dependencies
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-aws-messaging</artifactId>
<version>1.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>1.4.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-aws-messaging</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
But somehow my listener is not listening to messages (I am doing this in the existing code base).
I tried creating a separate spring boot application with only the listener in it, which is working fine. But the same thing is not working when added to existing code
and Listener code is as below:
#SqsListener(value = "test-queue",deletionPolicy = ON_SUCCESS)
public void receiveMessage(String message,
#Header(X_REQUEST_ID) String xRequestId,
#Header(X_SESSION_ID) String xSessionId) {
LOGGER.info("message received is: {}", message);
}
}
By mistake I had overriden AmazonSQSAsync bean
public AmazonSQSAsync amazonSQSClient() {
return new AmazonSQSAsyncClient();
}
which caused ignoring the aws properties I added. And hence SqsListner was not working as there is no way to explicitly specify aws properties including credentials to SqsListner. I removed the manual bean creation part and it started working smoothly as Bean is automatically created now and picking up the correct properties.

Spring cloud contract stub jar as a http rest endpoint

I'm trying to setup Spring contract stub jar as either a fat jar with consumer or a http REST endpoint that my services can send request to and eventually receive the evaluated response.
Ideally I'd prefer the latter where consumer could run the stub to manage the interactions. My tests from consumer to local producer stubs work as expected. My compilation fails when I add the required annotations to the main class for stub runner. I think I'm missing some config or setup needed for the consumer to run the stub either as http REST endpoint or recognize within its m2.
The app compilation fails with #EnableStubRunnerServer complaining the below:
ConsumerApplication.java:[8,60] package org.springframework.cloud.contract.stubrunner.server does not exist
ConsumerApplication.java:[15,2] cannot find symbol
[ERROR] symbol: class EnableStubRunnerServer
ConsumerApplication.java:
#SpringBootApplication
#EnableWebMvc
#EnableStubRunnerServer
#Slf4j
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
application.properties (Consumer):
stubrunner.ids=com.somecompany.somegroup:producer:0.0.1-SNAPSHOT:stubs:8081
stubrunner.stubsMode=REMOTE
server.ssl.key-store-password=password
server.ssl.key-password=password
server.ssl.trust-store-password=password
server.port=8081
Test.java: - This test works
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
#AutoConfigureMockMvc
#AutoConfigureJsonTesters
#AutoConfigureStubRunner( ids = "com.somecompany.somegroup:producer:+:stubs:8081",
stubsMode = StubRunnerProperties.StubsMode.LOCAL)
#DirtiesContext
public class ContractControllerTest extends AbstractTest {
}
pom:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-contract-stub-runner</artifactId>
<scope>test</scope>
</dependency>
Since you're trying to add test code to your main, production code, you have to change
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-contract-stub-runner</artifactId>
<scope>test</scope>
</dependency>
to
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-contract-stub-runner</artifactId>
</dependency>

JIRA REST CLIENT: issue.getattachments() returns null

I am trying to get the attachments for a JIRA issue. However the getAttachments() method is returning null. The JIRA version is v6.1.4
Below is the code
final JiraRestClientFactory factory = new AsynchronousJiraRestClientFactory();
final URI jiraServerUri = new URI("http://XXX-jira.YYY.com");
final JiraRestClient restClient = factory.createWithBasicHttpAuthentication(jiraServerUri, "XXXX", "YYYY");
//final NullProgressMonitor pm = new NullProgressMonitor();
final Issue issue = restClient.getIssueClient().getIssue("XXX-35238").claim();
System.out.println(issue);
System.out.println(issue.getAttachments());
Below are the maven dependencies
<dependency>
<groupId>com.atlassian.jira</groupId>
<artifactId>jira-rest-java-client</artifactId>
<version>2.0.0-m2</version>
</dependency>
<dependency>
<groupId>com.atlassian.jira</groupId>
<artifactId>jira-rest-java-client-api</artifactId>
<version>2.0.0-m25</version>
</dependency>
<dependency>
<groupId>com.atlassian.jira</groupId>
<artifactId>jira-rest-java-client-plugin</artifactId>
<version>2.0.0-m25</version>
</dependency>
<dependency>
<groupId>com.atlassian.jira</groupId>
<artifactId>jira-rest-java-client-core</artifactId>
<version>2.0.0-m25</version>
</dependency>
Your help is much appreciated.
The "Attachments" field must be available in the "default screen". Otherwise the attachments will not be included to the response (although they are visible when viewing the issue in the browser...)

Resources