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
Related
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
There are two ways to expose HTTP endpoints in spring 5 now.
#Controller or #RestController by making the controller's class, e.g.
#RestController
#RequestMapping("persons")
public class PersonController {
#Autowired
private PersonRepo repo;
#GetMapping("/{id}")
public Mono<Person> personById(#PathVariable String id){
retrun repo.findById(id);
}
}
Route in #Configuration class by using RouterFunctions:
#Bean
public RouterFunction<ServerResponse> personRoute(PersonRepo repo) {
return route(GET("/persons/{id}"), req -> Mono.justOrEmpty(req.pathVariable("id"))
.flatMap(repo::getById)
.flatMap(p -> ok().syncBody(p))
.switchIfEmpty(notFound().build()));
}
Is there any performance difference in using anyone approach? Which one should I use when writing my application from scratch.
Programming Paradigm: Imperative vs Functional
In the case with the #Controller or #RestController annotations, we agree with the annotation-based model where we use annotations for mappings (and not only) and as a result side effects (that is not allowed in the functional world) to make our API works. Such side effects could be #Valid annotation that provides inbuilt bean validation for requests' bodies or #RequestMapping with the root path for the whole controller.
On the other hand, with the router functions, we get rid of annotations that consist of any side effects in terms of API implementation and delegate it directly to the functional chain: router -> handler. Those two are perfectly suited for building the basic reactive block: a sequence of events and two protagonists, a publisher and a subscriber to those events.
MVC Legacy: Servlets Stack vs Netty Stack
When we are talking about #Controller I would say that we usually will think in term of synchronous Java world: Servlets, ServletContext, ServletContainerInitializer, DispatcherServlet etc. Even if we will return Mono from a controller to make our application reactive we still will play in terms of Servlet 3.0 specification that supports java.nio.* and running on the same servlets containers such as Jetty or Tomcat. Subsequently, here we will use corresponding design patterns and approaches for building web apps.
RouterFunction on the other hand was inspired by the true reactive approach that originates from the async Java world - Netty and its Channel Model.
Subsequently new set of classes and their APIs for reactive environment emerged: ServerRequest, ServerResponse, WebFilter and others. As for me, they were designed by the Spring team in accordance with the previous years of maintaining the framework and understanding new web systems requirements. The name for those requirements is Reactive Manifesto.
Use Case
Recently my team faced the issue that it is impossible to integrate Swagger with RouterFucntion endpoints. It could upvote for #Controlers, but the Spring team introduced their solution - Spring REST Docs that could be easily connected to reactive WebTestClient. And I use here word 'connected' cause it follows true reactive meaning behind: instead of Swagger with its overloaded configurations and side-effect annotations, you easily could build your API docs in tests without touching your working code at all.
Update 2020: Despite since now Spring Webflux already could be integrated with Swagger subsequently using OpenAPI specification, it still lacks configuration simplicity and transparency that, in my humble opinion, is the consequence of being a part of the archaic MVC approach.
Closure (opinion)
Cause of no performance impact it's likely to hear something similar to 'it is absolutely based on individual preference what to use'. And I agree that it's individual preference indeed among two options: moving forward or moving backwards when you let yourself stay in the same domain for a decade. I think that reactive support for #Controller was done by the Spring team to make it possible for old projects to somehow be in tune with requirements of time and have at least the opportunity for the migration.
If you are going to create a web application from scratch then do not hesitate and use the introduced reactive stack.
Though it's a bit late, but this may be useful for future readers.
By switching to a functional route declaration:
you maintain all routing configuration in one place
you get almost the same flexibility as the usual annotation-based approach in terms of accessing incoming request parameters, path variables, and other important components of the request
you get an ability to avoid the whole Spring Framework infrastructure being run which may decrease the bootstrapping time of the application
Regarding point 3, there are some cases where the whole functionality(IoC, annotation processing, autoconfiguration) of the Spring ecosystem may be redundant, therefore decreasing the overall startup time of the application.
In the era of tiny microservices, Amazon Lambdas, and similar cloud services, it is important to offer functionality that allows developers to create lightweight applications that have almost the same arsenal of framework features. This is why the Spring Framework team decided to incorporate this feature into the WebFlux module.
The new functional web framework allows you to build a web application without starting the whole Spring infrastructure. The main method in that case should be somewhat like the following(note, there is no #SpringBootApplication annotation)
class StandaloneApplication {
public static void main(String[] args) {
HttpHandler httpHandler = RouterFunctions.toHttpHandler(
routes(new BCryptPasswordEncoder(18))
);
ReactorHttpHandlerAdapter reactorHttpHandler = new ReactorHttpHandlerAdapter(httpHandler);
HttpServer.create()
.port(8080)
.handle(reactorHttpHandler)
.bind()
.flatMap(DisposableChannel::onDispose)
.block();
}
static RouterFunction<ServerResponse> routes(PasswordEncoder passwordEncoder ) {
return
route(
POST("/check"),
request -> request
.bodyToMono(PasswordDTO.class)
.map(p -> passwordEncoder
.matches(p.getRaw(), p.getSecured()))
.flatMap(isMatched -> isMatched
? ServerResponse
.ok()
.build()
: ServerResponse
.status(HttpStatus.EXPECTATION_FAILED)
.build()
)
);
}
}
I had was to expose the primary key which is annotated with #Id in entity.the ID field is only visible on the resource path, but not on the JSON body.
You can configure this using the RepositoryRestConfigurerAdapter on entity level.
#Configuration
public class ExposeEntityIdRestConfiguration extends RepositoryRestConfigurerAdapter {
#Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.exposeIdsFor(MyEntity.class);
}
}
Be aware that using this you are working against the principles of spring-data-rest - sdr promotes hypermedia to be able to use an API by navigating between resources using links - here your resources are identified and referenced by links and thus the ids are not needed anymore. Using ids on your client pushes the complexity of constructing links to resources to the client. And the client should not be bothered with this knowledge.
The best solution would be not to using the IDs of your entities, and use the link references the hypermedia provides.
You just need to parse your JSON accordingly to the HAL specification used by Spring Data Rest.
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)
I am trying to put a "Contract" on a method call. My web application is in Spring 3.
Is writing customs Annotations the right way to go. If so, any pointers( I didn't find anything in spring reference docs).
Should I use tools like "Modern Jass", JML ...? Again any pointers will be useful.
Thanks
Using Spring EL and Spring security could get you most of the way. Spring security defines the #PreAuthorize annotation which is fired before method invocation and allows you to use Spring 3's new expression engine, such as:
#PreAuthorize("#customerId > 0")
public Customer getCustomer(int customerId) { .. }
or far more advanced rules like the following which ensures that the passed user does not have role ADMIN.
#PreAuthorize("#user.role != T(com.company.Role).ADMIN)")
public void saveUser(User user) { .. }
You can also provide default values for your contract with the #Value annotation
public Customer getCustomer(#Value("#{434}") int customerId) { .. }
You can even reference system properties in your value expressions.
Setting up Spring security for this purpose is not to hard as you can just create a UserDetailsService that grants some default role to all users. Alternatively you could make you own custom Spring aspect and then let this use the SpelExpressionParser to check method values.
if you don't mind writing some parts of your Java web application in Groovy (which is possible with Spring) I would suggest using GContracts.
GContracts is a Design by Contract (tm) library entirely written in Java - without any dependencies to other libraries - and has full support for class invariants, pre- and postconditions and inheritance of those assertions.
Contracts for Java which is based on Modern Jass is one way to write contracts.
http://code.google.com/p/cofoja/
As per the writing of this reply, this is pretty basic. Hopefully this will improve as we go on.
I didn't find an ideal solution to this, interestingly it is a planned feature for the Spring framework (2.0 implemented patch):
http://jira.springframework.org/browse/SPR-2698
The best thing I suggest to use JSR 303 which is for bean validation. AFAIK there are two implementations for this:
Agimatec Validations
Hibernate Validator
There's a guide here for integrating it into Spring, I haven't followed it through but it looks ok:
http://blog.jteam.nl/2009/08/04/bean-validation-integrating-jsr-303-with-spring/
I personally recommend C4J for 2 reasons:
It has Eclipse plugin so you don't need to manually configure it.
The documentation is written in a clear, structured format so you can easily use it.
Her's the link to C4J