Created
October 25, 2023 06:05
-
-
Save mayankchoubey/9cda029f66fcb1b61c7934ca6686513a to your computer and use it in GitHub Desktop.
Quarkus - URL shortener service in PostgreSQL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| quarkus.datasource.db-kind=postgresql | |
| quarkus.datasource.username=${dbUser} | |
| quarkus.datasource.password=${dbUserPass} | |
| quarkus.datasource.reactive.url=postgresql://localhost:5432/${dbName} | |
| quarkus.datasource.reactive.max-size=10 | |
| quarkus.http.port=3000 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.example; | |
| import java.time.LocalDateTime; | |
| import io.vertx.mutiny.sqlclient.Row; | |
| public record ShortenedUrl( | |
| String id, | |
| String srcurl, | |
| LocalDateTime created, | |
| LocalDateTime lastaccessed) { | |
| public static ShortenedUrl of(String id, String srcurl, LocalDateTime created, LocalDateTime lastaccessed) { | |
| return new ShortenedUrl(id, srcurl, created, lastaccessed); | |
| } | |
| public static ShortenedUrl from(Row row) { | |
| return new ShortenedUrl( | |
| row.getString("id"), | |
| row.getString("srcurl"), | |
| row.getLocalDateTime("created"), | |
| row.getLocalDateTime("lastaccessed")); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.example; | |
| public class UrlShortenerError { | |
| private String errMsg; | |
| public UrlShortenerError() { | |
| } | |
| public UrlShortenerError(String errMsg) { | |
| this.errMsg = errMsg; | |
| } | |
| public String getErrMsg() { | |
| return this.errMsg; | |
| } | |
| public void setErrMsg(String errMsg) { | |
| this.errMsg = errMsg; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.example; | |
| import io.smallrye.mutiny.Multi; | |
| import io.smallrye.mutiny.Uni; | |
| import io.vertx.mutiny.pgclient.PgPool; | |
| import io.vertx.mutiny.sqlclient.Row; | |
| import io.vertx.mutiny.sqlclient.RowSet; | |
| import io.vertx.mutiny.sqlclient.Tuple; | |
| import jakarta.enterprise.context.ApplicationScoped; | |
| import jakarta.inject.Inject; | |
| import org.slf4j.Logger; | |
| import org.slf4j.LoggerFactory; | |
| import java.util.UUID; | |
| import java.util.function.Function; | |
| import java.util.stream.StreamSupport; | |
| import com.example.ShortenedUrl; | |
| @ApplicationScoped | |
| public class UrlShortenerRepository { | |
| @Inject | |
| private PgPool client; | |
| public UrlShortenerRepository(PgPool _client) { | |
| this.client = _client; | |
| } | |
| public Uni<ShortenedUrl> save(ShortenedUrl data) { | |
| return this.client | |
| .preparedQuery("INSERT INTO shortenedurls (id, srcurl, created, lastaccessed) VALUES ($1, $2, $3, $4) RETURNING *") | |
| .execute(Tuple.of(data.id(), data.srcurl(), data.created(), data.lastaccessed())) | |
| .onItem().transform(RowSet::iterator) | |
| .onItem().transform(iterator -> iterator.hasNext() ? ShortenedUrl.from(iterator.next()) : null); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.example; | |
| public class UrlShortenerRequest { | |
| private String srcUrl; | |
| public String getSrcUrl() { | |
| return this.srcUrl; | |
| } | |
| public void setSrcUrl(String srcUrl) { | |
| this.srcUrl = srcUrl; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.example; | |
| import io.smallrye.mutiny.Uni; | |
| import jakarta.enterprise.context.RequestScoped; | |
| import jakarta.inject.Inject; | |
| import jakarta.validation.Valid; | |
| import jakarta.ws.rs.*; | |
| import jakarta.ws.rs.core.MediaType; | |
| import jakarta.ws.rs.core.Response; | |
| import java.net.URI; | |
| import java.util.UUID; | |
| import java.util.logging.Logger; | |
| import static jakarta.ws.rs.core.Response.*; | |
| import io.vertx.mutiny.pgclient.PgPool; | |
| import com.example.UrlShortenerRequest; | |
| import com.example.UrlShortenerResponse; | |
| import com.example.UrlShortenerError; | |
| import java.time.LocalDateTime; | |
| import com.aventrix.jnanoid.jnanoid.*; | |
| @Path("/shorten") | |
| @RequestScoped | |
| public class UrlShortenerResource { | |
| final String baseUrl = "http://test.short/"; | |
| @Inject | |
| PgPool client; | |
| @Inject | |
| UrlShortenerRepository shortenerRepository; | |
| @POST | |
| @Consumes(MediaType.APPLICATION_JSON) | |
| @Produces(MediaType.APPLICATION_JSON) | |
| public Uni<Response> handleRequest(@Valid UrlShortenerRequest shortenRequest) { | |
| if(shortenRequest.getSrcUrl() == null) { | |
| return Uni.createFrom() | |
| .item( | |
| Response.status(400) | |
| .type(MediaType.APPLICATION_JSON) | |
| .entity(new UrlShortenerError("Parameter 'srcUrl' is missing")) | |
| .build()); | |
| } | |
| String srcUrl = shortenRequest.getSrcUrl(); | |
| if(srcUrl.length()>250) { | |
| return Uni.createFrom() | |
| .item( | |
| Response.status(400) | |
| .type(MediaType.APPLICATION_JSON) | |
| .entity(new UrlShortenerError("Parameter 'srcUrl' must not be more than 250 characters")) | |
| .build()); | |
| } | |
| if(!(srcUrl.startsWith("http://") || srcUrl.startsWith("https://"))) { | |
| return Uni.createFrom() | |
| .item( | |
| Response.status(400) | |
| .type(MediaType.APPLICATION_JSON) | |
| .entity(new UrlShortenerError("Parameter 'srcUrl' must start with http:// or https://")) | |
| .build()); | |
| } | |
| String urlId = NanoIdUtils.randomNanoId( | |
| NanoIdUtils.DEFAULT_NUMBER_GENERATOR, | |
| NanoIdUtils.DEFAULT_ALPHABET, | |
| 10 | |
| ); | |
| String shortUrl = baseUrl + urlId; | |
| ShortenedUrl shortenedUrl = new ShortenedUrl( | |
| urlId, | |
| srcUrl, | |
| LocalDateTime.now(), | |
| LocalDateTime.now()); | |
| Uni<ShortenedUrl> shortUrlData = this.shortenerRepository.save(shortenedUrl); | |
| return shortUrlData.map(shortenedUrlData -> { | |
| if(shortenedUrlData.id() == null) { | |
| return Response.status(500) | |
| .type(MediaType.APPLICATION_JSON) | |
| .entity(new UrlShortenerError("Failed to shorten")) | |
| .build(); | |
| } | |
| UrlShortenerResponse resp = new UrlShortenerResponse(srcUrl, shortUrl); | |
| return Response.ok() | |
| .type(MediaType.APPLICATION_JSON) | |
| .entity(resp) | |
| .build(); | |
| }); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.example; | |
| public class UrlShortenerResponse { | |
| private String srcUrl; | |
| private String shortenedUrl; | |
| public UrlShortenerResponse() { | |
| } | |
| public UrlShortenerResponse(String srcUrl, String shortenedUrl) { | |
| this.srcUrl = srcUrl; | |
| this.shortenedUrl = shortenedUrl; | |
| } | |
| public String getSrcUrl() { | |
| return this.srcUrl; | |
| } | |
| public void setSrcUrl(String srcUrl) { | |
| this.srcUrl = srcUrl; | |
| } | |
| public String getShortenedUrl() { | |
| return this.shortenedUrl; | |
| } | |
| public void setShortenedUrl(String shortenedUrl) { | |
| this.shortenedUrl = shortenedUrl; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment