diff --git a/boost-common/src/main/java/org/microshed/boost/common/config/ConfigConstants.java b/boost-common/src/main/java/org/microshed/boost/common/config/ConfigConstants.java index be76c4df..44c5bc63 100644 --- a/boost-common/src/main/java/org/microshed/boost/common/config/ConfigConstants.java +++ b/boost-common/src/main/java/org/microshed/boost/common/config/ConfigConstants.java @@ -57,6 +57,8 @@ public final class ConfigConstants { public static final String PROPERTIES = "properties"; public static final String CONTAINER_AUTH_DATA_REF = "containerAuthDataRef"; public static final String URL = "url"; + public static final String CONNECTION_MANAGEMENT = "connectionManager"; + public static final String BOOST_CONNECTION_MANAGEMENT_REF = "boostConnectionManager"; // Datasource configuration values public static final String DEFAULT_DATASOURCE = "DefaultDataSource"; diff --git a/boost-maven/boost-maven-plugin/src/it/test-conn-mgmt/pom.xml b/boost-maven/boost-maven-plugin/src/it/test-conn-mgmt/pom.xml new file mode 100644 index 00000000..b34e6582 --- /dev/null +++ b/boost-maven/boost-maven-plugin/src/it/test-conn-mgmt/pom.xml @@ -0,0 +1,247 @@ + + + + 4.0.0 + + org.microshed.boost.test + test-conn-mgmt + war + @pom.version@ + + + UTF-8 + UTF-8 + 1.8 + 1.8 + + + + + + sonatype-nexus-snapshots + Sonatype Nexus Snapshots + https://oss.sonatype.org/content/repositories/snapshots/ + + true + + + false + + + + + + + jitpack.io + https://jitpack.io + + + + + + + org.microshed.boost.boms + mp22-bom + 0.2.2-SNAPSHOT + import + pom + + + + + + + org.microshed.boost.boosters + jaxrs + + + org.microshed.boost.boosters + cdi + + + org.microshed.boost.boosters + jsonb + + + org.microshed.boost.boosters + mp-rest-client + + + org.microshed.boost.boosters + mp-config + + + org.microshed.boost.boosters + mp-health + + + org.microshed.boost.boosters + bean-validation + + + org.microshed.boost.boosters + jpa + + + org.microshed.boost.boosters + jdbc + + + org.postgresql + postgresql + 42.2.6 + + + org.microshed.boost.boosters + mp-openapi + + + + microshed-testing-liberty + com.github.microshed.microshed-testing + 0.4.1-beta + test + + + + org.junit.jupiter + junit-jupiter + 5.4.2 + test + + + + org.testcontainers + postgresql + 1.12.1 + test + + + + + myservice + + + org.apache.maven.plugins + maven-war-plugin + 3.2.2 + + false + + + + + io.openliberty.tools + liberty-maven-plugin + 3.0.1 + + + org.microshed.boost + boost-maven-plugin + 0.2.2-SNAPSHOT + + + + package + + + + test-start-server + pre-integration-test + + start + + + + test-stop-server + post-integration-test + + stop + + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + 3.0.0-M3 + + + integration-test + integration-test1 + + integration-test + + + false + + localhost + 9080 + ${project.build.directory}/liberty/wlp/usr + + + + + + integration-test2 + + integration-test + + + false + + localhost + 9080 + true + ${project.build.directory}/liberty/wlp/usr + + + + + verify-results + + verify + + + + + + + + + + ol + + true + + boostRuntime + ol + + + + + org.microshed.boost.runtimes + openliberty + + + + + tomee + + + boostRuntime + tomee + + + + + org.microshed.boost.runtimes + tomee + + + + + + diff --git a/boost-maven/boost-maven-plugin/src/it/test-conn-mgmt/src/main/java/org/eclipse/microprofile/system/test/app/Person.java b/boost-maven/boost-maven-plugin/src/it/test-conn-mgmt/src/main/java/org/eclipse/microprofile/system/test/app/Person.java new file mode 100644 index 00000000..cf062001 --- /dev/null +++ b/boost-maven/boost-maven-plugin/src/it/test-conn-mgmt/src/main/java/org/eclipse/microprofile/system/test/app/Person.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2019 IBM Corporation and others + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.eclipse.microprofile.system.test.app; + +import java.util.Objects; +import java.util.Random; + +import javax.json.bind.annotation.JsonbCreator; +import javax.json.bind.annotation.JsonbProperty; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.PositiveOrZero; +import javax.validation.constraints.Size; + +public class Person { + + private static final Random r = new Random(); + + @NotNull + public final long id; + + @NotNull + @Size(min = 2, max = 50) + public final String name; + + @NotNull + @PositiveOrZero + public final int age; + + public Person(String name, int age) { + this(name, age, null); + } + + @JsonbCreator + public Person(@JsonbProperty("name") String name, @JsonbProperty("age") int age, @JsonbProperty("id") Long id) { + this.name = name; + this.age = age; + this.id = id == null ? r.nextLong() : id; + } + + @Override + public boolean equals(Object obj) { + if (obj == null || !(obj instanceof Person)) + return false; + Person other = (Person) obj; + return Objects.equals(id, other.id) && Objects.equals(name, other.name) && Objects.equals(age, other.age); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, age); + } +} diff --git a/boost-maven/boost-maven-plugin/src/it/test-conn-mgmt/src/main/java/org/eclipse/microprofile/system/test/app/PersonService.java b/boost-maven/boost-maven-plugin/src/it/test-conn-mgmt/src/main/java/org/eclipse/microprofile/system/test/app/PersonService.java new file mode 100644 index 00000000..748122d2 --- /dev/null +++ b/boost-maven/boost-maven-plugin/src/it/test-conn-mgmt/src/main/java/org/eclipse/microprofile/system/test/app/PersonService.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2019 IBM Corporation and others + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.eclipse.microprofile.system.test.app; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +//import javax.annotation.PostConstruct; +import javax.enterprise.context.ApplicationScoped; +import javax.sql.DataSource; +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.PositiveOrZero; +import javax.validation.constraints.Size; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.InternalServerErrorException; +import javax.ws.rs.NotFoundException; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; + +@Path("/people") +@ApplicationScoped +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +public class PersonService { + + @Resource + DataSource defaultDataSource; + + @PostConstruct + public void initPeople() { + System.out.println("Seeding database with sample data"); + try (Connection conn = defaultDataSource.getConnection()) { + conn.prepareStatement("CREATE TABLE IF NOT EXISTS people (id bigint, name text, age integer)").execute(); + } catch (SQLException e) { + e.printStackTrace(System.out); + } + createPerson("Sample Person A", 25); + createPerson("Sample Person B", 26); + } + + @GET + public Collection getAllPeople() { + Set allPeople = new HashSet<>(); + + try (Connection conn = defaultDataSource.getConnection(); + ResultSet rs = conn.prepareStatement("SELECT name, age, id FROM people").executeQuery()) { + while (rs.next()) { + allPeople.add(new Person(rs.getString("name"), rs.getInt("age"), rs.getLong("id"))); + } + return allPeople; + } catch (SQLException e) { + throw new InternalServerErrorException("Could not get all people", e); + } + } + + @GET + @Path("/{personId}") + public Person getPerson(@PathParam("personId") long id) { + try (Connection conn = defaultDataSource.getConnection(); + ResultSet rs = conn.prepareStatement("SELECT name, age FROM people WHERE id = " + id).executeQuery()) { + if (rs.next()) { + return new Person(rs.getString("name"), rs.getInt("age"), id); + } + throw new NotFoundException("Person with id " + id + " not found."); + } catch (SQLException e) { + throw new InternalServerErrorException("Could not get person", e); + } + } + + @POST + public Long createPerson(@QueryParam("name") @NotEmpty @Size(min = 2, max = 50) String name, + @QueryParam("age") @PositiveOrZero int age) { + Person p = new Person(name, age); + + try (Connection conn = defaultDataSource.getConnection(); + PreparedStatement ps = conn.prepareStatement("INSERT INTO people VALUES(?,?,?)")) { + ps.setLong(1, p.id); + ps.setString(2, name); + ps.setInt(3, age); + ps.execute(); + return p.id; + } catch (SQLException e) { + throw new InternalServerErrorException("Could not create new person", e); + } + } + + @POST + @Path("/{personId}") + public void updatePerson(@PathParam("personId") long id, @Valid Person p) { + try (Connection conn = defaultDataSource.getConnection(); + PreparedStatement ps = conn.prepareStatement("UPDATE people SET name = ?, age = ? WHERE id = ?")) { + ps.setString(1, p.name); + ps.setInt(2, p.age); + ps.setLong(3, p.id); + if (ps.executeUpdate() > 0) { + return; + } + ; + throw new NotFoundException("Person with id " + id + " not found."); + } catch (SQLException e) { + throw new InternalServerErrorException("Could not update person", e); + } + } + + @DELETE + @Path("/{personId}") + public void removePerson(@PathParam("personId") long id) { + try (Connection conn = defaultDataSource.getConnection(); + PreparedStatement ps = conn.prepareStatement("DELETE FROM people WHERE id = ?")) { + ps.setLong(1, id); + if (ps.executeUpdate() > 0) { + return; + } + ; + throw new NotFoundException("Person with id " + id + " not found."); + } catch (SQLException e) { + throw new InternalServerErrorException("Could not delete person", e); + } + } + +} diff --git a/boost-maven/boost-maven-plugin/src/it/test-conn-mgmt/src/main/java/org/eclipse/microprofile/system/test/app/PersonServiceApp.java b/boost-maven/boost-maven-plugin/src/it/test-conn-mgmt/src/main/java/org/eclipse/microprofile/system/test/app/PersonServiceApp.java new file mode 100644 index 00000000..3a1589ee --- /dev/null +++ b/boost-maven/boost-maven-plugin/src/it/test-conn-mgmt/src/main/java/org/eclipse/microprofile/system/test/app/PersonServiceApp.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2019 IBM Corporation and others + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.eclipse.microprofile.system.test.app; + +import javax.ws.rs.ApplicationPath; +import javax.ws.rs.core.Application; + +@ApplicationPath("/") +public class PersonServiceApp extends Application { +} diff --git a/boost-maven/boost-maven-plugin/src/it/test-conn-mgmt/src/main/liberty/config/configDropins/overrides/connMgr.xml b/boost-maven/boost-maven-plugin/src/it/test-conn-mgmt/src/main/liberty/config/configDropins/overrides/connMgr.xml new file mode 100644 index 00000000..1f593dfa --- /dev/null +++ b/boost-maven/boost-maven-plugin/src/it/test-conn-mgmt/src/main/liberty/config/configDropins/overrides/connMgr.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/boost-maven/boost-maven-plugin/src/it/test-conn-mgmt/src/test/java/org/eclipse/microprofile/system/test/app/AppContainerConfig.java b/boost-maven/boost-maven-plugin/src/it/test-conn-mgmt/src/test/java/org/eclipse/microprofile/system/test/app/AppContainerConfig.java new file mode 100644 index 00000000..27f567b9 --- /dev/null +++ b/boost-maven/boost-maven-plugin/src/it/test-conn-mgmt/src/test/java/org/eclipse/microprofile/system/test/app/AppContainerConfig.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2019 IBM Corporation and others + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.eclipse.microprofile.system.test.app; + +import org.microshed.testing.SharedContainerConfiguration; +import org.microshed.testing.testcontainers.MicroProfileApplication; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; + +public class AppContainerConfig implements SharedContainerConfiguration { + + @Container + public static PostgreSQLContainer postgres = new PostgreSQLContainer<>().withNetworkAliases("testpostgres") + .withDatabaseName("test").withExposedPorts(5432).withInitScript("init.sql"); + + @Container + public static MicroProfileApplication app = new MicroProfileApplication() + .withEnv("POSTGRES_HOSTNAME", "testpostgres").withEnv("boost_db_portNumber", "5432") + .withEnv("boost_db_databaseName", "test").withEnv("boost_db_username", "test") + .withEnv("boost_db_password", "test").withAppContextRoot(""); + + @Override + public void startContainers() { + postgres.start(); + app.start(); + } + +} diff --git a/boost-maven/boost-maven-plugin/src/it/test-conn-mgmt/src/test/java/org/eclipse/microprofile/system/test/app/JaxrsJsonIT.java b/boost-maven/boost-maven-plugin/src/it/test-conn-mgmt/src/test/java/org/eclipse/microprofile/system/test/app/JaxrsJsonIT.java new file mode 100644 index 00000000..72b6cec7 --- /dev/null +++ b/boost-maven/boost-maven-plugin/src/it/test-conn-mgmt/src/test/java/org/eclipse/microprofile/system/test/app/JaxrsJsonIT.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2019 IBM Corporation and others + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.eclipse.microprofile.system.test.app; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.util.Collection; + +import javax.inject.Inject; +import javax.ws.rs.BadRequestException; +import javax.ws.rs.NotFoundException; + +import org.junit.jupiter.api.Test; +import org.microshed.testing.SharedContainerConfig; +import org.microshed.testing.jupiter.MicroShedTest; + +@MicroShedTest +@SharedContainerConfig(AppContainerConfig.class) +public class JaxrsJsonIT { + + @Inject + public static PersonService personSvc; + + @Test + public void testCreatePerson() { + Long createId = personSvc.createPerson("Hank", 42); + assertNotNull(createId); + } + + @Test + public void testMinSizeName() { + Long minSizeNameId = personSvc.createPerson("Ha", 42); + assertEquals(new Person("Ha", 42, minSizeNameId), personSvc.getPerson(minSizeNameId)); + } + + @Test + public void testMinAge() { + Long minAgeId = personSvc.createPerson("Newborn", 0); + assertEquals(new Person("Newborn", 0, minAgeId), personSvc.getPerson(minAgeId)); + } + + @Test + public void testGetPerson() { + Long bobId = personSvc.createPerson("Bob", 24); + Person bob = personSvc.getPerson(bobId); + assertEquals("Bob", bob.name); + assertEquals(24, bob.age); + assertNotNull(bob.id); + } + + @Test + public void testGetAllPeople() { + Long person1Id = personSvc.createPerson("Person1", 1); + Long person2Id = personSvc.createPerson("Person2", 2); + + Person expected1 = new Person("Person1", 1, person1Id); + Person expected2 = new Person("Person2", 2, person2Id); + + Collection allPeople = personSvc.getAllPeople(); + assertTrue("Expected at least 2 people to be registered, but there were only: " + allPeople, + allPeople.size() >= 2); + assertTrue("Did not find person " + expected1 + " in all people: " + allPeople, allPeople.contains(expected1)); + assertTrue("Did not find person " + expected2 + " in all people: " + allPeople, allPeople.contains(expected2)); + } + + @Test + public void testUpdateAge() { + Long personId = personSvc.createPerson("newAgePerson", 1); + + Person originalPerson = personSvc.getPerson(personId); + assertEquals("newAgePerson", originalPerson.name); + assertEquals(1, originalPerson.age); + assertEquals(personId, Long.valueOf(originalPerson.id)); + + personSvc.updatePerson(personId, new Person(originalPerson.name, 2, originalPerson.id)); + Person updatedPerson = personSvc.getPerson(personId); + assertEquals("newAgePerson", updatedPerson.name); + assertEquals(2, updatedPerson.age); + assertEquals(personId, Long.valueOf(updatedPerson.id)); + } + + @Test + public void testGetUnknownPerson() { + assertThrows(NotFoundException.class, () -> personSvc.getPerson(-1L)); + } + + @Test + public void testCreateBadPersonNullName() { + assertThrows(BadRequestException.class, () -> personSvc.createPerson(null, 5)); + } + + @Test + public void testCreateBadPersonNegativeAge() { + assertThrows(BadRequestException.class, () -> personSvc.createPerson("NegativeAgePersoN", -1)); + } + + @Test + public void testCreateBadPersonNameTooLong() { + assertThrows(BadRequestException.class, + () -> personSvc.createPerson("NameTooLongPersonNameTooLongPersonNameTooLongPerson", 5)); + } +} \ No newline at end of file diff --git a/boost-maven/boost-maven-plugin/src/it/test-conn-mgmt/src/test/resources/init.sql b/boost-maven/boost-maven-plugin/src/it/test-conn-mgmt/src/test/resources/init.sql new file mode 100644 index 00000000..15b2b19f --- /dev/null +++ b/boost-maven/boost-maven-plugin/src/it/test-conn-mgmt/src/test/resources/init.sql @@ -0,0 +1 @@ +CREATE TABLE IF NOT EXISTS people (id bigint, name text, age integer) \ No newline at end of file diff --git a/boost-maven/boost-maven-plugin/src/it/test-conn-mgmt/src/test/resources/log4j.properties b/boost-maven/boost-maven-plugin/src/it/test-conn-mgmt/src/test/resources/log4j.properties new file mode 100644 index 00000000..df5cc304 --- /dev/null +++ b/boost-maven/boost-maven-plugin/src/it/test-conn-mgmt/src/test/resources/log4j.properties @@ -0,0 +1,10 @@ +log4j.rootLogger=INFO, stdout + +log4j.appender=org.apache.log4j.ConsoleAppender +log4j.appender.layout=org.apache.log4j.PatternLayout + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%r %p %c %x - %m%n + +log4j.logger.org.microshed=DEBUG \ No newline at end of file diff --git a/boost-maven/boost-runtimes/runtime-openliberty/src/main/java/org/microshed/boost/runtimes/openliberty/LibertyServerConfigGenerator.java b/boost-maven/boost-runtimes/runtime-openliberty/src/main/java/org/microshed/boost/runtimes/openliberty/LibertyServerConfigGenerator.java index de1f4844..0ae831a0 100644 --- a/boost-maven/boost-runtimes/runtime-openliberty/src/main/java/org/microshed/boost/runtimes/openliberty/LibertyServerConfigGenerator.java +++ b/boost-maven/boost-runtimes/runtime-openliberty/src/main/java/org/microshed/boost/runtimes/openliberty/LibertyServerConfigGenerator.java @@ -139,8 +139,7 @@ public void addFeatures(List features) { } /** - * Write the server.xml and bootstrap.properties to the server config - * directory + * Write the server.xml and bootstrap.properties to the server config directory * * @throws TransformerException * @throws IOException @@ -338,6 +337,7 @@ public void addDataSource(Map driverInfo, Properties datasourceP Element dataSource = serverXml.createElement(DATASOURCE); dataSource.setAttribute("id", DEFAULT_DATASOURCE); dataSource.setAttribute(JDBC_DRIVER_REF, JDBC_DRIVER_1); + dataSource.setAttribute("connectionManagerRef", BOOST_CONNECTION_MANAGEMENT_REF); // Add all configured datasource properties Element props = serverXml.createElement(datasourcePropertiesElement);