Slide 1

Slide 1 text

No content

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

FacesServlet

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

- Vorteil: Nutzung der HTTP Semantik (z.B. Verben) möglich - Implementierungen müssen Adapter für JSP und JSF bereitstellen − −

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

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' //… }

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

import javax.ws.rs.ApplicationPath; import javax.ws.rs.core.Application; @ApplicationPath("/mvc") public class App extends Application { }

Slide 12

Slide 12 text

Hello World

Hello World!

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"; } }

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

No content

Slide 15

Slide 15 text

@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"; } // ...

Slide 16

Slide 16 text

@Path("/bookings") @Controller public class BookingController { // ... @Inject private Models models; @GET public String showIndex() { // ... models.put("bookings", bookings); return "index.jsp"; } // ... } ${booking.bookingNumber} ${booking.name} …

Slide 17

Slide 17 text

@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"; } // ... }

Slide 18

Slide 18 text

@Inject private Models models; ${booking.bookingNumber} ${booking.name} … @Path("/bookings") @Controller public class BookingController { // ... @Inject private Models models; @GET public String showIndex() { // ... return "index.jsp"; } // ... }

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

@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(); } } // ...

Slide 21

Slide 21 text

@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 { // ... } }

Slide 22

Slide 22 text

@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(); } }

Slide 23

Slide 23 text

No content

Slide 24

Slide 24 text

Slide 25

Slide 25 text

Slide 26

Slide 26 text

Slide 27

Slide 27 text

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

@Path("/bookings") @Controller public class BookingController { // ... @GET @Path("/new") public String showNewBookingForm() { return "form.jsp"; } // ... }

Slide 34

Slide 34 text

Name
Save

Slide 35

Slide 35 text

// ... @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(); } // ...

Slide 36

Slide 36 text

${msg.get("form.label.name")}
${error.getParamName()}: ${error.getMessage()}
${msg.get("form.btn.save")}

Slide 37

Slide 37 text

No content

Slide 38

Slide 38 text

• •

Slide 39

Slide 39 text

Name
Save

Slide 40

Slide 40 text

No content

Slide 41

Slide 41 text

No content

Slide 42

Slide 42 text

No content

Slide 43

Slide 43 text

Name
Save

Slide 44

Slide 44 text

@POST @CsrfProtected public String createNewBooking(@MvcBinding @FormParam("name") @NotBlank @Size(min = 5, max = 255) final String name) { // ... }

Slide 45

Slide 45 text

No content

Slide 46

Slide 46 text

// ... @DELETE @Path("/{bookingNumber}") public String cancelBooking(@PathParam("bookingNumber") final UUID bookingNumber) { final var isCancelled = bookingService.cancelBooking(bookingNumber); return isCancelled ? "redirect:/bookings" : "404.jsp"; } // ...

Slide 47

Slide 47 text

No content

Slide 48

Slide 48 text

Cancel

Slide 49

Slide 49 text

No content

Slide 50

Slide 50 text

/** *

Locale resolvers are used to determine the locale of the current request and are * discovered using CDI. *

* * … */ public interface LocaleResolver { /** *

Resolve the locale of the current request given a {@linkLocaleResolverContext}.

* * … * * @param context the context needed for processing. * @return The resolved locale or null. */ Locale resolveLocale(LocaleResolverContext context); }

Slide 51

Slide 51 text

/** *

Locale resolvers are used to determine the locale of the current request and are * discovered using CDI. *

* * … */ public interface LocaleResolver { /** *

Resolve the locale of the current request given a {@linkLocaleResolverContext}.

* * … * * @param context the context needed for processing. * @return The resolved locale or null. */ Locale resolveLocale(LocaleResolverContext context); } org.eclipse.krazo.locale.LocaleResolverChain MvcContext

Slide 52

Slide 52 text

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!

Slide 53

Slide 53 text

@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); } }

Slide 54

Slide 54 text

<%@ page contentType="text/html;charset=UTF-8" language="java" %> ${msg.get("page.title")}

${msg.get("hello.world")}

Slide 55

Slide 55 text

//messages.properties My awesome application

Hello World!

//messages_fr.properties My awesome application

Bonjour le monde!

//messages_de.properties My awesome application

Hallo Welt!

Slide 56

Slide 56 text

No content

Slide 57

Slide 57 text

No content