eclipse / microprofile-rest-client Goto Github PK
View Code? Open in Web Editor NEWMicroProfile Rest Client
License: Apache License 2.0
MicroProfile Rest Client
License: Apache License 2.0
Explain how readers/writers are wired in and used.
The package level javadoc description for the 1.0.X and dev streams have no description in the Javadocs - http://download.eclipse.org/microprofile/microprofile-rest-client-1.0.1/apidocs/
specifically:
http://download.eclipse.org/microprofile/microprofile-rest-client-1.0.1/apidocs/org/eclipse/microprofile/rest/client/package-summary.html (only lists Emily as the author)
all the rest have no description at all, for example:
http://download.eclipse.org/microprofile/microprofile-rest-client-1.0.1/apidocs/org/eclipse/microprofile/rest/client/annotation/package-summary.html
This should be changed by adding javadoc comments to the package-info.java files.
Clarify in the spec that providers and features should both be registered in a client, both via builder and via annotation.
If microservice A wants to call microservice B via the rest client "remote interface" for B, there should be an option to flow along the HTTP headers and cookies, from the inbound request to A, to the outbound request to B. Automatically forwarding along security credentials, like an Authentication header, or an LTPA SSO cookie, is one key scenario, though there are likely others too. Without this, a secured microservice B will reject the calls from A, if the Auth header, or the SSO cookie, don't flow along on the requests from microservice to microservice.
I was thinking a new CDI annotation, perhaps named @PropagateHeaders, could be defined at the point of injection. It probably needs to take the HttpServletRequest as a param (so it has something to get the inbound headers/cookies from) or maybe use of an @PostContruct annotation.
I don't have all the answers - I just know we need a way to tell the rest client that it needs to not lose the security (or other) headers/cookies that flowed in to microservice A, when it calls microservice B. This is possibly related to whatever resolution occurs for issue #16.
Currently, the @RegisterRestClient
annotation on an interface is not auto-scanned by CDI unless the same interface is also annotated by @Dependent
or a CDI scope annotation - without this annotation, some implementations will see an ambiguous bean deployment failure when trying to inject a type-safe instance of the interface into an injection point qualified with @RestClient
.
By making the @RegisterRestClient
annotation bean-defining, the user can leave off the @Dependent
or scope annotations, and injection of the rest client will succeed.
This issue will be resolved by pull request #83.
We're introducing an annotation to use when registering providers. It was decided that the name @RegisterProviders
wasn't great, but didn't have a better name. So for now we're introducing it with this name, however we want to reevaluate before end of release.
So this ticket serves as a placeholder for that change, and will be closed within 1.0 regardless of results.
When MP-OpenTracing is in the server, it should be possible to start a trace already in the client, so that the network hop between client and server is also recorded as a span.
cc @pavolloffay
See #69 for further details. To me these tests look incorrect, but I might be wrong
Microprofile rest client is still rather new and it is hard to find example for some specific usage, and that is way I'm asking here.
Problem that I now facing is how to use rest client when rest endpoint implements HATEOAS. In this example bellow we have some endpoint https://localhost1/rest/management
that produces output :
{
"departmentId": 10,
"departmentName": "Administration",
"locationId": 1700,
"managerId": 200,
"links": [
{
"href": "https://localhost2/rest/employees",
"rel": "employees",
"type" : "GET"
}
]
}
My question is about how to implement rest client interface that gets content from resource(s) that is defined in links
.
Do we need to build new client interface(we cannot override base url for client interface already created?) for each link in links? Is building new client interface expensive operation, because we can have a lot of links?
It would be nice that solution for given problem can be implemented with microprofile rest client CDI support.
Any guidance to existing documentation, example or pointer in direction to solve problem are welcome.
Thanks on your very good work on Microprofile project.
We have a package-info.java class in the org.eclipse.microprofile.rest.client root package, but not in any of the sub-packages. This file is required in order to generate OSGi bundles with the correct package version.
Without these files, the 1.0.1 release updated all of the sub-packages to be version 1.0.1 (because when there is no package-info.java file) the builds will use the bundle version as the package version, but this is incorrect and could mislead users.
The 1.0.1 release is already out and is incorrect. I think that in order to resolve this, we should add package-info.java files indicating that all sub-package versions should be 1.0.1. Then move on from there - i.e. if we make a change that breaks an API user, we increment the major version; if we make a change that breaks an implementor, we increment the minor version; if we make any other changes, we increment the micro version.
Explain how CDI interceptors are applied.
Java EE requires a JSON-P provider to be available. We should follow suit on the client side.
This is a placeholder for some open TCK issues.
To close the client instance and all associated resources, e.g. an underlying javax.ws.rs.client.Client
.
In https://github.com/eclipse/microprofile-rest-client/blob/master/spec/src/main/asciidoc/cdi.asciidoc
The following text is duplicated:
com.mycompany.remoteServices.MyServiceClient/mp-rest/uri: The base URI to use for this service, the equivalent of the baseUri method. This property (or */mp-rest/url) is considered required, however implementations may have other ways to define these URLs/URIs.
Given that JAX-RS normally uses URI
instead of URL
, RestClientBuilder
should have a method
RestClientBuilder baseUri(URI uri);
in addition to
RestClientBuilder baseUrl(URL url);
and there may be good reasons to deprecate the latter.
Create separate API and SPI. The current RestClientBuilder
represents an API that end users interact with. Create a new SPI that implementers will satisfy that can be used in OSGi and non-OSGi aware environments.
Below is an agreed upon list of changes:
RestClientBuilderProvider
abstract class in a new spi
package:
ServiceLoader
based look upRestClientBuilder
to be an interface
We integrate with MP Config to allow external config of proxies. We test for URL and Scope, but we don't test for providers. We should add tests for the providers.
Explain how to bootstrap a client that is just an interface into a CDI bean, without requiring custom producers.
Define how to use async invocations
I don't understand the motivation to allow for null
return values on ResponseExceptionMapper.toThrowable()
. Can some explain the rationale behind this? To me this looks like an invitation to NPE's and it really complicates the ResponseMapper selection, i.e. you might have cases where the priority would determine another mapper, but because this particular one return null
, you need to fallback to one with higher priority values.
The base of the spec should include rough details about what a rest client looks like.
1- AsyncMethodTest#testExecutorService method stub is created with path "/execSvc" and Rest Client interface "SimpleGetApiAsync" path is "/" blank which cause 404 Not Found error.
2- The same issue, I have observed with test AsyncMethodTest#testAsyncInvocationInterceptorProvider method where stub is created for path "/asyncIntercept", Rest Client interface "SimpleGetApiAsync" final updated path (using filter) is "/808" and finally verification is done for "/asyncIntercept/808".
If it is not an issue, please share the info about, how it is expected to work behind the scene.
We're missing TCK tests for disabling the built in ResponseExceptionMapper
Explain what happens when a check exception is meant to be thrown:
Based on review notes, what we're leaning towards:
Once CDI has been declared, explain how to bootstrap with the config spec in place, matching on config keys and how to potentially override the client.
There exists an ambiguity in the spec, on what happens when providers are registered via both builder and via annotation.
It was agreed at a high level we need to consider:
The TCK tests will fail, atleast not behave consistently, because the built in providers will tend to have the same default priority as a JAX-RS runtime's providers.
This means that our message body readers/writers will have the same priority as the default ones.
Some tests (see discussion on #69) make use of ParamConverterProvider to change the request parameter values on the client side, prior to the actual HTTP request.
I think using a ParamConverter for these purposes is arguable or even wrong. The spec only references ParamConverter for injection cases to supply values to resource fields annotated with @<X>Param
. See section 3.2 in https://github.com/jax-rs/spec/blob/master/spec.pdf.
IMO the following tests make invalid use of a ParamConverterProvider
and should be changed to not depend on the a ParamConverter
, which seems to be a server-side extension point only:
InvokeWithBuiltProvidersTest
InvokeWithRegisteredProvidersTest
CDIInvokeWithRegisteredProvidersTest
@andymc12 Thoughts?
Need to figure out how to simplify the Wiremock runtime so that it doesn't add extra dependencies:
@RunAsClient
to avoid adding the wiremock runtime to the servers?Need to ensure we meet the goal of one command to run the tests.
Replace the current handles
method so that instead of the Response
just pass in the response status code and the headers of the response.
I'm using WildFly Swarm's implementation (2018.2.0) but I always receive the following exception for a simple GET method.
Checking their source code, most of the methods have no real implementation and they just throw this exception, like getEntity()
2018-02-17 00:22:08,681 ERROR [io.undertow.request] (default task-1) UT005023: Exception handling request to /game/users: java.lang.RuntimeException: method call not supported
at org.wildfly.swarm.microprofile.restclient.PartialResponse.notSupported(PartialResponse.java:69)
at org.wildfly.swarm.microprofile.restclient.PartialResponse.getEntity(PartialResponse.java:65)
at org.jboss.resteasy.core.ExceptionHandler.unwrapException(ExceptionHandler.java:128)
at org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:76)
at org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:222)
at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:179)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:422)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:213)
at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:228)
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56)
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85)
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at org.wildfly.swarm.generated.FaviconErrorHandler.handleRequest(FaviconErrorHandler.java:61)
at io.undertow.server.handlers.PathHandler.handleRequest(PathHandler.java:94)
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at org.wildfly.extension.undertow.deployment.GlobalRequestControllerHandler.handleRequest(GlobalRequestControllerHandler.java:68)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292)
at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135)
at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
at org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction.lambda$create$0(SecurityContextThreadSetupAction.java:105)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1508)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272)
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:104)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:326)
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:812)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.base/java.lang.Thread.run(Unknown Source)
With the change to use Wiremock on the client side, the tests for the TCK no longer work correctly on servlet based containers (most of the MP Impls are servlet based). We need to address this to allow the injection of clients to continue to work.
Some ideas we had:
JAX-RS defines an ExceptionMapper that converts an Exception into a Response object.
We should be able to define a mapping of the inverse, by the HTTP response code, what exception to throw.
The instance
method has a doPriv for getting the thread context classloader, but if that is null, it then attempts to get the RestClientBuilderResolver's classloader without privilege. Also, in the loadSpi
method there is a call to cl.getParent()
that also needs to be wrapped in a doPriv.
Implementors should be able to work around this issue by providing the API jar with sufficient permissions (i.e. creating a permissions.perm file in an OSGi bundle), but this ought to be fixed in the next rev of the MP Rest Client spec.
Explain how JAX-RS client request filters, client response filters are applied.
Determine if another filter type is required.
OpenAPI / Swagger has swagger-codegen
which can take a swagger.json
file to generate clients for many available languages.
The swagger.json
file itself can be automatically be created from the JAX-RS interfaces that are annotated with OpenAPI annotations.
In fact the swagger.json
could be skipped in the annotation case and an api-processor could do the work. I have done something similar for docs generation in the past for RHQ : https://github.com/rhq-project/rhq/tree/master/modules/helpers/rest-docs-generator it emits an intermediate XML format though, which then gets turned into DocBook.
Need to handle cases where the application code is in error - these should be documented in the spec and tested in the TCK. Here are a few of the exceptions we should cover (please add more as we think of them):
@GET @PUT public Object someMethod()
@GET @Path("/blah") public Object someMethod(@PathParam("{someParam}")
- in this case there is no path parameter defined@Path
annotation on the passed-in interfaceIssue #35 expose the need for a global or system-wide registration of providers. In the OpenTracing example, the OpenTracing implementation could easily add a ClientRequestFilter that would start the tracing, but then user code would be responsible for registering the filter. Instead, there should be a mechanism that allows automatic registration of providers to be used for all rest clients.
I'd propose using the ServiceLoader mechanism to search the classpath for instances of an interface that would register these providers. In this way, OpenTracing could add an implementation of that interface to register their filter. Likewise, other features (Fault Tolerance, Metrics, or even user-specific features) could register their own providers.
@Emily-Jiang would you or someone else who's more familiar with it be able to help with OSGi support as needed by OpenLiberty?
Create a bootstrap API, not CDI specific, that allows a user to create a rest client proxy from an interface that has JAX-RS annotations on it.
We should automatically register providers used in Java EE 8:
See eclipse/microprofile-open-api#224, this kind of method don't belong to the API and is only issues promises so should disappear from any coming release
Current version 1.0.1 requires that the URL and other attributes like scope
and providers
for an injected client proxy is specified using an external MP Config value under a generated config key.
I suggest to allow specifying the URL also in the code as the default value, using a non-binding attribute of the RestClient qualifier, such as:
@Inject
@RestClient(url="http://localhost/myservice", providers = {MyProvider.class, AnotherProvider.class})
MyService myService
Prepare the MP Rest Client for the new release process. The Jenkins job to use is at https://ci.eclipse.org/microprofile/view/Release/job/MicroProfile%20Releases/
<distributionManagement>
<repository>
<id>ossrh</id>
<name>Sonatype OSSRH - Release Staging Area</name>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
<snapshotRepository>
<id>ossrh</id>
<name>Sonatype OSSRH Snapshots</name>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
<uniqueVersion>true</uniqueVersion>
</snapshotRepository>
</distributionManagement>
<profiles>
<profile>
<id>release</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<autoVersionSubmodules>true</autoVersionSubmodules>
<localCheckout>true</localCheckout>
<useReleaseProfile>false</useReleaseProfile>
<arguments>${arguments} -Prelease</arguments>
</configuration>
</plugin>
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.