diff --git a/README.md b/README.md index 6887dde..bfc5d44 100644 --- a/README.md +++ b/README.md @@ -6,16 +6,18 @@ An archetype Elide project using Spring Boot. ## Background -This project is the sample code for [Elide's Getting Started documentation](https://elide.io/pages/guide/01-start.html). +This project is the sample code for [Elide's Getting Started documentation](https://elide.io/pages/guide/v7/01-start.html). ## Install To build and run: 1. mvn clean install -2. java -jar target/elide-spring-boot-1.0.jar +2. java -jar target/elide-spring-boot-1.0.0.jar 3. Browse http://localhost:8080/ +Springdoc is accessible at http://localhost:8080/swagger-ui/index.html. + ## Docker and Containerize To containerize and run elide project locally @@ -71,10 +73,10 @@ To containerize and run elide project locally ## Usage -See [Elide's Getting Started documentation](https://elide.io/pages/guide/v5/01-start.html). +See [Elide's Getting Started documentation](https://elide.io/pages/guide/v7/01-start.html). ## Contribute -Please refer to [the contributing.md file](CONTRIBUTING.md) for information about how to get involved. We welcome issues, questions, and pull requests. +Please refer to the [CONTRIBUTING.md](CONTRIBUTING.md) file for information about how to get involved. We welcome issues, questions, and pull requests. ## License This project is licensed under the terms of the [Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0.html) open source license. diff --git a/pom.xml b/pom.xml index fdf8837..4aa2be7 100644 --- a/pom.xml +++ b/pom.xml @@ -10,37 +10,62 @@ Elide Spring Boot Example Elide Spring Boot Example example - 1.0 + 1.0.0 org.springframework.boot spring-boot-starter-parent - 3.0.5 + 3.1.0 elide-spring-boot 17 - 7.0.0-pr3 + 7.0.0-pr5 - 4.18.0 - 2.28.0 + 2.1.0 + 4.0.0 + 2.0 - 5.3.0 + + 5.0.0 3.0.0-M5 - + + + + jakarta.servlet + jakarta.servlet-api + ${jakarta.servlet-api.version} + + + + com.yahoo.elide + elide-bom + ${elide.version} + pom + import + + + + org.projectlombok lombok + + org.springdoc + springdoc-openapi-starter-webmvc-ui + ${springdoc.version} + + org.springframework.boot spring-boot-starter-security @@ -54,7 +79,6 @@ com.yahoo.elide elide-spring-boot-starter - ${elide.version} @@ -73,11 +97,6 @@ org.springframework.boot spring-boot-starter-jetty - - jakarta.servlet - jakarta.servlet-api - 5.0.0 - org.springframework.boot @@ -116,12 +135,12 @@ - net.rakugakibox.spring.boot + dev.akkinoc.spring.boot logback-access-spring-boot-starter - 2.7.1 + ${logback-access-spring-boot-starter.version} - + com.yahoo.elide elide-test-helpers @@ -165,6 +184,12 @@ junit-jupiter-engine test + + + org.springframework.boot + spring-boot-configuration-processor + true + diff --git a/src/main/java/example/App.java b/src/main/java/example/App.java index 2f8d6fd..5a2a715 100644 --- a/src/main/java/example/App.java +++ b/src/main/java/example/App.java @@ -10,12 +10,25 @@ import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.context.annotation.ImportRuntimeHints; +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.info.Info; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.security.SecurityScheme; +import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; + /** * Example app using elide-spring. */ @SpringBootApplication @EntityScan @ImportRuntimeHints(AppRuntimeHints.class) +@OpenAPIDefinition(info = @Info(title = "My Title"), security = @SecurityRequirement(name = "bearerAuth")) +@SecurityScheme( + name = "bearerAuth", + type = SecuritySchemeType.HTTP, + bearerFormat = "JWT", + scheme = "bearer" + ) public class App { public static void main(String[] args) throws Exception { SpringApplication.run(App.class, args); diff --git a/src/main/java/example/FilterConfiguration.java b/src/main/java/example/config/FilterConfiguration.java similarity index 97% rename from src/main/java/example/FilterConfiguration.java rename to src/main/java/example/config/FilterConfiguration.java index 53dd113..1b31c33 100644 --- a/src/main/java/example/FilterConfiguration.java +++ b/src/main/java/example/config/FilterConfiguration.java @@ -4,7 +4,7 @@ * See LICENSE file in project root for terms. */ -package example; +package example.config; import ch.qos.logback.access.servlet.TeeFilter; diff --git a/src/main/java/example/SecurityConfigProperties.java b/src/main/java/example/config/SecurityConfigProperties.java similarity index 81% rename from src/main/java/example/SecurityConfigProperties.java rename to src/main/java/example/config/SecurityConfigProperties.java index 45d4bd5..6b42380 100644 --- a/src/main/java/example/SecurityConfigProperties.java +++ b/src/main/java/example/config/SecurityConfigProperties.java @@ -4,14 +4,14 @@ * See LICENSE file in project root for terms. */ -package example; +package example.config; import org.springframework.boot.context.properties.ConfigurationProperties; import lombok.Data; @Data -@ConfigurationProperties(prefix = "security") +@ConfigurationProperties(prefix = "app.security") public class SecurityConfigProperties { private String origin = "*"; } diff --git a/src/main/java/example/SecurityConfiguration.java b/src/main/java/example/config/SecurityConfiguration.java similarity index 75% rename from src/main/java/example/SecurityConfiguration.java rename to src/main/java/example/config/SecurityConfiguration.java index 756b411..573741c 100644 --- a/src/main/java/example/SecurityConfiguration.java +++ b/src/main/java/example/config/SecurityConfiguration.java @@ -4,11 +4,14 @@ * See LICENSE file in project root for terms. */ -package example; +package example.config; + +import static org.springframework.security.config.Customizer.withDefaults; import java.time.Duration; import java.util.Arrays; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -23,17 +26,15 @@ */ @Configuration @EnableWebSecurity +@EnableConfigurationProperties(SecurityConfigProperties.class) public class SecurityConfiguration { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - http.cors() - .and() - .headers().frameOptions().sameOrigin() - .and() - .authorizeHttpRequests().anyRequest().permitAll() - .and() - .csrf().disable(); + http.cors(withDefaults()) + .headers(headers -> headers.frameOptions(frameOptions -> frameOptions.sameOrigin())) + .authorizeHttpRequests(authorizeHttpRequests -> authorizeHttpRequests.anyRequest().permitAll()) + .csrf(csrf -> csrf.disable()); return http.build(); } diff --git a/src/main/java/example/controllers/HelloController.java b/src/main/java/example/controllers/HelloController.java new file mode 100644 index 0000000..5fe4c54 --- /dev/null +++ b/src/main/java/example/controllers/HelloController.java @@ -0,0 +1,40 @@ +package example.controllers; + +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.tags.Tags; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Tags(value = { @Tag(name = "hello", description = "Say hello.") }) +@RestController +public class HelloController { + @Builder + @AllArgsConstructor + @Schema(title= "Hello", description = "The hello response.") + public static class HelloResource { + @Getter + private String text; + @Getter + private String language; + } + + @GetMapping(value = "/hello", produces = MediaType.APPLICATION_JSON_VALUE) + @ApiResponses( + @ApiResponse( + responseCode = "200", + content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, + schema = @Schema(implementation = HelloResource.class)))) + public ResponseEntity hello() { + return ResponseEntity.ok(HelloResource.builder().text("Hello").language("English").build()); + } +} diff --git a/src/main/java/example/models/ArtifactGroup.java b/src/main/java/example/models/ArtifactGroup.java index 919fb00..fcfd637 100644 --- a/src/main/java/example/models/ArtifactGroup.java +++ b/src/main/java/example/models/ArtifactGroup.java @@ -18,7 +18,7 @@ import java.util.ArrayList; import java.util.List; -@Include(name = "group") +@Include(name = "group", description = "Artifact group.", friendlyName = "Group") @Table(name = "artifactgroup") @Entity @Subscription diff --git a/src/main/java/example/models/ArtifactProduct.java b/src/main/java/example/models/ArtifactProduct.java index 1d83adf..aef39bc 100644 --- a/src/main/java/example/models/ArtifactProduct.java +++ b/src/main/java/example/models/ArtifactProduct.java @@ -15,7 +15,7 @@ import java.util.ArrayList; import java.util.List; -@Include(rootLevel = false, name = "product") +@Include(rootLevel = false, name = "product", description = "Artifact product.", friendlyName = "Product") @Table(name = "artifactproduct") @Entity public class ArtifactProduct { diff --git a/src/main/java/example/models/ArtifactVersion.java b/src/main/java/example/models/ArtifactVersion.java index d7296c5..e1d92c5 100644 --- a/src/main/java/example/models/ArtifactVersion.java +++ b/src/main/java/example/models/ArtifactVersion.java @@ -13,7 +13,7 @@ import jakarta.persistence.Table; import java.util.Date; -@Include(rootLevel = false, name = "version") +@Include(rootLevel = false, name = "version", description = "Artifact version.", friendlyName = "Version") @Table(name = "artifactversion") @Entity public class ArtifactVersion { diff --git a/src/main/java/example/models/v1/ArtifactGroupV1.java b/src/main/java/example/models/v1/ArtifactGroupV1.java new file mode 100644 index 0000000..f2057b1 --- /dev/null +++ b/src/main/java/example/models/v1/ArtifactGroupV1.java @@ -0,0 +1,39 @@ +/* + * Copyright 2019, Yahoo Inc. + * Licensed under the Apache License, Version 2.0 + * See LICENSE file in project root for terms. + */ +package example.models.v1; + +import com.yahoo.elide.annotation.Include; +import com.yahoo.elide.graphql.subscriptions.annotations.Subscription; +import com.yahoo.elide.graphql.subscriptions.annotations.SubscriptionField; + +import lombok.Data; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; +import java.util.ArrayList; +import java.util.List; + +@Include(name = "groupV1", description = "Artifact group.", friendlyName = "GroupV1") +@Table(name = "artifactgroup") +@Entity +@Subscription +@Data +public class ArtifactGroupV1 { + @Id + private String name = ""; + + @SubscriptionField + private String commonName = ""; + + @SubscriptionField + private String description = ""; + + @SubscriptionField + @OneToMany(mappedBy = "group") + private List products = new ArrayList<>(); +} diff --git a/src/main/java/example/models/v1/ArtifactProductV1.java b/src/main/java/example/models/v1/ArtifactProductV1.java new file mode 100644 index 0000000..1c22eaf --- /dev/null +++ b/src/main/java/example/models/v1/ArtifactProductV1.java @@ -0,0 +1,34 @@ +/* + * Copyright 2019, Yahoo Inc. + * Licensed under the Apache License, Version 2.0 + * See LICENSE file in project root for terms. + */ +package example.models.v1; + +import com.yahoo.elide.annotation.Include; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; +import java.util.ArrayList; +import java.util.List; + +@Include(rootLevel = false, name = "productV1", description = "Artifact product.", friendlyName = "ProductV1") +@Table(name = "artifactproduct") +@Entity +public class ArtifactProductV1 { + @Id + private String name = ""; + + private String commonName = ""; + + private String description = ""; + + @ManyToOne + private ArtifactGroupV1 group = null; + + @OneToMany(mappedBy = "artifact") + private List versions = new ArrayList<>(); +} diff --git a/src/main/java/example/models/v1/ArtifactVersionV1.java b/src/main/java/example/models/v1/ArtifactVersionV1.java new file mode 100644 index 0000000..71805b6 --- /dev/null +++ b/src/main/java/example/models/v1/ArtifactVersionV1.java @@ -0,0 +1,27 @@ +/* + * Copyright 2019, Yahoo Inc. + * Licensed under the Apache License, Version 2.0 + * See LICENSE file in project root for terms. + */ +package example.models.v1; + +import com.yahoo.elide.annotation.Include; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import java.util.Date; + +@Include(rootLevel = false, name = "versionV1", description = "Artifact version.", friendlyName = "VersionV1") +@Table(name = "artifactversion") +@Entity +public class ArtifactVersionV1 { + @Id + private String name = ""; + + private Date createdAt = new Date(); + + @ManyToOne + private ArtifactProductV1 artifact; +} diff --git a/src/main/java/example/models/v1/package-info.java b/src/main/java/example/models/v1/package-info.java new file mode 100644 index 0000000..dd872a9 --- /dev/null +++ b/src/main/java/example/models/v1/package-info.java @@ -0,0 +1,12 @@ +/* + * Copyright 2019, Yahoo Inc. + * Licensed under the Apache License, Version 2.0 + * See LICENSE file in project root for terms. + */ +/** + * Models Package V1. + */ +@ApiVersion(version = "1") +package example.models.v1; + +import com.yahoo.elide.annotation.ApiVersion; diff --git a/src/main/java/example/models/v2/ArtifactGroupV2.java b/src/main/java/example/models/v2/ArtifactGroupV2.java new file mode 100644 index 0000000..9f7076d --- /dev/null +++ b/src/main/java/example/models/v2/ArtifactGroupV2.java @@ -0,0 +1,27 @@ +/* + * Copyright 2019, Yahoo Inc. + * Licensed under the Apache License, Version 2.0 + * See LICENSE file in project root for terms. + */ + +package example.models.v2; + +import com.yahoo.elide.annotation.Include; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.Data; + +@Include(name = "groups", description = "Artifact group.", friendlyName = "Group") +@Entity +@Data +@Table(name = "artifactgroup") +public class ArtifactGroupV2 { + @Id + private String name = ""; + + @Column(name = "commonName") + private String title = ""; +} diff --git a/src/main/java/example/models/v2/package-info.java b/src/main/java/example/models/v2/package-info.java new file mode 100644 index 0000000..4247262 --- /dev/null +++ b/src/main/java/example/models/v2/package-info.java @@ -0,0 +1,12 @@ +/* + * Copyright 2019, Yahoo Inc. + * Licensed under the Apache License, Version 2.0 + * See LICENSE file in project root for terms. + */ +/** + * Models Package V2. + */ +@ApiVersion(version = "2") +package example.models.v2; + +import com.yahoo.elide.annotation.ApiVersion; diff --git a/src/main/resources/META-INF/resources/graphiql/index.html b/src/main/resources/META-INF/resources/graphiql/index.html index cae188e..e6b5e98 100644 --- a/src/main/resources/META-INF/resources/graphiql/index.html +++ b/src/main/resources/META-INF/resources/graphiql/index.html @@ -116,7 +116,7 @@ // In a PR preview, it connects to the Star Wars API externally. // Change this to point wherever you host your GraphQL server. const isDev = !window.location.hostname.match(/(^|\.)netlify\.com$|(^|\.)graphql\.org$/) - const api = '/graphql/api/v1'; + const api = '../graphql/api'; return fetch(api, { method: 'post', headers: { diff --git a/src/main/resources/META-INF/resources/index.html b/src/main/resources/META-INF/resources/index.html index a76e20d..1b52b6d 100644 --- a/src/main/resources/META-INF/resources/index.html +++ b/src/main/resources/META-INF/resources/index.html @@ -33,12 +33,12 @@ -