View Javadoc
1   package net.sumaris.server.http.graphql;
2   
3   /*-
4    * #%L
5    * SUMARiS:: Server
6    * %%
7    * Copyright (C) 2018 SUMARiS Consortium
8    * %%
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU General Public License as
11   * published by the Free Software Foundation, either version 3 of the
12   * License, or (at your option) any later version.
13   * 
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Public License for more details.
18   * 
19   * You should have received a copy of the GNU General Public
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/gpl-3.0.html>.
22   * #L%
23   */
24  
25  import com.fasterxml.jackson.databind.ObjectMapper;
26  import graphql.GraphQL;
27  import graphql.schema.GraphQLSchema;
28  import io.leangen.graphql.GraphQLSchemaGenerator;
29  import io.leangen.graphql.metadata.strategy.query.AnnotatedResolverBuilder;
30  import io.leangen.graphql.metadata.strategy.value.jackson.JacksonValueMapperFactory;
31  import net.sumaris.core.dao.technical.model.IEntity;
32  import net.sumaris.server.http.graphql.administration.AdministrationGraphQLService;
33  import net.sumaris.server.http.graphql.administration.ProgramGraphQLService;
34  import net.sumaris.server.http.graphql.data.DataGraphQLService;
35  import net.sumaris.server.http.graphql.extraction.AggregationGraphQLService;
36  import net.sumaris.server.http.graphql.extraction.ExtractionGraphQLService;
37  import net.sumaris.server.http.graphql.referential.ReferentialGraphQLService;
38  import net.sumaris.server.http.graphql.security.AuthGraphQLService;
39  import net.sumaris.server.http.graphql.technical.ConfigurationGraphQLService;
40  import net.sumaris.server.http.graphql.technical.DefaultTypeTransformer;
41  import org.slf4j.Logger;
42  import org.slf4j.LoggerFactory;
43  import org.springframework.beans.factory.annotation.Autowired;
44  import org.springframework.context.annotation.Bean;
45  import org.springframework.context.annotation.Configuration;
46  import org.springframework.web.socket.WebSocketHandler;
47  import org.springframework.web.socket.config.annotation.EnableWebSocket;
48  import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
49  import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
50  import org.springframework.web.socket.handler.PerConnectionWebSocketHandler;
51  
52  import java.io.Serializable;
53  
54  @Configuration
55  @EnableWebSocket
56  public class GraphQLConfiguration implements WebSocketConfigurer {
57  
58      private static final Logger log = LoggerFactory.getLogger(GraphQLConfiguration.class);
59  
60      @Autowired
61      private AdministrationGraphQLService administrationService;
62  
63      @Autowired
64      private ProgramGraphQLService programService;
65  
66      @Autowired
67      private ConfigurationGraphQLService podConfigurationService;
68  
69      @Autowired
70      private DataGraphQLService dataService;
71  
72      @Autowired
73      private ReferentialGraphQLService referentialService;
74  
75      @Autowired
76      private ExtractionGraphQLService extractionGraphQLService;
77  
78      @Autowired
79      private AggregationGraphQLService aggregationGraphQLService;
80  
81      @Autowired
82      private AuthGraphQLService authGraphQLService;
83  
84      @Autowired
85      private ObjectMapper objectMapper;
86  
87      @Bean
88      public GraphQLSchema graphQLSchema() {
89  
90          log.info("Generating GraphQL schema (using SPQR)...");
91  
92          return new GraphQLSchemaGenerator()
93                  .withResolverBuilders(new AnnotatedResolverBuilder())
94                  .withOperationsFromSingleton(administrationService, AdministrationGraphQLService.class)
95                  .withOperationsFromSingleton(programService, ProgramGraphQLService.class)
96                  .withOperationsFromSingleton(dataService, DataGraphQLService.class)
97                  .withOperationsFromSingleton(referentialService, ReferentialGraphQLService.class)
98                  .withOperationsFromSingleton(authGraphQLService, AuthGraphQLService.class)
99                  .withOperationsFromSingleton(extractionGraphQLService, ExtractionGraphQLService.class)
100                 .withOperationsFromSingleton(aggregationGraphQLService, AggregationGraphQLService.class)
101                 .withOperationsFromSingleton(podConfigurationService, ConfigurationGraphQLService.class)
102 
103 
104                 .withTypeTransformer(new DefaultTypeTransformer(false, true)
105                         // Replace unbounded IEntity<ID> with IEntity<Serializable>
106                         .addUnboundedReplacement(IEntity.class, Serializable.class))
107 
108                 .withValueMapperFactory(new JacksonValueMapperFactory.Builder()
109                         .withPrototype(objectMapper)
110                         .build())
111                 .generate();
112     }
113 
114     @Bean
115     public GraphQL graphQL() {
116         return GraphQL.newGraphQL(graphQLSchema()).build();
117     }
118 
119 
120     @Override
121     public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
122 
123         log.info(String.format("Starting GraphQL websocket handler at {%s}...", GraphQLPaths.SUBSCRIPTION_PATH));
124 
125         webSocketHandlerRegistry
126                 .addHandler(webSocketHandler(), GraphQLPaths.BASE_PATH)
127                 .setAllowedOrigins("*")
128                 .withSockJS();
129     }
130 
131     @Bean
132     public WebSocketHandler webSocketHandler() {
133         return new PerConnectionWebSocketHandler(SubscriptionWebSocketHandler.class);
134     }
135 }
136