算法艺术创作
algorithmic-art
通过代码和可调参数创作生成艺术与交互式视觉效果。
quarkus-backend【设计与创意】Use this skill when building Quarkus backend applications — supersonic Java, Dev UI, GraalVM native, reactive messaging, Panache ORM. This skill enforces: compile-time metadata processing, live reload, continuous testing, container-first design. Do NOT use for: Spring Boot projects, Micronaut applications, standard Jakarta EE.
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
Define Quarkus backend application architecture: supersonic startup, live reload, native executables, reactive messaging, and extension ecosystem.
User request includes: quarkus, quarkus backend, supersonic java, quarkus native, panache, quarkus reactive, quarkus extension, quarkus dev ui, container-first java.
A markdown document containing:
Produce the artifact directly. No preamble, no postamble, no explanations. No filler, no hedging. Compress output.
4096 tokens
# Using Maven
mvn io.quarkus.platform:quarkus-maven-plugin:3.6.0:create \
-DprojectGroupId=com.example \
-DprojectArtifactId=order-service \
-Dextensions='resteasy-reactive,hibernate-validator,reactive-pg-client,panache'
# Using Gradle
quarkus create app com.example:order-service \
--extension=resteasy-reactive,reactive-pg-client,panache,kafka
# Using Quarkus CLI
quarkus create app order-service \
-x resteasy-reactive,reactive-pg-client,panache,kafka
src/
+-- main/
| +-- java/com/example/
| | +-- OrderResource.java
| | +-- OrderService.java
| | +-- Order.java
| | +-- OrderRepository.java
| | +-- OrderMapper.java
| | +-- dto/
| | | +-- CreateOrderRequest.java
| | | +-- OrderResponse.java
| | +-- messaging/
| | | +-- OrderEventProducer.java
| | | +-- OrderEventConsumer.java
| | +-- exception/
| | | +-- GlobalExceptionMapper.java
| | | +-- OrderNotFoundException.java
| | +-- health/
| | +-- DatabaseHealthCheck.java
| +-- resources/
| +-- application.properties
| +-- META-INF/
| +-- resources-config.json (GraalVM hints)
+-- test/
| +-- java/com/example/
| +-- OrderResourceTest.java
| +-- OrderServiceTest.java
+-- docker-compose.yml
@Path("/api/orders")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class OrderResource {
@Inject OrderService service;
@GET
public Uni<List<OrderResponse>> list(
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size) {
return service.list(page, size)
.map(list -> list.stream().map(o -> OrderMapper.toResponse(o)).toList());
}
@GET
@Path("/{id}")
public Uni<OrderResponse> get(@PathParam UUID id) {
return service.findById(id)
.map(o -> o.map(OrderMapper::toResponse)
.orElseThrow(() -> new OrderNotFoundException(id)));
}
@POST
public Uni<RestResponse<OrderResponse>> create(@Valid CreateOrderRequest req) {
return service.create(req)
.map(r -> RestResponse.status(CREATED, OrderMapper.toResponse(r)));
}
@PUT
@Path("/{id}")
public Uni<OrderResponse> update(@PathParam UUID id, @Valid CreateOrderRequest req) {
return service.update(id, req)
.map(OrderMapper::toResponse);
}
@DELETE
@Path("/{id}")
public Uni<RestResponse<Void>> delete(@PathParam UUID id) {
return service.delete(id)
.map(r -> RestResponse.noContent());
}
}
@Entity
@Table(name = "orders")
public class Order extends PanacheEntityBase {
@Id
public UUID id;
@Column(name = "customer_id", nullable = false)
public String customerId;
@Enumerated(STRING)
@Column(nullable = false)
public OrderStatus status;
@Column(name = "total_amount", precision = 10, scale = 2)
public BigDecimal totalAmount;
@Column(name = "created_at")
public Instant createdAt;
@Column(name = "updated_at")
public Instant updatedAt;
@PrePersist
void prePersist() {
if (id == null) id = UUID.randomUUID();
if (createdAt == null) createdAt = Instant.now();
updatedAt = Instant.now();
}
public static Uni<Order> findByCustomerId(String customerId) {
return find("customerId", customerId).firstResult();
}
public static Uni<List<Order>> listRecent(int limit) {
return find("ORDER BY createdAt DESC").page(Page.ofSize(limit)).list();
}
}
// Repository Pattern (alternative)
@ApplicationScoped
public class OrderRepository implements PanacheRepositoryBase<Order, UUID> {
public Uni<List<Order>> findRecent(int limit) {
return find("ORDER BY createdAt DESC").page(Page.ofSize(limit)).list();
}
public Uni<Long> countByStatus(OrderStatus status) {
return count("status", status);
}
}
// DTO
public record CreateOrderRequest(
@NotBlank String customerId,
@NotEmpty List<OrderItemDto> items
) {}
public record OrderItemDto(
@NotBlank String productId,
@Min(1) int quantity,
@Positive BigDecimal unitPrice
) {}
public record OrderResponse(
UUID id,
String customerId,
String status,
BigDecimal totalAmount,
Instant createdAt
) {}
// Mapper
public class OrderMapper {
public static OrderResponse toResponse(Order order) {
return new OrderResponse(
order.id,
order.customerId,
order.status.name(),
order.totalAmount,
order.createdAt
);
}
}
// messaging/OrderEventProducer.java
@ApplicationScoped
public class OrderEventProducer {
@Channel("orders-out")
Emitter<OrderEvent> emitter;
public Uni<Void> sendOrderCreated(Order order) {
return emitter.send(new OrderEvent(
order.id.toString(),
"ORDER_CREATED",
order.customerId,
order.totalAmount
));
}
}
// messaging/OrderEventConsumer.java
@ApplicationScoped
public class OrderEventConsumer {
@Inject InventoryService inventoryService;
@Inject NotificationService notificationService;
@Incoming("orders-in")
public CompletionStage<Void> onOrderCreated(OrderEvent event) {
return Uni.combine().all()
.unis(
inventoryService.reserveItems(event.orderId()),
notificationService.sendConfirmation(event.customerId(), event.orderId())
)
.discardItems()
.subscribeAsCompletionStage();
}
}
// OrderEvent.java
public record OrderEvent(
String orderId,
String eventType,
String customerId,
BigDecimal totalAmount
) {}
# application.properties
quarkus.http.port=8080
quarkus.log.level=INFO
quarkus.log.console.enable=true
# Datasource
quarkus.datasource.db-kind=postgresql
quarkus.datasource.username=${DB_USER}
quarkus.datasource.password=${DB_PASS}
quarkus.datasource.reactive.url=${DB_URL}
# Hibernate
quarkus.hibernate-orm.database.generation=validate
quarkus.hibernate-orm.log.sql=false
# Kafka
mp.messaging.outgoing.orders-out.connector=smallrye-kafka
mp.messaging.outgoing.orders-out.topic=orders
mp.messaging.outgoing.orders-out.value.serializer=io.quarkus.kafka.client.serialization.JsonbSerializer
mp.messaging.incoming.orders-in.connector=smallrye-kafka
mp.messaging.incoming.orders-in.topic=orders
mp.messaging.incoming.orders-in.value.deserializer=io.quarkus.kafka.client.serialization.JsonbDeserializer
mp.messaging.incoming.orders-in.group.id=order-service
# Native
quarkus.native.container-build=true
quarkus.native.additional-build-args=--enable-url-protocols=http,--initialize-at-run-time=com.example.messaging
quarkus.native.builder-image=graalvm:21
# Dev Services (auto-starts containers in dev/test)
quarkus.devservices.enabled=true
quarkus.devservices.postgresql.image-name=postgres:15
# CORS
quarkus.http.cors=true
quarkus.http.cors.origins=http://localhost:3000
quarkus.http.cors.methods=GET,POST,PUT,DELETE,OPTIONS
# Health
quarkus.health.extensions.enabled=true
@QuarkusTest
public class OrderResourceTest {
@Test
public void testCreateOrder() {
given()
.body("""
{
"customerId": "cust-1",
"items": [
{"productId": "prod-1", "quantity": 2, "unitPrice": 19.99}
]
}
""")
.contentType(ContentType.JSON)
.when()
.post("/api/orders")
.then()
.statusCode(201)
.body("customerId", equalTo("cust-1"));
}
@Test
public void testGetNonExistentOrder() {
given()
.when()
.get("/api/orders/" + UUID.randomUUID())
.then()
.statusCode(404);
}
@Test
public void testUnauthenticatedRequest() {
given()
.when()
.get("/api/orders")
.then()
.statusCode(401);
}
}
@QuarkusTest
@QuarkusTestResource(PostgresTestResource.class)
public class OrderServiceTest {
@Inject OrderService orderService;
@Inject PanacheMock mockOrder;
@Test
public void testFindById() {
UUID id = UUID.randomUUID();
Order order = new Order();
order.id = id;
order.customerId = "cust-1";
PanacheMock.mock(Order.class);
when(Order.findById(id)).thenReturn(Uni.createFrom().item(order));
orderService.findById(id)
.subscribe().with(found -> {
assertNotNull(found);
assertEquals("cust-1", found.get().customerId);
});
}
}
@Provider
public class GlobalExceptionMapper implements ExceptionMapper<Throwable> {
@Override
public Response toResponse(Throwable exception) {
if (exception instanceof OrderNotFoundException) {
return Response.status(Response.Status.NOT_FOUND)
.entity(new ErrorResponse("NOT_FOUND", exception.getMessage()))
.build();
}
if (exception instanceof ConstraintViolationException) {
List<String> errors = ((ConstraintViolationException) exception)
.getConstraintViolations().stream()
.map(v -> v.getPropertyPath() + ": " + v.getMessage())
.toList();
return Response.status(Response.Status.BAD_REQUEST)
.entity(new ErrorResponse("VALIDATION", "Validation failed", errors))
.build();
}
if (exception instanceof WebApplicationException) {
return ((WebApplicationException) exception).getResponse();
}
Log.error("Unhandled exception", exception);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(new ErrorResponse("INTERNAL_ERROR", "An unexpected error occurred"))
.build();
}
}
public class OrderNotFoundException extends RuntimeException {
public OrderNotFoundException(UUID id) {
super("Order with id " + id + " not found");
}
}
public record ErrorResponse(String code, String message, Object details) {
public ErrorResponse(String code, String message) {
this(code, message, null);
}
}
Need fine-grained JPA control (custom queries, entity graphs)?
+-- Yes -> Repository pattern. Interface extends PanacheRepositoryBase.
+-- No -> Active Record pattern. Order extends PanacheEntityBase. Simpler.
Already using blocking JDBC driver?
+-- Yes -> Use standard Hibernate ORM + RESTEasy (non-reactive). Same code, JIT runtime.
+-- No -> Use Hibernate Reactive + RESTEasy Reactive + R2DBC/Reactive PG Client.
Container deployment with cold-start requirements?
+-- Yes -> Native binary. <0.1s startup, ~50MB memory. Add GraalVM hints for reflection.
+-- No -> JIT JAR. Simpler build, broader compatibility, faster builds.
Reflection not configured for native: Classes loaded dynamically (serialization, frameworks) need GraalVM reflect-config.json or @RegisterForReflection.
Blocking JDBC usage in reactive context: Calling block() on a Uni in a reactive chain blocks the event loop. Use Hibernate Reactive or separate blocking pool.
Dev Services in production: Dev Services auto-start containers. Disable with quarkus.devservices.enabled=false in production profiles.
Lazy fetching across transactions: In reactive mode, no open session for lazy loading. Use JOIN FETCH or entity graphs.
Missing Panache mock setup: PanacheMock requires explicit mock configuration. Use PanacheMock.mock(Order.class) before method stubs.
Large native build times: GraalVM native compilation is slow (2-5 minutes). Use CI caching for native build artifacts.
Quarkus version conflicts: Extension versions must match Quarkus platform BOM. Use quarkus-bom in dependency management.
Reactive messaging retry not configured: Failed messages are retried indefinitely by default unless max-retries is configured on the connector.
Health endpoint exposed in production: Configure quarkus.health.extensions.enabled=false or secure health endpoint behind authentication.
Serialization issues with custom types: Register custom JBoss Marshalling serializer for types used in cluster replication or messaging.
mvn quarkus:test — tests re-run on code changes in dev mode.| Feature | Quarkus | Spring Boot | Micronaut |
|---|---|---|---|
| Startup time (JIT) | ~0.3s | ~2-4s | ~0.4s |
| Startup (GraalVM native) | <0.1s | ~0.5s | <0.1s |
| Memory (JIT) | ~50MB | ~150MB | ~40MB |
| Memory (native) | ~15MB | ~50MB | ~10MB |
| Reactive support | First-class | Via WebFlux | First-class |
| Live reload | Yes (dev mode) | Via DevTools | Yes |
| GraalVM support | First-class | Limited | First-class |
| Extension ecosystem | 200+ | 2000+ | 100+ |
| Tool | Purpose |
|---|---|
| Quarkus CLI | Project creation, dev mode, build |
| Quarkus Maven/Gradle Plugin | Build integration |
| Dev UI | Web-based development dashboard |
| SmallRye OpenAPI | OpenAPI spec generation |
| Panache | Simplified Hibernate ORM |
| RESTEasy Reactive | Reactive REST endpoints |
| SmallRye Reactive Messaging | Event-driven messaging |
| Hibernate Reactive | Reactive database access |
| Testcontainers | Integration test containers |
| GraalVM | Native image compilation |
| Container-first Docker | Optimized container images |
Hand off to backend/universal/api-response/SKILL.md for API response formats.