Whatsit (DEMISED and moved to vertx-jax-rs)
A Toolkit to build web microservice using Vert.x
- JDK 17
- Maven
- JDK 17
- Vert.x
The whatsit-core library provides the following features:
- Application startup
- Set the environment variable, specify the config file for current env.
java -Dconfig.resource=local.conf -jar xxxx.jar
- Init the Application Context
- run the application.
import io.github.pangzixiang.whatsit.vertx.core.ApplicationRunner;
import io.github.pangzixiang.whatsit.vertx.core.ApplicationContext;
public class RunWhatsitCoreLocalTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new ApplicationContext();
// applicationContext.getApplicationConfiguration().setHttpServerOptions(new HttpServerOptions().setLogActivity(true));
// applicationContext.getApplicationConfiguration().setVertxOptions(new VertxOptions());
ApplicationRunner.run(applicationContext).onSuccess(unused -> {
deployVerticle(applicationContext.getVertx(), new TestVerticle());
});
}
}
- Static Config Management
We are using typesafe config to manage the config
- Controller
- Create a new Class to extend the BaseController Class and add @Path
- Create a new method with @Path method
- Finally, the application will automatically register the endpoint and deploy this Verticle.
import io.github.pangzixiang.whatsit.vertx.core.RestController;
import io.github.pangzixiang.whatsit.vertx.core.HttpRequestMethod;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.vertx.ext.web.RoutingContext;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
@Path("/v1")
public class SomeController extends BaseController {
@Path("/test")
@GET
public void someEndpoint(RoutingContext routingContext) {
sendJsonResponse(routingContext
, HttpResponseStatus.OK
, "something");
}
@Path("/echoTest")
@GET
public HttpResponse echoTest() {
log.info("Echo Controller handle request!");
return HttpResponse.builder().status(HttpResponseStatus.OK).data("echo").build();
}
@Path("/postBody")
@POST
// @Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public HttpResponse postTestBody(@RequestBody TestPojo body) {
log.info(body.toString());
return HttpResponse.builder().status(HttpResponseStatus.OK).data(body).build();
}
@Path("/echoHeader")
@GET
@Produces(MediaType.APPLICATION_JSON)
public HttpResponse echoTestHeader(@HeaderParam("test") String test) {
log.info("Echo Controller handle request!");
return HttpResponse.builder().status(HttpResponseStatus.OK).data(test).build();
}
@Path("/echo/{test}/{test2}")
@GET
public HttpResponse pathParamTest(@PathParam("test") boolean test, @PathParam("test2") boolean test2) {
log.info("received path param {} - {}", test, test2);
return HttpResponse.builder().status(HttpResponseStatus.OK).data(test&&test2).build();
}
@Path("/echo/query")
@GET
public HttpResponse queryParamTest(@QueryParam("test") String test, @QueryParam("test2") String test2) {
log.info("received path param {} - {}", test, test2);
return HttpResponse.builder().status(HttpResponseStatus.OK).data(test + test2).build();
}
@Path("/echo/form")
@POST
public HttpResponse queryParamTestForm(@FormParam("test") int test, @FormParam("test2") int test2) {
log.info("received path param {} - {}", test, test2);
return HttpResponse.builder().status(HttpResponseStatus.OK).data(test + test2).build();
}
@Path("/post")
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public void postTest(RoutingContext routingContext) {
log.info(routingContext.body().asString());
sendJsonResponse(routingContext, HttpResponseStatus.OK, routingContext.body().asString());
}
}
- Filter(Support Multiple Filters)
- Create a new Class to extend HttpFilter Class
- Override the doFilter method, adding your filter logic in it
- Add the filter to the Controller like:
import io.github.pangzixiang.whatsit.vertx.core.annotation.Filter;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
@Path("/test")
@GET
@Filter(filter = {xxx.class})
public void someEndpoint(RoutingContext routingContext){
sendJsonResponse(routingContext
,HttpResponseStatus.OK
,"something");
}
- logging
we are using logback to manage the log, if the 'config.resource' or 'config.file' not contains 'local' , then it will create the log file under the ./log folder, for details, please refer to whatsit-core/src/main/resources/logback.xml
- Database
- just to enable the DB connection via the conf file:
database: {
enable: true
url: "jdbc:h2:file:./h2/core-test-dev"
user: "sa"
password: ""
maxPoolSize: 4
eventLoopSize: 2
connectionTimeout: 30
idleTimeout: 60
}
- then you can get the jdbc pool from ApplicationContext.
- Schedule Job
- extend Class BaseScheduleJob
- put the logic to the abstract method 'execute'
- add Annotation 'Schedule' to the method 'execute'
- specify the period or delay to the Annotation or pass the config key into it
public class TestScheduleJob extends BaseScheduleJob{
public TestScheduleJob(ApplicationContext applicationContext) {
super(applicationContext);
}
@Override
@Schedule(configKey = "schedule.testJob")
// or @Schedule(periodInMillis = 10_000, delayInMillis = 0)
public void execute() {
// do some thing
}
}
config:
schedule: {
testJob: {
period: 30000
delay: 5000
}
}
- WebSocket
- create a controller class to extend AbstractWebSocketController and add @WebSocketAnnotation to the class
@Slf4j
@WebSocketAnnotation(path = "/ws")
public class TestWebSocketController extends AbstractWebSocketController {
public TestWebSocketController(ApplicationContext applicationContext, Vertx vertx) {
super(applicationContext, vertx);
}
@Override
public void startConnect(ServerWebSocket serverWebSocket) {
log.info(serverWebSocket.binaryHandlerID());
}
@Override
public Handler<WebSocketFrame> onConnect(ServerWebSocket serverWebSocket) {
return webSocketFrame -> {
log.info(webSocketFrame.textData());
serverWebSocket.writeTextMessage("ok");
};
}
@Override
public Handler<Void> closeConnect(ServerWebSocket serverWebSocket) {
return v -> {
log.info("Closed");
};
}
}
- finally it will be automatically registered.