How to define HTTP filter for GraphQL requests? - quarkus

I use Quarkus 1.6.1.Final version with GraphQL implementation using SmallRye GraphQL. My aim is to define logic to check user permissions on every request (Query + Mutation) made to /graphql endpoint. So, I am trying to find something like jax-rs ContainerRequestFilter but for GraphQL. Do you have any ideas on how to do it? I've tried to define ContainerRequestFilter but it catches only RestEasy requests but not GraphQL ones.

I was looking into this myself. It seems like GraphQL directly registers a Vert.X routing call [1] rather than using Undertow(servlets) or RestEASY(jaxrs). This is so it can do stuff like partial results more easily from what I can tell.
You're going to want to look at intercepting Vert.X requests using the RouteFilter annotation. I've included the link below, but it works a lot like the ContainerRequestFilter from jax-rs. I've copied the sample code from the Quarkus help guide [2] to provide a quick example:
package org.acme.reactive.routes;
import io.vertx.ext.web.RoutingContext;
public class MyFilters {
#RouteFilter(100)
void myFilter(RoutingContext rc) {
// Put your logic here
// continue the filtering of the request
rc.next();
}
}
1: https://github.com/quarkusio/quarkus/blob/master/extensions/smallrye-graphql/runtime/src/main/java/io/quarkus/smallrye/graphql/runtime/SmallRyeGraphQLRecorder.java
2: https://quarkus.io/guides/reactive-routes#intercepting-http-requests

Related

Reactive rest client headers injection in Quarkus

I am following the guide of the new quarkus-resteasy-reactive-jackson extension to use it in an existing Quarkus application deployed in production.
In the Custom headers support section it's introduced the ClientHeadersFactory interface to allow injecting headers in a request, but you are forced to return a sync response. One can not use Uni<MultivaluedMap<String, String>>, which is of what is desired in my case, because I need to add a token in the header, and this token is retrieved by a request to another rest endpoint that returns a Uni<Token>.
How can I achieve this in the new implementation? If not possible, is there a workaround?
It's not possible to use Uni<MultivaluedMap<...>> in ClientHeadersFactory in Quarkus 2.2.x (and older versions). We may add such a feature in the near future.
Currently, you can #HeaderParam directly. Your code could probably look as follows:
Uni<String> token = tokenService.getToken();
token.onItem().transformToUni(tokenValue -> client.doTheCall(tokenValue));
Where the client interface would be something like:
#Path("/")
public interface MyClient {
#GET
Uni<Foo> doTheCall(#HeaderParam("token") String tokenValue);
}

Difference between Datafetchers and Resolvers

I am planning to implement Graphql in my spring boot application. I Googled many sites for Graphql server setup in Java and came across two ways of doing it .
One is implementing GraphQlResolver like below
public class MyResolver implements GraphQLResolver<ModelX>
and another one is by Implementing Datafetcher
Reference: https://www.graphql-java.com
#Component
public class MyDataFetcher implements DataFetcher<ModelX> {
#Override
public ModelX get(DataFetchingEnvironment environment) {
// TODO Auto-generated method stub
}
}
Please provide some information on differences in both the approaches and best among them
DataFetcher is from graphql-java library , the only GraphQL Java implementation that I known in Java world so far.
GraphQLResolver is from another library called graphql-java-tools which is built on top of graphql-java . You can think that it provides a way which allow you to build a GraphQL server in a more high level way or a way that you may find more convenient. At the end , GraphQLResolver will somehow invoke DataFetcher#get() for resolving the value for a field.
An similar analogy in Spring is that graphql-java like Servlet while graphql-java-tools like SpringMVC.
The term "resolver" is a general GraphQL term and is agnostic of any specific GraphQL implementation/framework/language. Each field in GraphQL is backed by a function called the resolver which is provided by the GraphQL server developer. In short, the resolver is the first logic hit to map any specific field to any specific response.
The Netflix DGS library is now open source (as of late 2020) and it introduced "DataFetchers". DataFetchers, in the DGS world, are simply a DGS-specific way of implementing resolvers.
Reading:
Netflix DGS Resolvers

How to generate Java client proxy for RESTful service implemented with Spring?

We use Spring to implement REST controller, for example:
#Controller
#RequestMapping("/myservice")
public class MyController {
#RequestMapping(value = "foo", method = RequestMethod.GET)
public #ResponseBody string foo() {...}
}
I can call this service using spring RestTemplate, and it works fine, but I would prefer to invoke it using a proxy, instead of typeless invocation using string url:
// client code:
MyController proxy = getProxy("baseUrl", MyController.class);
String results = proxy.foo();
So the input to proxy generation is java interface with annotations describing REST details.
I read this article and it looks like all types of remote calls do have proxies, and all I need for REST is something like RestProxyFactoryBean, that would take my REST java interface and return type-safe proxy that uses RestTemplate as implementation.
The closest solution I found is JBoss RESTEasy.
But it seems to use different set of annotations, so I am not sure it will work with annotations I already have: #Controller, #RequestMapping.
Are there other options, or RESTEasy is the only one?
Note, I am spring newbie so some obvious spring things are pretty new to me.
Thank you.
Dima
You can try Feign by Netflix, a lightweight proxy-based REST client. It works declaratively through annotations, and it's used by Spring Cloud projects to interact with Netflix Eureka.
One of the reasons the REST paradigm was invented was because expirience with other remoting technologies (RMI, CORBA, SOAP) shows us that often, the proxy-based approach creates more problems than it solves.
Theoretically, a proxy makes the fact that a function call is remote transparent to its users, so they can use the function exactly the same way as if it were a local function call.
In practice however this promise cannot be fulfilled, because remote function calls simply have other properties than local calls. Network outages, congestion, timeouts, load problems to name just a few. If you choose to ignore all these things that can go wrong with remote calls, your code probably won't be very stable.
TL;DR: You probably shouldn't work with a proxy, it's not state of the art any more. Just use RestTemplate.
Here is a project trying to generate runtime proxies from the controller annotations (using RestTemplate in the background to handle proxy calls): spring-rest-proxy-client Very early in implementation though.
This seems to do it: https://swagger.io/swagger-codegen/, and swagger has many other nice things for REST API.
Have a look at https://github.com/ggeorgovassilis/spring-rest-invoker.
All you need is to register FactoryBean:
#Configuration
public class MyConfiguration {
#Bean
SpringRestInvokerProxyFactoryBean BankService() {
SpringRestInvokerProxyFactoryBean proxyFactory = new SpringRestInvokerProxyFactoryBean();
proxyFactory.setBaseUrl("http://localhost/bankservice");
proxyFactory.setRemoteServiceInterfaceClass(BankService.class);
return proxyFactory;
}
and after that you can autowire the interface class:
#Autowired
BookService bookService;
I also ended up making my own library for this. I wanted something that is as small as possible, adds only itself to classpath and no transitive dependencies.
A client is created like:
final StoreApi storeApi = SpringRestTemplateClientBuilder
.create(StoreApi.class)
.setRestTemplate(restTemplate)
.setUrl(this.getMockUrl())
.build();
And rest-requests will be performed when invoking the methods:
storeApi.deleteOrder(1234L);
The is supports both method signatures:
ResponseEntity<X> deleteOrder(Long)
X deleteOrder(Long)

Best way to mock complex soap responses

I have a Java method I want to Unit test, but it requires a mocked SOAP response which contains multiple lists and layers of nodes. I am doing this with a handwritten mock i.e. just manually creating the objects and setting the values, but as the response is quite complex its a pain building up the response. I have a sample XML response is there an easy way of creating the mock using the XML?
Also I looked at Mockito and it looks fine for simple Objects, but it doesnt seem that good for complex responses (I may not be using it to its full potential).
The app stack is Java 1.6, Spring 3 and using JAX-WS.
I do something like this
#WebService
public class MyWebService {
#Autowired
private ServiceBean serviceBean;
public SomeReturedData getData(SomeInputData inputData) {
return serviceBean.getData(inputData);
}
}
For my UnitTest, I have a mock instanciation of "ServiceBean" which I inject in to #MyWebService, and "MyWebService" is deployed using the "in-vm" transport as described here
By Using the in-vm transport, All the XML marshalling/unmarshalling is still done by the web-service framework ,and you only have to deal with Java part.
Now someone might ask, why not test the "ServiceBean" directly, why the need to deply a WS using in-vm transport ? Well 2 things, Using in-vm transport you get to test that the JAXB XML marshalling/unmarshalling is working correctly, and it also allows you to test any intercepting handlers that you might have defined for your webservice.

JIRA Rest Service with Bandana Manager

I have a JIRA plugin that I'm developing that has a REST service. That service should be able to accept POSTed requests, unmarshall some data and store it. The seemingly suggested way to do this in JIRA is to make use of the Bandana persistence framework. According to this page, I should be able to simply define a setter that Spring should call to give me my Bandana manager.
#Path("/path")
public class SCMService {
private BandanaManager bandanaManager;
// setter called by Spring
public void setBandanaManager(BandanaManager bandanaManager) {
this.bandanaManager = bandanaManager;
}
//...More methods...
}
However, when I test this, the setter is never being called and my manager is null. I'm guessing this should be as simple as registering this service with Spring for injection somehow but I can't seem to find anything like that.
How would I get my setter called? Is there a better way to do this?
Er, I'm not sure that JIRA uses Bandana in that way, though Confluence does. You can certainly post data to a JIRA rest resource and then store it using properties tables
Something like this:
#POST
#Consumes (MediaType.APPLICATION_XML)
public Response createComponentAndIssues(#Context HttpServletRequest request, ...

Resources