Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Webanwendungen mit der MVC API und Eclipse Krazo

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on. →

Webanwendungen mit der MVC API und Eclipse Krazo

Avatar for Tobias Erdle

Tobias Erdle

January 23, 2020

More Decks by Tobias Erdle

Other Decks in Programming

Transcript

  1. - Vorteil: Nutzung der HTTP Semantik (z.B. Verben) möglich -

    Implementierungen müssen Adapter für JSP und JSF bereitstellen − −
  2. plugins { id 'java' id 'war' } repositories { jcenter()

    mavenCentral() } dependencies { //… implementation 'javax.mvc:javax.mvc-api:1.0.0‘ implementation 'org.eclipse.krazo:krazo-resteasy:1.0.0‘ // implementation 'org.eclipse.krazo.ext:krazo-thymeleaf:1.0.0' providedCompile 'jakarta.platform:jakarta.jakartaee-web-api:8.0.0' //… }
  3. <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Hello World</title> </head>

    <body> <h1>Hello World!</h1> </body> </html> import javax.mvc.Controller; import javax.ws.rs.GET; import javax.ws.rs.Path; @Path("hello") @Controller public class HelloWorldController { @GET public String sayHello() { return "hello.jsp"; } }
  4. @Path("/bookings") @Controller public class BookingController { // ... @Inject private

    Models models; @GET public String index() { final var bookings = bookingService.getAllBookings(); models.put("bookings", bookings); return "index.jsp"; } // ...
  5. @Path("/bookings") @Controller public class BookingController { // ... @Inject private

    Models models; @GET public String showIndex() { // ... models.put("bookings", bookings); return "index.jsp"; } // ... } <c:forEach var="booking" items="${bookings}"> <tr> <td>${booking.bookingNumber}</td> <td>${booking.name}</td> … </c:forEach>
  6. @Path("/bookings") @Controller public class BookingController { // ... @Inject private

    Models models; @GET public String showIndex() { final var bookings = bookingService.getAllBookings(); models.put("bookings", bookings); return "index.jsp"; } // ... }
  7. @Inject private Models models; <c:forEach var="booking" items="${bookings}"> <tr> <td>${booking.bookingNumber}</td> <td>${booking.name}</td>

    … </c:forEach> @Path("/bookings") @Controller public class BookingController { // ... @Inject private Models models; @GET public String showIndex() { // ... return "index.jsp"; } // ... }
  8. @Path("/bookings") @Controller public class BookingController { // ... @GET @Path("/{bookingNumber}")

    public Response showDetailsOfBooking(@PathParam("bookingNumber") final UUID bookingNumber) { final var booking = bookingService.findBookingForBookingNumber(bookingNumber); if (booking.isPresent()) { models.put("booking", booking.get()); return Response.ok("details.jsp").build(); } else { models.put("bookingNumber", bookingNumber); return Response.status(Response.Status.NOT_FOUND).entity("404.jsp").build(); } } // ...
  9. @GET @Path("/{bookingNumber}") public Response showDetailsOfBooking( @PathParam("bookingNumber") final UUID bookingNumber) {

    // ... if (booking.isPresent()) { models.put("booking", booking.get()); return Response.ok("details.jsp").build(); } else { // ... } }
  10. @GET @Path("/{bookingNumber}") public Response showDetailsOfBooking( @PathParam("bookingNumber") final UUID bookingNumber) {

    // ... if (booking.isPresent()) { // ... } else { models.put("bookingNumber", bookingNumber); return Response .status(Response.Status.NOT_FOUND) .entity("404.jsp") .build(); } }
  11. <a class="btn btn-link" href="${mvc.uriBuilder('BookingController#showDetailsOfBooking').build(booking.bookingNumber)}"> Details </a> @Path("/bookings") @Controller public class

    BookingController { // ... @GET @Path("/{bookingNumber}") public String showDetailsOfBooking(@PathParam("bookingNumber") final UUID bookingNumber) { // ... } // ...
  12. <a class="btn btn-link" href="${mvc.uriBuilder('showBookingDetails').build(booking.bookingNumber)}">Details </a> @Path("/bookings") @Controller public class BookingController

    { // ... @GET @Path("/{bookingNumber}") @UriRef("showBookingDetails") public String showDetailsOfBooking(@PathParam("bookingNumber") final UUID bookingNumber) { // ... } // ...
  13. @Path("/bookings") @Controller public class BookingController { // ... @GET @Path("/new")

    public String showNewBookingForm() { return "form.jsp"; } // ... }
  14. <form method="post" action="${mvc.uri('BookingController#createNewBooking')}"> <div class="form-row"> <div class="col-md-6"> <label for="name">Name</label> <input

    id="name" name="name" class="form-control" placeholder="Name of booking" required> </div> </div> <div class="form-row mt-2"> <div class="col-md-3"> <button type="submit" class="btn btn-primary">Save</button> </div> </div> </form>
  15. // ... @Inject private BindingResult bindingResult; @POST public String createNewBooking(@MvcBinding

    @FormParam("name") @NotBlank @Size(min = 5, max = 255) final String name) { if (bindingResult.isFailed()) { models.put("errors", new ArrayList<>(bindingResult.getAllErrors())); return "form.jsp"; } final var booking = bookingService.createNewBooking(name); return "redirect:/bookings/" + booking.getBookingNumber(); } // ... <input id="name" name="name" class="form-control" placeholder="Name of booking" required>
  16. <form method="post" action="${mvc.uri('BookingController#createNewBooking')}" accept-charset="UTF-8"> <div class="form-row"> <div class="col-md-6"> <label for="name">${msg.get("form.label.name")}</label>

    <input id="name" name="name" class="form-control" placeholder="${msg.get("form.label.name.placeholder")}" required> </div> </div> <c:choose> <c:when test="${not errors.isEmpty()}"> <div class="row mt-2"> <c:forEach var="error" items="${errors}"> <div class="col-md-12"> <div class="alert alert-danger">${error.getParamName()}: ${error.getMessage()}</div> </div> </c:forEach> </div> </c:when> </c:choose> <div class="form-row mt-2"> <div class="col-md-3"> <button type="submit" class="btn btn-primary">${msg.get("form.btn.save")}</button> </div> </div> </form>
  17. <form method="post" action="${mvc.uri('BookingController#createNewBooking')}"> <div class="form-row"> <div class="col-md-6"> <label for="name">Name</label> <input

    id="name" name="name" class="form-control" placeholder="Name of booking" required> </div> </div> <div class="form-row mt-2"> <div class="col-md-3"> <button type="submit" class="btn btn-primary">Save</button> </div> </div> </form>
  18. <form method="post" action="${mvc.uri('BookingController#createNewBooking')}"> <div class="form-row"> <div class="col-md-6"> <label for="name">Name</label> <input

    id="name" name="name" class="form-control" placeholder="Name of booking" required> </div> </div> <div class="form-row mt-2"> <input type="hidden" name="${mvc.csrf.name}" value="${mvc.csrf.token}"/> <div class="col-md-3"> <button type="submit" class="btn btn-primary">Save</button> </div> </div> </form>
  19. // ... @DELETE @Path("/{bookingNumber}") public String cancelBooking(@PathParam("bookingNumber") final UUID bookingNumber)

    { final var isCancelled = bookingService.cancelBooking(bookingNumber); return isCancelled ? "redirect:/bookings" : "404.jsp"; } // ...
  20. <form class="d-inline" method="post" action="${mvc.uriBuilder('BookingController#cancelBooking').build(booking.bookingNumber)}" onsubmit="return confirm('Do you really want to

    cancel the booking?');"> <input type="hidden" name="_method" value="DELETE"> <button type="submit" class="btn btn-link">Cancel</button> </form>
  21. /** * <p>Locale resolvers are used to determine the locale

    of the current request and are * discovered using CDI. *</p> * * … */ public interface LocaleResolver { /** * <p>Resolve the locale of the current request given a {@linkLocaleResolverContext}.</p> * * … * * @param context the context needed for processing. * @return The resolved locale or <code>null</code>. */ Locale resolveLocale(LocaleResolverContext context); }
  22. /** * <p>Locale resolvers are used to determine the locale

    of the current request and are * discovered using CDI. *</p> * * … */ public interface LocaleResolver { /** * <p>Resolve the locale of the current request given a {@linkLocaleResolverContext}.</p> * * … * * @param context the context needed for processing. * @return The resolved locale or <code>null</code>. */ Locale resolveLocale(LocaleResolverContext context); } org.eclipse.krazo.locale.LocaleResolverChain MvcContext
  23. messages //messages.properties … #Index Page page.title=My awesome application #Hello World

    hello.world=Hello World! //messages_fr.properties #Hello World hello.world=Bonjour le monde! //messages_de.properties #Hello World hello.world=Hallo Welt!
  24. @RequestScoped @Named("msg") public class Messages { @Inject private MvcContext mvcContext;

    public final String get(final String key) { LOGGER.info(String.format("Getting message '%s' for locale '%s'", key, mvcContext.getLocale())); final var bundle = ResourceBundle.getBundle("messages", mvcContext.getLocale()); return bundle.containsKey(key) ? bundle.getString(key) : formatUnknownKey(key); } private static String formatUnknownKey(final String key) { return String.format("???%s???", key); } }
  25. <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html lang="en"> <head> <meta charset="UTF-8">

    <title>${msg.get("page.title")}</title> </head> <body> <h1>${msg.get("hello.world")}</h1> </body> </html>
  26. //messages.properties <html lang="en"> <head> <meta charset="UTF-8"> <title> My awesome application

    </title> </head> <body> <h1> Hello World! </h1> </body> </html> //messages_fr.properties <html lang="en"> <head> <meta charset="UTF-8"> <title> My awesome application </title> </head> <body> <h1> Bonjour le monde! </h1> </body> </html> //messages_de.properties <html lang="en"> <head> <meta charset="UTF-8"> <title> My awesome application </title> </head> <body> <h1> Hallo Welt! </h1> </body> </html>