Skip to content

Commit

Permalink
Merge pull request #41858 from galderz/topic.dev-services-agent
Browse files Browse the repository at this point in the history
Enable dev services to be located by in-container java
  • Loading branch information
geoand committed Jul 19, 2024
2 parents b4835d8 + ed90549 commit d727ede
Show file tree
Hide file tree
Showing 9 changed files with 280 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,27 @@
<!-- insert test dependencies here -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy</artifactId>
<artifactId>quarkus-agroal</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-jackson</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-orm</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-postgresql</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package org.acme;

import jakarta.persistence.Cacheable;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.NamedQuery;
import jakarta.persistence.QueryHint;
import jakarta.persistence.SequenceGenerator;
import jakarta.persistence.Table;

@Entity
@Table(name = "known_fruits")
@NamedQuery(name = "Fruits.findAll", query = "SELECT f FROM Fruit f ORDER BY f.name", hints = @QueryHint(name = "org.hibernate.cacheable", value = "true"))
@Cacheable
public class Fruit {

@Id
@SequenceGenerator(name = "fruitsSequence", sequenceName = "known_fruits_id_seq", allocationSize = 1, initialValue = 10)
@GeneratedValue(generator = "fruitsSequence")
private Integer id;

@Column(length = 40, unique = true)
private String name;

public Fruit() {
}

public Fruit(String name) {
this.name = name;
}

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package org.acme;

import java.util.List;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.persistence.EntityManager;
import jakarta.transaction.Transactional;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.ExceptionMapper;
import jakarta.ws.rs.ext.Provider;

import org.jboss.logging.Logger;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

@Path("fruits")
@ApplicationScoped
@Produces("application/json")
@Consumes("application/json")
public class FruitResource {

private static final Logger LOGGER = Logger.getLogger(FruitResource.class.getName());

@Inject
EntityManager entityManager;

@GET
public List<Fruit> get() {
return entityManager.createNamedQuery("Fruits.findAll", Fruit.class)
.getResultList();
}

@GET
@Path("{id}")
public Fruit getSingle(Integer id) {
Fruit entity = entityManager.find(Fruit.class, id);
if (entity == null) {
throw new WebApplicationException("Fruit with id of " + id + " does not exist.", 404);
}
return entity;
}

@POST
@Transactional
public Response create(Fruit fruit) {
if (fruit.getId() != null) {
throw new WebApplicationException("Id was invalidly set on request.", 422);
}

entityManager.persist(fruit);
return Response.ok(fruit).status(201).build();
}

@PUT
@Path("{id}")
@Transactional
public Fruit update(Integer id, Fruit fruit) {
if (fruit.getName() == null) {
throw new WebApplicationException("Fruit Name was not set on request.", 422);
}

Fruit entity = entityManager.find(Fruit.class, id);

if (entity == null) {
throw new WebApplicationException("Fruit with id of " + id + " does not exist.", 404);
}

entity.setName(fruit.getName());

return entity;
}

@DELETE
@Path("{id}")
@Transactional
public Response delete(Integer id) {
Fruit entity = entityManager.getReference(Fruit.class, id);
if (entity == null) {
throw new WebApplicationException("Fruit with id of " + id + " does not exist.", 404);
}
entityManager.remove(entity);
return Response.status(204).build();
}

@Provider
public static class ErrorMapper implements ExceptionMapper<Exception> {

@Inject
ObjectMapper objectMapper;

@Override
public Response toResponse(Exception exception) {
LOGGER.error("Failed to handle request", exception);

int code = 500;
if (exception instanceof WebApplicationException) {
code = ((WebApplicationException) exception).getResponse().getStatus();
}

ObjectNode exceptionJson = objectMapper.createObjectNode();
exceptionJson.put("exceptionType", exception.getClass().getName());
exceptionJson.put("code", code);

if (exception.getMessage() != null) {
exceptionJson.put("error", exception.getMessage());
}

return Response.status(code)
.entity(exceptionJson)
.build();
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
quarkus.hibernate-orm.log.sql=true
quarkus.hibernate-orm.sql-load-script=import.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
INSERT INTO known_fruits(id, name) VALUES (1, 'Cherry');
INSERT INTO known_fruits(id, name) VALUES (2, 'Apple');
INSERT INTO known_fruits(id, name) VALUES (3, 'Banana');
ALTER SEQUENCE known_fruits_id_seq RESTART WITH 4;
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.acme;

import io.quarkus.test.junit.QuarkusIntegrationTest;

@QuarkusIntegrationTest
public class FruitsEndpointIT extends FruitsEndpointTest {

// Runs the same tests as the parent class

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package org.acme;

import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.core.IsNot.not;

import org.junit.jupiter.api.Test;

import io.quarkus.test.junit.QuarkusTest;

@QuarkusTest
public class FruitsEndpointTest {

@Test
public void testListAllFruits() {
//List all, should have all 3 fruits the database has initially:
given()
.when().get("/fruits")
.then()
.statusCode(200)
.body(
containsString("Cherry"),
containsString("Apple"),
containsString("Banana"));

//Delete the Cherry:
given()
.when().delete("/fruits/1")
.then()
.statusCode(204);

//List all, cherry should be missing now:
given()
.when().get("/fruits")
.then()
.statusCode(200)
.body(
not(containsString("Cherry")),
containsString("Apple"),
containsString("Banana"));

//Create the Pear:
given()
.when()
.body("{\"name\" : \"Pear\"}")
.contentType("application/json")
.post("/fruits")
.then()
.statusCode(201);

//List all, cherry should be missing now:
given()
.when().get("/fruits")
.then()
.statusCode(200)
.body(
not(containsString("Cherry")),
containsString("Apple"),
containsString("Banana"),
containsString("Pear"));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ public void testUnknownName()
given()
.when().get("/hello/Bob")
.then()
.statusCode(404)
.body(is(""));
.statusCode(404);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.quarkus.test.junit;

import static io.quarkus.test.junit.ArtifactTypeUtil.isContainer;
import static io.quarkus.test.junit.ArtifactTypeUtil.isJar;
import static io.quarkus.test.junit.IntegrationTestUtil.activateLogging;
import static io.quarkus.test.junit.IntegrationTestUtil.determineBuildOutputDirectory;
import static io.quarkus.test.junit.IntegrationTestUtil.determineTestProfileAndProperties;
Expand Down Expand Up @@ -194,7 +195,10 @@ private QuarkusTestExtensionState doProcessStart(Properties quarkusArtifactPrope

String artifactType = getArtifactType(quarkusArtifactProperties);

boolean isDockerLaunch = isContainer(artifactType);
Config config = LauncherUtil.installAndGetSomeConfig();
String testProfile = TestConfigUtil.integrationTestProfile(config);
boolean isDockerLaunch = isContainer(artifactType)
|| (isJar(artifactType) && "test-with-native-agent".equals(testProfile));

ArtifactLauncher.InitContext.DevServicesLaunchResult devServicesLaunchResult = handleDevServices(context,
isDockerLaunch);
Expand Down Expand Up @@ -272,10 +276,8 @@ public void close() throws Throwable {
if ((testHost != null) && !testHost.isEmpty()) {
launcher = new TestHostLauncher();
} else {
Config config = LauncherUtil.installAndGetSomeConfig();
Duration waitDuration = TestConfigUtil.waitTimeValue(config);
String target = TestConfigUtil.runTarget(config);
String testProfile = TestConfigUtil.integrationTestProfile(config);
// try to execute a run command published by an extension if it exists. We do this so that extensions that have a custom run don't have to create any special artifact type
launcher = RunCommandLauncher.tryLauncher(devServicesLaunchResult.getCuratedApplication().getQuarkusBootstrap(),
target, waitDuration);
Expand Down

0 comments on commit d727ede

Please sign in to comment.