From a73bf3ce7bbb5acaf693a54e53cd5e28e9b1947f Mon Sep 17 00:00:00 2001 From: Tim Middleton Date: Mon, 27 Jan 2025 11:06:14 +0800 Subject: [PATCH] addition work on templates --- go.mod | 4 +- pkg/cmd/root.go | 3 +- pkg/cmd/starter.go | 215 ++++++++++++++++++ templates/helidon/pom.xml | 123 ++++++++++ .../demo/frameworks/helidon/Customer.java | 86 +++++++ .../frameworks/helidon/CustomerResource.java | 65 ++++++ .../src/main/resources/META-INF/beans.xml | 15 ++ .../META-INF/helidon/serial-config.properties | 17 ++ .../META-INF/microprofile-config.properties | 15 ++ .../src/main/resources/logging.properties | 25 ++ templates/micronaut/pom.xml | 176 ++++++++++++++ .../frameworks/micronaut/Application.java | 21 ++ .../demo/frameworks/micronaut/Customer.java | 85 +++++++ .../micronaut/rest/ApplicationController.java | 60 +++++ .../src/main/resources/application.yml | 28 +++ .../micronaut/src/main/resources/logback.xml | 23 ++ templates/springboot/pom.xml | 86 +++++++ .../demo/frameworks/springboot/Customer.java | 86 +++++++ .../springboot/DemoApplication.java | 19 ++ .../springboot/controller/DemoController.java | 58 +++++ .../src/main/resources/application.properties | 14 ++ templates/template.yaml | 68 ++++++ 22 files changed, 1289 insertions(+), 3 deletions(-) create mode 100644 pkg/cmd/starter.go create mode 100644 templates/helidon/pom.xml create mode 100644 templates/helidon/src/main/java/com/oracle/coherence/demo/frameworks/helidon/Customer.java create mode 100644 templates/helidon/src/main/java/com/oracle/coherence/demo/frameworks/helidon/CustomerResource.java create mode 100644 templates/helidon/src/main/resources/META-INF/beans.xml create mode 100644 templates/helidon/src/main/resources/META-INF/helidon/serial-config.properties create mode 100644 templates/helidon/src/main/resources/META-INF/microprofile-config.properties create mode 100644 templates/helidon/src/main/resources/logging.properties create mode 100644 templates/micronaut/pom.xml create mode 100644 templates/micronaut/src/main/java/com/oracle/coherence/demo/frameworks/micronaut/Application.java create mode 100644 templates/micronaut/src/main/java/com/oracle/coherence/demo/frameworks/micronaut/Customer.java create mode 100644 templates/micronaut/src/main/java/com/oracle/coherence/demo/frameworks/micronaut/rest/ApplicationController.java create mode 100644 templates/micronaut/src/main/resources/application.yml create mode 100644 templates/micronaut/src/main/resources/logback.xml create mode 100644 templates/springboot/pom.xml create mode 100644 templates/springboot/src/main/java/com/oracle/coherence/demo/frameworks/springboot/Customer.java create mode 100644 templates/springboot/src/main/java/com/oracle/coherence/demo/frameworks/springboot/DemoApplication.java create mode 100644 templates/springboot/src/main/java/com/oracle/coherence/demo/frameworks/springboot/controller/DemoController.java create mode 100644 templates/springboot/src/main/resources/application.properties create mode 100644 templates/template.yaml diff --git a/go.mod b/go.mod index 46f3e7f..bd72d60 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -// Copyright (c) 2021, 2024 Oracle and/or its affiliates. +// Copyright (c) 2021, 2025 Oracle and/or its affiliates. // Licensed under the Universal Permissive License v 1.0 as shown at // https://oss.oracle.com/licenses/upl. // @@ -17,6 +17,7 @@ require ( go.uber.org/zap v1.27.0 golang.org/x/term v0.27.0 golang.org/x/text v0.21.0 + gopkg.in/yaml.v3 v3.0.1 ) require ( @@ -45,5 +46,4 @@ require ( golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/pkg/cmd/root.go b/pkg/cmd/root.go index ee62640..883db1d 100644 --- a/pkg/cmd/root.go +++ b/pkg/cmd/root.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024 Oracle and/or its affiliates. + * Copyright (c) 2021, 2025 Oracle and/or its affiliates. * Licensed under the Universal Permissive License v 1.0 as shown at * https://oss.oracle.com/licenses/upl. */ @@ -672,6 +672,7 @@ func Initialize(command *cobra.Command) *cobra.Command { command.AddCommand(createCmd) createCmd.AddCommand(createSnapshotCmd) createCmd.AddCommand(createClusterCmd) + createCmd.AddCommand(createStarterCmd) // recover command.AddCommand(recoverCmd) diff --git a/pkg/cmd/starter.go b/pkg/cmd/starter.go new file mode 100644 index 0000000..660b081 --- /dev/null +++ b/pkg/cmd/starter.go @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2025 Oracle and/or its affiliates. + * Licensed under the Universal Permissive License v 1.0 as shown at + * https://oss.oracle.com/licenses/upl. + */ + +package cmd + +import ( + "fmt" + "github.com/oracle/coherence-cli/pkg/utils" + "github.com/spf13/cobra" + "gopkg.in/yaml.v3" + "os" + "path/filepath" +) + +const ( + framework = "framework" + frameworkURL = "https://raw.githubusercontent.com/oracle/coherence-cli/refs/heads/template/templates" + frameworkTypesURL = "https://raw.githubusercontent.com/oracle/coherence-cli/refs/heads/template/templates/template.yaml" +) + +// FrameworkTemplate contains the contents read from the coherence-cli repository. +type FrameworkTemplate struct { + Name string `yaml:"name"` + FrameworkVersion string `yaml:"frameworkVersion"` + Instructions string `yaml:"instructions"` + Files []string `yaml:"files"` +} + +type Templates struct { + Templates []FrameworkTemplate `yaml:"templates"` +} + +var ( + frameworkTypeParam string + validFrameworks = []string{"helidon", "springboot", "micronaut"} + + commonInstructions = ` +Add a customer: + curl -X POST -H "Content-Type: application/json" -d '{"id": 1, "name": "Tim", "balance": 1000}' http://localhost:8080/api/customers + +Get a customer: + curl -s http://localhost:8080/api/customers/1 + +Get all customers: + curl -s http://localhost:8080/api/customers + +Delete a customer: + curl -X DELETE http://localhost:8080/api/customers/1 +` +) + +// createStarterCmd represents the create starter command. +var createStarterCmd = &cobra.Command{ + Use: "starter project-name", + Short: "creates a starter project for Coherence", + Long: `The 'create starter' command creates a starter Maven project to use Coherence +with various frameworks including Helidon, Spring Boot and Micronaut. A directory +will be created off the current directory with the same name as the project name.`, + Args: func(cmd *cobra.Command, args []string) error { + if len(args) != 1 { + displayErrorAndExit(cmd, "you must provide a project name") + } + return nil + }, + RunE: func(cmd *cobra.Command, args []string) error { + var ( + projectName = args[0] + err error + ) + + // the project name will be used as the directory off the current directory, validate it + if utils.SanitizeSnapshotName(projectName) != projectName { + return fmt.Errorf("invalid project name: %s", projectName) + } + + // validate the framework + if !utils.SliceContains(validFrameworks, frameworkTypeParam) { + return fmt.Errorf("framework must be one of %v", validFrameworks) + } + + // check the directory does not exist + if utils.DirectoryExists(projectName) { + return fmt.Errorf("the directory %s already exists", projectName) + } + + cmd.Printf("checking for availability of template %v...\n", frameworkTypeParam) + + // load the template files + templates, err := loadTemplateFiles() + if err != nil { + return err + } + + // get the template for the framework + template := getTemplate(templates, frameworkTypeParam) + + if template == nil { + return fmt.Errorf("unable to find files for framework %s", frameworkTypeParam) + } + + absolutePath, err := filepath.Abs(projectName) + if err != nil { + return fmt.Errorf("unable to get absolute path for directory %s: %w", projectName, err) + } + + cmd.Println("\nCreate Starter Project") + cmd.Printf("Project Name: %s\n", projectName) + cmd.Printf("Framework Type: %s\n", frameworkTypeParam) + cmd.Printf("Framework Versions: %s\n", template.FrameworkVersion) + cmd.Printf("Project Path %s\n\n", absolutePath) + + // confirm the operation + if !confirmOperation(cmd, "Are you sure you want to create the starter project above? (y/n) ") { + return nil + } + + return initProject(cmd, template, projectName, absolutePath) + }, +} + +func initProject(cmd *cobra.Command, template *FrameworkTemplate, projectName string, absolutePath string) error { + var err error + + // create the directory + if err = utils.EnsureDirectory(projectName); err != nil { + return err + } + + err = saveFiles(template.Files, projectName, template.Name) + if err != nil { + return err + } + + // output instructions for the framework + cmd.Printf("\nYour %s template project has been saved to %s\n", template.Name, absolutePath) + + // get framework instructions + instructions := template.Instructions + + cmd.Printf("\nPlease see the file %s/readme.txt for instructions\n\n", projectName) + return writeContentToFile(projectName, "readme.txt", instructions+commonInstructions) +} + +func loadTemplateFiles() (*Templates, error) { + var templates Templates + + response, err := GetURLContents(frameworkTypesURL) + if err != nil { + return nil, err + } + + err = yaml.Unmarshal(response, &templates) + if err != nil { + return nil, fmt.Errorf("unable to unmarshal %v, %v", frameworkTypesURL, err) + } + + return &templates, nil +} + +func getTemplate(templates *Templates, framework string) *FrameworkTemplate { + for _, template := range templates.Templates { + if template.Name == framework { + return &template + } + } + return nil +} + +func saveFiles(fileList []string, baseDir string, frameworkType string) error { + for _, file := range fileList { + url := fmt.Sprintf("%s/%s/%s", frameworkURL, frameworkType, file) + + // Get the file contents + response, err := GetURLContents(url) + if err != nil { + return fmt.Errorf("error downloading file %s: %w", file, err) + } + + // Construct the full destination path + destPath := filepath.Join(baseDir, file) + + destDir := filepath.Dir(destPath) + if err = os.MkdirAll(destDir, os.ModePerm); err != nil { + return fmt.Errorf("error creating directory %s: %w", destDir, err) + } + + // Write the file contents to the destination + if err = os.WriteFile(destPath, response, 0600); err != nil { + return fmt.Errorf("error writing file %s: %w", destPath, err) + } + } + + return nil +} + +func writeContentToFile(baseDir, fileName, content string) error { + filePath := filepath.Join(baseDir, fileName) + + // Write the content to the file + err := os.WriteFile(filePath, []byte(content), 0600) + if err != nil { + return fmt.Errorf("failed to write to file %s: %w", filePath, err) + } + + return nil +} + +func init() { + createStarterCmd.Flags().StringVarP(&frameworkTypeParam, framework, "f", "", "the framework to create for: helidon, springboot or micronaut") + _ = createStarterCmd.MarkFlagRequired(framework) + createStarterCmd.Flags().BoolVarP(&automaticallyConfirm, "yes", "y", false, confirmOptionMessage) +} diff --git a/templates/helidon/pom.xml b/templates/helidon/pom.xml new file mode 100644 index 0000000..852033f --- /dev/null +++ b/templates/helidon/pom.xml @@ -0,0 +1,123 @@ + + + + 4.0.0 + + io.helidon.applications + helidon-mp + 4.1.6 + + + + com.oracle.coherence.demo.frameworks + helidon + 1.0-SNAPSHOT + Demo project for Helidon and Coherence + + + com.oracle.coherence.ce + 24.09 + 2.18.2 + 21 + + + + + + io.helidon.microprofile.bundles + helidon-microprofile-core + + + + jakarta.json.bind + jakarta.json.bind-api + + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson.version} + + + + org.glassfish.jersey.media + jersey-media-json-binding + runtime + + + + io.helidon.logging + helidon-logging-jul + runtime + + + + + ${coherence.group.id} + ${coherence.version} + coherence + + + ${coherence.group.id} + ${coherence.version} + coherence-cdi-server + + + ${coherence.group.id} + ${coherence.version} + coherence-mp-config + + + ${coherence.group.id} + ${coherence.version} + coherence-json + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-libs + + + + + + ${coherence.group.id} + ${coherence.version} + pof-maven-plugin + + + instrument + + instrument + + + + instrument-tests + + instrument-tests + + + + + + + diff --git a/templates/helidon/src/main/java/com/oracle/coherence/demo/frameworks/helidon/Customer.java b/templates/helidon/src/main/java/com/oracle/coherence/demo/frameworks/helidon/Customer.java new file mode 100644 index 0000000..9579d7f --- /dev/null +++ b/templates/helidon/src/main/java/com/oracle/coherence/demo/frameworks/helidon/Customer.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2024, 2025 Oracle and/or its affiliates. + * Licensed under the Universal Permissive License v 1.0 as shown at + * https://oss.oracle.com/licenses/upl. + */ + +package com.oracle.coherence.demo.frameworks.helidon; + +import java.util.Objects; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.tangosol.io.pof.schema.annotation.PortableType; + +@PortableType(id = 1000) +@JsonIgnoreProperties(value = { "evolvable", "evolvableHolder", "empty" }) +public class Customer { + @JsonProperty("id") + private int id; + + @JsonProperty("name") + private String name; + + @JsonProperty("balance") + private double balance; + + public Customer() {} + + public Customer(int id, String name, double balance) { + this.id = id; + this.name = name; + this.balance = balance; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public double getBalance() { + return balance; + } + + public void setBalance(double balance) { + this.balance = balance; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Customer customer = (Customer) o; + return id == customer.id && Double.compare(balance, customer.balance) == 0 && + Objects.equals(name, customer.name); + } + + @Override + public int hashCode() { + int result = id; + result = 31 * result + Objects.hashCode(name); + result = 31 * result + Double.hashCode(balance); + return result; + } + + @Override + public String toString() { + return "Customer{" + + "id=" + id + + ", name='" + name + '\'' + + ", balance=" + balance + + '}'; + } +} diff --git a/templates/helidon/src/main/java/com/oracle/coherence/demo/frameworks/helidon/CustomerResource.java b/templates/helidon/src/main/java/com/oracle/coherence/demo/frameworks/helidon/CustomerResource.java new file mode 100644 index 0000000..90f996a --- /dev/null +++ b/templates/helidon/src/main/java/com/oracle/coherence/demo/frameworks/helidon/CustomerResource.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2024, 2025 Oracle and/or its affiliates. + * Licensed under the Universal Permissive License v 1.0 as shown at + * https://oss.oracle.com/licenses/upl. + */ + +package com.oracle.coherence.demo.frameworks.helidon; + +import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; + +import com.oracle.coherence.cdi.Name; + +import com.tangosol.net.NamedMap; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.DELETE; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; + +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.Response; + +@Path("/api/customers") +@ApplicationScoped +public class CustomerResource { + + @Inject + @Name("tasks") + private NamedMap customers; + + @POST + @Consumes(APPLICATION_JSON) + public Response createCustomer(Customer customer) { + customers.put(customer.getId(), customer); + return Response.accepted(customer).build(); + } + + @GET + @Produces(APPLICATION_JSON) + public Response getCustomers() { + return Response.ok(customers.values()).build(); + } + + @GET + @Path("{id}") + @Produces(APPLICATION_JSON) + public Response getTask(@PathParam("id") int id) { + Customer customer = customers.get(id); + + return customer == null ? Response.status(Response.Status.NOT_FOUND).build() : Response.ok(customer).build(); + } + + @DELETE + @Path("{id}") + @Produces(APPLICATION_JSON) + public Response deleteTask(@PathParam("id") int id) { + Customer oldCustomer = customers.remove(id); + return oldCustomer == null ? Response.status(Response.Status.NOT_FOUND).build() : Response.ok(oldCustomer).build(); + } +} diff --git a/templates/helidon/src/main/resources/META-INF/beans.xml b/templates/helidon/src/main/resources/META-INF/beans.xml new file mode 100644 index 0000000..711dcac --- /dev/null +++ b/templates/helidon/src/main/resources/META-INF/beans.xml @@ -0,0 +1,15 @@ + + + + \ No newline at end of file diff --git a/templates/helidon/src/main/resources/META-INF/helidon/serial-config.properties b/templates/helidon/src/main/resources/META-INF/helidon/serial-config.properties new file mode 100644 index 0000000..14261c5 --- /dev/null +++ b/templates/helidon/src/main/resources/META-INF/helidon/serial-config.properties @@ -0,0 +1,17 @@ +# +# Copyright (c) 2025, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at +# https://oss.oracle.com/licenses/upl. +# + +pattern=com.tangosol.**;\ + com.oracle.coherence.**;\ + java.io.**;java.lang.**;\ + java.util.**;\ + java.math.**;\ + javax.management.**;\ + java.net.Inet6Address;\ + java.net.**;\ + oracle.sql.converter.*;\ + oracle.i18n.text.converter.*;\ + java.rmi.* \ No newline at end of file diff --git a/templates/helidon/src/main/resources/META-INF/microprofile-config.properties b/templates/helidon/src/main/resources/META-INF/microprofile-config.properties new file mode 100644 index 0000000..e35588c --- /dev/null +++ b/templates/helidon/src/main/resources/META-INF/microprofile-config.properties @@ -0,0 +1,15 @@ +# +# Copyright (c) 2025 Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at +# https://oss.oracle.com/licenses/upl. +# + +## Microprofile server properties +server.port=8080 +server.host=0.0.0.0 +# Coherence system properties +coherence.pof.enabled=true +coherence.wka=127.0.0.1 +coherence.ttl=0 +coherence.management.http=all +coherence.management=all diff --git a/templates/helidon/src/main/resources/logging.properties b/templates/helidon/src/main/resources/logging.properties new file mode 100644 index 0000000..3a55005 --- /dev/null +++ b/templates/helidon/src/main/resources/logging.properties @@ -0,0 +1,25 @@ +# +# Copyright (c) 2025, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at +# https://oss.oracle.com/licenses/upl. +# + +# Example Logging Configuration File +# For more information see $JAVA_HOME/jre/lib/logging.properties + +# Send messages to the console +handlers=io.helidon.logging.jul.HelidonConsoleHandler + +# HelidonConsoleHandler uses a SimpleFormatter subclass that replaces "!thread!" with the current thread +java.util.logging.SimpleFormatter.format=%1$tY.%1$tm.%1$td %1$tH:%1$tM:%1$tS %4$s %3$s !thread!: %5$s%6$s%n + +# Global logging level. Can be overridden by specific loggers +.level=INFO + +# Quiet Weld +org.jboss.level=WARNING + +# Component specific log levels +#io.helidon.config.level=INFO +#io.helidon.security.level=INFO +#io.helidon.common.level=INFO diff --git a/templates/micronaut/pom.xml b/templates/micronaut/pom.xml new file mode 100644 index 0000000..69839c7 --- /dev/null +++ b/templates/micronaut/pom.xml @@ -0,0 +1,176 @@ + + + + 4.0.0 + + + io.micronaut.platform + micronaut-parent + 4.7.3 + + + + com.oracle.coherence.demo.frameworks + micronaut + 1.0-SNAPSHOT + Demo project for Helidon and Coherence + + + com.oracle.coherence.ce + 24.09 + 2.18.2 + 21 + + + netty + ${project.parent.version} + 4.3.0 + + + 5.0.4 + + + 3.0 + 1.5.12 + 4.1.115.Final + 2.4.1 + + + 3.13.0 + 4.7.1 + + com.oracle.coherence.demo.frameworks.micronaut.Application + + + + + + + ${coherence.group.id} + coherence + ${coherence.version} + + + ${coherence.group.id} + coherence-json + ${coherence.version} + + + io.micronaut.coherence + micronaut-coherence + ${micronaut.coherence.version} + + + + + io.micronaut + micronaut-jackson-databind + + + io.micronaut + micronaut-http-server-netty + + + netty-common + io.netty + + + + + + io.micronaut + micronaut-runtime + + + + org.yaml + snakeyaml + runtime + + + + + + netty-common + io.netty + ${netty.version} + + + + + ch.qos.logback + logback-classic + ${logback.version} + runtime + + + ch.qos.logback + logback-core + ${logback.version} + runtime + + + + org.fusesource.jansi + jansi + ${jansi.version} + + + + + + + + io.micronaut.maven + micronaut-maven-plugin + ${plugin.micronaut.version} + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${plugin.compiler.version} + + + + + org.apache.maven.plugins + maven-shade-plugin + + true + + + + + ${coherence.group.id} + pof-maven-plugin + ${coherence.version} + + + instrument + + instrument + + + + instrument-tests + + instrument-tests + + + + + + + diff --git a/templates/micronaut/src/main/java/com/oracle/coherence/demo/frameworks/micronaut/Application.java b/templates/micronaut/src/main/java/com/oracle/coherence/demo/frameworks/micronaut/Application.java new file mode 100644 index 0000000..3009d6e --- /dev/null +++ b/templates/micronaut/src/main/java/com/oracle/coherence/demo/frameworks/micronaut/Application.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Oracle and/or its affiliates. + * Licensed under the Universal Permissive License v 1.0 as shown at + * https://oss.oracle.com/licenses/upl. + */ + + +package com.oracle.coherence.demo.frameworks.micronaut; + +import io.micronaut.runtime.Micronaut; + +/** + * {@code Micronaut} entry point. + */ +public class Application + { + public static void main(String[] args) + { + Micronaut.run(Application.class, args); + } + } diff --git a/templates/micronaut/src/main/java/com/oracle/coherence/demo/frameworks/micronaut/Customer.java b/templates/micronaut/src/main/java/com/oracle/coherence/demo/frameworks/micronaut/Customer.java new file mode 100644 index 0000000..39bf9ce --- /dev/null +++ b/templates/micronaut/src/main/java/com/oracle/coherence/demo/frameworks/micronaut/Customer.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2025 Oracle and/or its affiliates. + * Licensed under the Universal Permissive License v 1.0 as shown at + * https://oss.oracle.com/licenses/upl. + */ + +package com.oracle.coherence.demo.frameworks.micronaut; + +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.tangosol.io.pof.schema.annotation.PortableType; + +@PortableType(id = 1000) +@JsonIgnoreProperties(value = { "evolvable", "evolvableHolder", "empty" }) +public class Customer { + @JsonProperty("id") + private int id; + + @JsonProperty("name") + private String name; + + @JsonProperty("balance") + private double balance; + + public Customer() {} + + public Customer(int id, String name, double balance) { + this.id = id; + this.name = name; + this.balance = balance; + } + + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public double getBalance() { + return balance; + } + + public void setBalance(double balance) { + this.balance = balance; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Customer customer = (Customer) o; + return id == customer.id && Double.compare(balance, customer.balance) == 0 && + Objects.equals(name, customer.name); + } + + @Override + public int hashCode() { + int result = id; + result = 31 * result + Objects.hashCode(name); + result = 31 * result + Double.hashCode(balance); + return result; + } + + @Override + public String toString() { + return "Customer{" + + "id=" + id + + ", name='" + name + '\'' + + ", balance=" + balance + + '}'; + } +} diff --git a/templates/micronaut/src/main/java/com/oracle/coherence/demo/frameworks/micronaut/rest/ApplicationController.java b/templates/micronaut/src/main/java/com/oracle/coherence/demo/frameworks/micronaut/rest/ApplicationController.java new file mode 100644 index 0000000..428336b --- /dev/null +++ b/templates/micronaut/src/main/java/com/oracle/coherence/demo/frameworks/micronaut/rest/ApplicationController.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2025 Oracle and/or its affiliates. + * Licensed under the Universal Permissive License v 1.0 as shown at + * https://oss.oracle.com/licenses/upl. + */ + + +package com.oracle.coherence.demo.frameworks.micronaut.rest; + +import java.util.Collection; +import com.oracle.coherence.demo.frameworks.micronaut.Customer; + +import com.tangosol.net.NamedCache; + +import io.micronaut.http.HttpResponse; +import io.micronaut.http.MediaType; +import io.micronaut.http.annotation.Body; +import io.micronaut.http.annotation.Controller; + +import io.micronaut.http.annotation.Delete; +import io.micronaut.http.annotation.Get; +import io.micronaut.http.annotation.PathVariable; +import io.micronaut.http.annotation.Post; + +import jakarta.inject.Inject; +import jakarta.inject.Singleton; + +/** + * REST API for To Do list management. + */ +@Controller("/api/customers") +@Singleton +public class ApplicationController { + @Inject + private NamedCache customers; + + @Get(produces = MediaType.APPLICATION_JSON) + public Collection getCustomers() { + return customers.values(); + } + + @Post(consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON) + public HttpResponse createCustomer(@Body Customer customer) { + customers.put(customer.getId(), customer); + return HttpResponse.accepted(); + } + + @Get("/{id}") + public HttpResponse getCustomer(@PathVariable("id") int id) { + Customer customer = customers.get(id); + + return customer == null ? HttpResponse.notFound() : HttpResponse.ok(customer); + } + + @Delete("/{id}") + public HttpResponse deleteCustomer(@PathVariable("id") int id) { + Customer oldCustomer = customers.remove(id); + return oldCustomer == null ? HttpResponse.notFound() : HttpResponse.accepted(); + } +} diff --git a/templates/micronaut/src/main/resources/application.yml b/templates/micronaut/src/main/resources/application.yml new file mode 100644 index 0000000..c3a97c5 --- /dev/null +++ b/templates/micronaut/src/main/resources/application.yml @@ -0,0 +1,28 @@ +# +# Copyright (c) 2025, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at +# https://oss.oracle.com/licenses/upl. +# + +micronaut: + application: + name: micronaut-server + server: + port: 8080 + router: + static-resources: + default: + enabled: true + mapping: "/**" + paths: "classpath:web" + +coherence: + cluster: demo-cluster + ttl: 0 + wka: 127.0.0.1 + serializer: pof + distributed: + localstorage: true + management: + http: all + all: true diff --git a/templates/micronaut/src/main/resources/logback.xml b/templates/micronaut/src/main/resources/logback.xml new file mode 100644 index 0000000..b517f9b --- /dev/null +++ b/templates/micronaut/src/main/resources/logback.xml @@ -0,0 +1,23 @@ + + + + + + true + + + %cyan(%d{HH:mm:ss.SSS}) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n + + + + + + + diff --git a/templates/springboot/pom.xml b/templates/springboot/pom.xml new file mode 100644 index 0000000..f7083ee --- /dev/null +++ b/templates/springboot/pom.xml @@ -0,0 +1,86 @@ + + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.4.1 + + + + com.oracle.coherence.demo.frameworks + springboot + 1.0-SNAPSHOT + demo + Demo project for Spring Boot and Coherence + + + 21 + 24.09 + com.oracle.coherence.ce + 4.3.0 + + + + + org.springframework.boot + spring-boot-starter-web + + + + com.oracle.coherence.spring + coherence-spring-boot-starter + ${coherence-spring.version} + + + + ${coherence.group.id} + ${coherence.version} + coherence + + + + ${coherence.group.id} + ${coherence.version} + coherence-json + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + ${coherence.group.id} + ${coherence.version} + pof-maven-plugin + + + instrument + + instrument + + + + instrument-tests + + instrument-tests + + + + + + + \ No newline at end of file diff --git a/templates/springboot/src/main/java/com/oracle/coherence/demo/frameworks/springboot/Customer.java b/templates/springboot/src/main/java/com/oracle/coherence/demo/frameworks/springboot/Customer.java new file mode 100644 index 0000000..5dfc675 --- /dev/null +++ b/templates/springboot/src/main/java/com/oracle/coherence/demo/frameworks/springboot/Customer.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2024, 2025 Oracle and/or its affiliates. + * Licensed under the Universal Permissive License v 1.0 as shown at + * https://oss.oracle.com/licenses/upl. + */ + +package com.oracle.coherence.demo.frameworks.springboot; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.tangosol.io.pof.schema.annotation.PortableType; + +import java.util.Objects; + +@PortableType(id = 1000) +@JsonIgnoreProperties(value = { "evolvable", "evolvableHolder", "empty" }) +public class Customer { + @JsonProperty("id") + private int id; + + @JsonProperty("name") + private String name; + + @JsonProperty("balance") + private double balance; + + public Customer() {} + + public Customer(int id, String name, double balance) { + this.id = id; + this.name = name; + this.balance = balance; + } + + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public double getBalance() { + return balance; + } + + public void setBalance(double balance) { + this.balance = balance; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Customer customer = (Customer) o; + return id == customer.id && Double.compare(balance, customer.balance) == 0 && + Objects.equals(name, customer.name); + } + + @Override + public int hashCode() { + int result = id; + result = 31 * result + Objects.hashCode(name); + result = 31 * result + Double.hashCode(balance); + return result; + } + + @Override + public String toString() { + return "Customer{" + + "id=" + id + + ", name='" + name + '\'' + + ", balance=" + balance + + '}'; + } +} diff --git a/templates/springboot/src/main/java/com/oracle/coherence/demo/frameworks/springboot/DemoApplication.java b/templates/springboot/src/main/java/com/oracle/coherence/demo/frameworks/springboot/DemoApplication.java new file mode 100644 index 0000000..ed9f2fd --- /dev/null +++ b/templates/springboot/src/main/java/com/oracle/coherence/demo/frameworks/springboot/DemoApplication.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2024, 2025 Oracle and/or its affiliates. + * Licensed under the Universal Permissive License v 1.0 as shown at + * https://oss.oracle.com/licenses/upl. + */ + +package com.oracle.coherence.demo.frameworks.springboot; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DemoApplication { + + public static void main(String[] args) { + SpringApplication.run(DemoApplication.class, args); + } + +} diff --git a/templates/springboot/src/main/java/com/oracle/coherence/demo/frameworks/springboot/controller/DemoController.java b/templates/springboot/src/main/java/com/oracle/coherence/demo/frameworks/springboot/controller/DemoController.java new file mode 100644 index 0000000..6a42b8a --- /dev/null +++ b/templates/springboot/src/main/java/com/oracle/coherence/demo/frameworks/springboot/controller/DemoController.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2024, 2025 Oracle and/or its affiliates. + * Licensed under the Universal Permissive License v 1.0 as shown at + * https://oss.oracle.com/licenses/upl. + */ + +package com.oracle.coherence.demo.frameworks.springboot.controller; + +import com.oracle.coherence.demo.frameworks.springboot.Customer; +import com.oracle.coherence.spring.configuration.annotation.CoherenceCache; + +import com.tangosol.net.NamedCache; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Collection; + +@RestController +@RequestMapping(path = "/api/customers") +public class DemoController { + + private final NamedCache customers; + + public DemoController(@CoherenceCache NamedCache customers) { + this.customers = customers; + } + + @GetMapping + public Collection getCustomers() { + return customers.values(); + } + + @PostMapping + public ResponseEntity createCustomer(@RequestBody Customer customer) { + customers.put(customer.getId(), customer); + return ResponseEntity.accepted().build(); + } + + @GetMapping("/{id}") + public ResponseEntity getCustomer(@PathVariable int id) { + Customer customer = customers.get(id); + return customer == null ? ResponseEntity.notFound().build() : ResponseEntity.ok(customer); + } + + @DeleteMapping("/{id}") + public void removeCustomer(@PathVariable int id) { + customers.remove(id); + } + +} diff --git a/templates/springboot/src/main/resources/application.properties b/templates/springboot/src/main/resources/application.properties new file mode 100644 index 0000000..2d996ca --- /dev/null +++ b/templates/springboot/src/main/resources/application.properties @@ -0,0 +1,14 @@ +# +# Copyright (c) 2024, 2025 Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at +# https://oss.oracle.com/licenses/upl. +# + +# Common Coherence system properties +# Enable POF serialization +coherence.pof.enabled=true +# Confine Coherence to the current server +coherence.wka=127.0.0.1 +# Enable management +coherence.management.http=all +coherence.management=all \ No newline at end of file diff --git a/templates/template.yaml b/templates/template.yaml new file mode 100644 index 0000000..caaf664 --- /dev/null +++ b/templates/template.yaml @@ -0,0 +1,68 @@ +# +# Copyright (c) 2025 Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at +# https://oss.oracle.com/licenses/upl. +# +templates: + - name: helidon + frameworkVersion: "4.1.6" + instructions: | + To run the Helidon starter you must have JDK21+ and maven 3.8.5+. + Change to the newly created directory and run the following to build: + + mvn clean install + + To run single server: + java -jar target/helidon.jar + + To run additional server: + java -Dmain.class=com.tangosol.net.Coherence -Dcoherence.management.http=none -Dserver.port=-1 -jar target/helidon.jar + files: + - pom.xml + - src/main/resources/logging.properties + - src/main/resources/META-INF/beans.xml + - src/main/resources/META-INF/helidon/serial-config.properties + - src/main/resources/META-INF/microprofile-config.properties + - src/main/java/com/oracle/coherence/demo/frameworks/helidon/Customer.java + - src/main/java/com/oracle/coherence/demo/frameworks/helidon/CustomerResource.java + + - name: springboot + frameworkVersion: "spring-boot-starter 3.4.1, coherence-spring 4.3.0" + instructions: | + To run Spring Boot starter you must have JDK21+ and maven 3.8.5+. + Change to the newly created directory and run the following to build: + + mvn clean install + + To run single server: + java -jar target/springboot-1.0-SNAPSHOT.jar + + To run additional server: + java -Dserver.port=-1 -Dloader.main=com.tangosol.net.Coherence -Dcoherence.management.http=none -jar target/springboot-1.0-SNAPSHOT.jar + files: + - pom.xml + - src/main/resources/application.properties + - src/main/java/com/oracle/coherence/demo/frameworks/springboot/Customer.java + - src/main/java/com/oracle/coherence/demo/frameworks/springboot/controller/DemoController.java + - src/main/java/com/oracle/coherence/demo/frameworks/springboot/DemoApplication.java + + - name: micronaut + frameworkVersion: "micronaut-parent: 4.7.3, micronaut-coherence: 5.0.4" + instructions: | + To run Micronaut starter you must have JDK21+ and maven 3.8.5+. + Change to the newly created directory and run the following to build: + + mvn clean install + + To run single server: + java -jar target/micronaut-1.0-SNAPSHOT-shaded.jar + + To run additional server: + java -Dmicronaut.main.class=com.tangosol.net.Coherence -Dcoherence.management.http=none -Dmicronaut.server.port=-1 -jar target/micronaut-1.0-SNAPSHOT-shaded.jar + files: + - pom.xml + - src/main/resources/logback.xml + - src/main/resources/application.yml + - src/main/java/com/oracle/coherence/demo/frameworks/micronaut/Application.java + - src/main/java/com/oracle/coherence/demo/frameworks/micronaut/Customer.java + - src/main/java/com/oracle/coherence/demo/frameworks/micronaut/rest/ApplicationController.java