kumuluz / kumuluzee

Lightweight open-source framework for developing microservices using standard Java EE technologies and migrating Java EE to cloud-native architecture.
https://ee.kumuluz.com
MIT License
291 stars 71 forks source link

rest client - dynamic parameters + exceptions #159

Closed eriskooo closed 4 years ago

eriskooo commented 4 years ago

hello, is there any chance to have dynamic number of params, fex in get request ? + why does rest client throws an exception when receving 4xx / 5xx code ?

Jamsek-m commented 4 years ago

why does rest client throws an exception when receving 4xx / 5xx code ?

Hi, by default, A DefaultExceptionMapper is registered with every client instance, which takes any response with status 400 or greater and returns WebApplicationException.

To avoid this, you can set key microprofile.rest.client.disable.default.mapper to false, so that default mapper will not be registered and no exception will be thrown. However, if you are not using raw response object as return type, you may have problems with serialization of response body, if you will receive error from server. Therefore it is probably a good idea to define your own mappers.

hello, is there any chance to have dynamic number of params, fex in get request ?

KumuluzEE uses Jersey underneath, so you can try something like this: link

eriskooo commented 4 years ago

hi, thank you for answer about exceptions -> second part, I ment dynamic amount of parameters with different names. eq, there is endpoint, which will return items based on 10 different criterias (GET), If I need only 3 of them there seems to be no way how to define client interface.

eriskooo commented 4 years ago

hi - to the 1st answer - I would like rest client to NOT TO throw an exception, unfortunately, microprofile: rest: client: disable: default: mapper: false did not avoid throwing and exception while receiving for example 404.

Jamsek-m commented 4 years ago

Hi, yeah, sorry, it should be set to true

eriskooo commented 4 years ago

unfortunately, neither microprofile: rest: client: disable: default: mapper: true did job

Jamsek-m commented 4 years ago

second part, I ment dynamic amount of parameters with different names. eq, there is endpoint, which will return items based on 10 different criterias (GET), If I need only 3 of them there seems to be no way how to define client interface.

For dynamic query parameters, as far as I know, MP spec doesn't specify any way to provide dynamic query parameters. You either need to specify them as method parameters, or you need to specify them as part of BeanParam. However, in both cases, when adding them to request, Jersey will throw exception if any value is null, making them non-optional.

unfortunately, neither microprofile: rest: client: disable: default: mapper: true did job

I just tested it and it should work. Are you providing it in yaml format with proper indentation?

microprofile:
  rest:
    client:
      disable:
        default:
          mapper: true
eriskooo commented 4 years ago

thank you, it's working with 4xx + 5xx errors. and plz how about those query params ?

Jamsek-m commented 4 years ago

I checked and JAX-RS client does indeed allow null values to be set for query parameters - if value is null, they are simply not set. It seems the problem is only with Jersey's implementation of UriBuilder, which is used behind the scene. I will probably add filtering of null values, but I need first to check if it would be a viable solution. This would enable you to define POJO with @QueryParam annotations on fields (your 10 fields), and simply populate needed fields (your 3 fields you actually want to pass), while null fields will be ignored. You then simply pass this POJO to interface as @BeanParam.

Jamsek-m commented 4 years ago

If you raise rest client's version to 1.4.0-SNAPSHOT now, you should be able to specify POJO class with query parameters and only non-null values will be sent to server.

public class MyBean {
  @QueryParam("param1")
  public String param1;
  @QueryParam("param2")
  public String param2;
  @QueryParam("param3")
  public String param3;
  @QueryParam("param4")
  public String param4;
 // ...  
}
public interface MyApi {
  @GET
  @Path("/call")
  Response callMe(@BeanParam MyBean bean);
}
// ...
  MyBean bean = new MyBean();
  bean.param1 = "set";
  bean.param3  = "set";

 Response response = myApi.callMe(bean);
 // will call /call?param1=set&param3=set
// ...

Don't forget to include snapshot repository in your pom.xml to use snapshot version:

    <repositories>
        <repository>
            <id>sonatype-snapshots</id>
            <name>Sonatype Snapshots</name>
            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
            <releases>
                <enabled>false</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>sonatype-snapshots</id>
            <name>Sonatype Snapshots</name>
            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
            <releases>
                <enabled>false</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>
eriskooo commented 4 years ago

many thanks !