Skip to content

summaries

Miguel Gamboa edited this page Dec 13, 2024 · 55 revisions

Lessons:

  • SSR != CSR
  • IPW uses SSR (Server Side Rendering)
  • LS uses CSR (Client Side Rendering)
  • CSR => JavaScript + fetch API
  • FrontEnd with partial updates:
    • Example appending HTML fragment to an HTML page
  • BackEnd with Spring Framework (1st half of semester):
    • Equivalent do Express in IPW but with different approach and tech (JVM)
    • Spring may be used with an HTTP Server such as jetty, Tomcat, or other
  • FrontEnd (2nd half of semester):
    • React library and TypeScript programming language
    • WebPack module bundler

  • Build the Spring project and run the jar
  • Comparing Spring Controllers != Express Routes
  • Annotation @RestController and annotation @GetMapping
  • Testing with the browser and in terminal with curl
  • Analyzing the Content-Type response header and Accept request header
  • Content negotiation

  • Homework:
    • Request curl -i http://localhost:8080/hello and the Content-Type is text/plain;charset=UTF-8
    • Request from a browser responds with Content-Type now text/html; charset=UTF-8.
    • QUESTION: Can you change the curl request command to has the response also with the text/html media type?
  • Controller life-cycle
  • Using logging statements and multiple HTTP requests observe how many ControllerExample instances are created?
    • One instance by default. This behavior can be changed.
  • Observe the identifiers of the threads where the handler methods are called.
    • One instance whose handlers (methods) are invoked by multiple threads
  • QUESTION: given the observations, what should be the restrictions to the instance state?

  • ControllerExample ----> ServiceGreetings (interface)
  • ControllerExample has a dependency of ServiceGreetings (interface):
    • We need an instance of a class compatible with ServiceGreetings to instantiate ControllerExample
  • Spring has to resolve the dependency.
  • How Spring instantiates ControllerExample?
    • ERROR: Parameter 0 of constructor in ControllerExample required a bean of type 'ServiceGreetings' that could not be found.
  • Class implementing ServiceGreetings must have the @Component annotation.
  • Classpath scanning and managed components - @Component
  • Bean - "an object that is instantiated, assembled, and managed by a Spring container".
  • Spring Container is called Context

  • Review Spring Basics: Controller, Handlers, Component and Bean.

  • Implementation of a simple DI and IoC function loadInstanceOf(klass: KClass<T>) : T

  • Context - In the Spring Framework, the IoC container is often referred to as context.
  • AnnotationConfigApplicationContext - scan(), refresh(), getBean()
  • Scope: singleton (by default) versus prototype
  • Lists injection
  • Example of MovieLister --> MovieFinder --> DataSourceClientViaHttpClient --> HttpClient
  • @Bean - marks a bean function

  • HTTP servlet API: HttpServlet and HttpFilter
    • HttpServlet: doGet(HttpServletRequest, HttpServletResponse)
    • HttpFilter: doFilter(HttpServletRequest, HttpServletResponse, FilterChain)
  • Servlet Container:
    • implements and manages instances of HttpServletRequest, HttpServletResponse, FilterChain.
    • "contains and manages servlets through their lifecycle."
    • e.g. Jetty, Tomcat, etc
  • Servlet and Filter Pipeline
  • E.g. running ExampleServlet and ExampleFilteron Tomcat or Jetty
  • HTTP Servlet API ◄--- Spring MVC ---> Servlet Container
  • @PathVariable - Binding path variables to arguments.
  • @RequestParam - Binding query string values to arguments (Nullable for optional).
  • @RequestBody - Binding HTTP request body in JSON to an argument.
  • Bean Validation - "Express validation rules in a standardized way using annotation-based constraints"
  • Dependency => spring-boot-starter-validation => @Valid
  • Built-in return value handling in Spring: String and JSON

  • WebMvcConfigurer - configure Argument Resolvers and Message Converters
    • HandlerMethodArgumentResolver
    • AbstractGenericHttpMessageConverter => Processing the HTTP body (request and/or response).
  • Filters -> DispatcherServlet -> Interceptors -> Arg resolution | Return value handling -> Handlers
  • HandlerMethod - represents a Spring handler in a Controller instance.
  • Review - Spring Web MVC provides:
    • DI + Controllers/Handlers management + HTTP Server integration
    • Mapping between HTTP protocol <-> Controller handlers
  • Why a Service?
  • Service --> Domain <-- Repository
  • Different implementations of Repository: JDBI, JPA, other.
  • Domain model:
    • immutable;
    • no side-effects;
    • has no dependencies on Service or Repository.
  • Use case for Agendify web app (~ e.g. Doodle)
  • Testing the Service with Repositories mocks.
  • MockK - mocking library for Kotlin.

  • Maintain the domain model with associations that have single multiplicity.
  • Managing Many-to-One relationships at the Repository Level.
  • Manage Database connections and transactions;
  • TransactionManager ---new--> Transaction --uses/new-->* Repository
/**
 * block > operations using the repositories provided by a Transaction, 
 * e.g. createParticipant:
 * 1. repoParticipants.findByEmail(email) // return Failure if already exist
 * 2. repoParticipants.createParticipant(name, email, kind)
 */
interface TransactionManager { fun <R> run(block: Transaction.() -> R) : R }
  • TransactionManager life-cycle managed by DI/IoC container
  • Transaction life-cycle out of the scope of the DI/IoC container (managed by a TransactionManager).
  • Either<L,R> - Strongly typed representation of failure.
  • Controller should handle all types of Failure (i.e. Either.Left) returned by a Service.
  • RFC 7807 - Problem Details for HTTP APIs
  • Auxiliary sealed class Problem to manage application/problem+json responses.
  • WebTestClient

  • JDBI (Java Database Interface) - high-level library that simplifies JDBC interactions.
  • JDBI Handle - connection wrapper that manages database interaction and lifecycle.
  • repository-jdbi - TransactionManager on run(block):
    1. manages an Handle per Transaction;
    2. a Transaction instantiates repositories with given Handle.
  • repository-jdbi folders:
    • /src/sql contains create-schema.sql
    • /tests contains docker file Dockerfile-db-test to build a Docker image to run Postgres.
    • /tests/scripts/wait-for-postgres.sh - checks when PostgreSQL is running and ready to accept connections.
  • Dockerfile <--- Image <---* Container:
    • Dockerfile: contains instructions for building a Docker image.
    • Image: read-only template used to create containers.
    • Container: isolated execution environment that packages an application and its dependencies.
  • "The same way that processes are created from executable files, containers are created from container images."
  • Running Service tests with different repository implementations, such as in-memory and JDBI.
  • Junit Jupiter API for @ParameterizedTest and @MethodSource
  • Make the Gradle test task dependent on Docker Compose to manage the PostgreSQL container lifecycle.
  • Docker Compose tool for running multi-container Docker applications:
    • Service: Represents a single container, e.g. db-tests
    • docker-compose.yml - configuration file.
    • docker compose up - start the application by creating and starting all services.
    • docker-compose down - stops and removes containers.
  • Syntax style rules and enforcement, e.g. using ktlint
  • Continuous integration and continuous check, e.g. using GitHub actions
  • Using secrets in GitHub Actions
  • Project agendify class Environment gets DB_URL from env variable.
  • Running http-api tests with different implementations of repository: in-memory and JDBI.
  • Context configuration with Profiles:
    • spring.main.allow-bean-definition-overriding=true
    • @Profile- associate a Bean or configuration to a Profile
    • @ActiveProfiles - select the profile to be activated with the context.
  • Module host
  • Authentication flow:
    1. 👤 -- username/password --------------> login --> token
    2. 👤 -- Authorization: Bearer <token> --> validate; find user; ...
    3. 👤 -- Authorization: ... ...
  • Bearer authentication scheme
  • TokenEncoder:
    • takes a token and produces a validation information that can be stored in the database.
    • the token should be hard to compute from this information, but easy to validate.
  • Configurations: TTL and maximum number of tokens per user.
  • HTTP pipeline:
    1. AuthenticationInterceptor:
      1. Checks if the handler requires authentication.
      2. If so, verifies the token and retrieves the associated user.
      3. Add an AuthenticatedUser object to the request attributes.
    2. AuthenticatedUserArgumentResolver
      1. Applied to handlers with an AuthenticatedUser argument.
      2. Retrieves the AuthenticatedUser object from the request attributes.
  • Using client established connections to send server initiated events.
  • Sending events in the context of an unfinished response.
  • The Server-sent Events specification, namely its media-type: text/event-stream
  • Last-Event-ID HTTP request header and the EventSource object reestablishing the connection.
  • Keep Alice ~ comment line (one starting with a : character)
  • Spring MVC support for the SSE specification: SseEmitter class.
  • Implementing route on Agendify Web App to listen SSE for updated TimeSlot instances.
  • TypeScript type system.
  • Primitive types: string, number, and boolean.
  • Type any
  • Object types.
  • Optional properties - <prop name>?:...
  • Structural Type System:
    • "type checking focuses on the shape that values have."
  • Type alias - a name for any type. Syntax: type <name> = ...
  • interface => an open type, which is always extendable.
  • Unions, discriminated unions, and type narrowing.
  • Generics
  • Arrays
  • See: TypeScript for JavaScript Programmers

  • HTML tag script to embed or refer to JavaScript code.
  • Without modules support:
    • No isolation between different JS files
    • Declarations visible in global scope
  • Demo: conflict between top-level declarations in different JS files
  • <script type="module" ... - causes the code to be treated as an ES module:
    • The processing of the script contents is deferred
    • That module may import other ES modules => HTTP request to that resource.

  • Common JS modules via JS API: object exports and function require
  • EcmaScript modules keywords: export and import
  • Demo: main.js --> lib1.js --> lib2.js
  • Comparing dependency resolution on Node vs Browser--HTTP server
  • NO native Browser support for Common JS modules

  • The motivation for an application build step:
    • transforming the source files into the resources provided to the browser.
  • Bundling may include:
    • reduction of the HTTP requests needed to load the script resources.
    • Minification - reduction of the script size.
    • "transpiling" (Source-to-source compiler):
      • translate different language on the source files, namely TypeScript.
      • translate unsupported Browser features, e.g. Common JS.
  • webpack and webpack-cli:
    • src and dist
    • bundling, minifying and "transpiling"
  • GUI development approaches: From Imperative to Declarative:
    • Imperative e.g. AWT, Windows Forms, GWT, others
    • Declarative e.g. React, Jetpack Compose, Flutter, others
  • React approach:
    • GUI = Tree
    • State is Immutable
    • life-cycle: S1 -> S2 -> ... -> SN
    • f(model) => Tree
  • Frontend Dev Environment:
    • Dev dependencies: Webpack, Typecript, React and React DOM
    • Config: Typecript and Webpack config: ts-loader
    • HTTP server: serve, webpack-dev-server, or other
  • React and ReactDom API
  • Virtual Tree != DOM Tree
  • JSX:
    • Syntax extension for JavaScript that lets you write HTML-like markup within JavaScript
    • Like a web template syntax WITHOUT the need of special control flow dialects like #each, :each, and others
  • Reconciliation: Virtual Tree => DOM Tree
    • "React can decide exactly which components in the tree need re-rendering and skip over the ones that don’t."
  • Defining components and creating elements using components.
  • React Components as pure functions:
    • Idempotent – the same result for the same inputs
    • No side effects
    • Does not mutate non-local values:
  • React Components:
    • Never call component functions directly
    • Don’t call them as regular functions.
    • Components should only be used in JSX.
    • React should call it.
  • Passing properties JSX to React Component
  • "Components need to "remember" things"
  • State => "A Component's Memory"
  • How to manage State in Functional Components?
    • Global State?? AVOID mutable global state
    • Instance Fields?? NO Gui components through classes definition
    • Closures?? NO adequate isolation
  • DON'T DO THIS:
let count = 0
function Counter({}) {
  return (
    <div>
      <button onClick={() => {count++; root.render((<Counter/>))}}>
        +
      </button>
  ...
  • Hooks: special functions ONLY available while React is rendering
  • let you “hook into” different React features.
  • You “use” React features at the top of your component, similar to how you “import” modules at the top of your file.
  • E.g. useState, you are telling React that you want this component to remember something.
  • WITHOUT a conditional order between several uses of useSate()!!!!
  • Hooks rely on a stable call order on every render of the same component.
  • useState gives you an array containing 2 values:
    • The state variable with the value you stored.
    • The state setter function .
      • => trigger React to render the component again.
  • State is ISOLATED and PRIVATE
  • If you render the same component twice, each copy will have completely isolated state!
  • State is fully private to the component declaring it.
  • State management reviews;
  • Example: implementation of a TextFieldValidator Component.

  • REMEMBER: React Components as pure functions:
    • Idempotent – the same result for the same inputs
    • Does not mutate non-local values:
    • No side effects
  • DON'T DO THIS: Example of a recursive loop caused by improper use of side effects:
function FetchAndShow({uri}: {uri: string}) {
    const [respBody, setRespBody] = React.useState("")
    fetch(uri) /* DON'T DO THIS!!!! */
        .then(resp => resp.text())
        .then(body => setRespBody(body) /* Runs after rendering is complete */ )
    return (...)
}
  • Infinite recursion: render -> FetchAndShow() -> fetch -> render completion -> fetch completion -> setRespBody -> render -> FetchAndShow() -> fetch -> render completion -> fetch completion -> setRespBody -> render -> ...
  • Effects - Run after render.
  • useEffect(callback, [dependency, ...]) - schedule an effect
  • effect dependencies:
    • array of values;
    • if present, effect will only activate if the values in the list change.
  • useEffect(() => { ... return Cleanup Function }, [dependency, ...])
  • Cleanup Function
    • called if a component is Unmounted.
    • called each time before the Effect runs again.
  • Some operations, such as fetch, cannot be easily canceled:
    • In that case, we may choose to cancel subsequent UI updates.
  • Example: implementation of a StopWatch Component.

  • WeakChecker: React component to check for security leaks, such as length, use of numbers, special characters, avoidance of common weak passwords, etc.
    • version 1: synchronous validation.
    • version 2: asynchronous validation through an external service.
  • Validate password only after user stops typing => use setTimeout
  • !!! RACE condition between last validation error and current input value.
  • reduce: function reduce(State, Action): State
  • const [state, dispatch]: useReducer(reduce, { <Initial State> })
  • React Component => dispatch(<instance of Action>)

  • server-side routing <versus> client-side routing
  • The concept of client-side routing.
  • The browser history API for changing the navigation history.
  • Introduction to the React Router library.
  • Redirection between routes.
  • <Outlet> - in parent route elements to render their child route elements.

  • Deep Linking
  • Webpack devServer.historyApiFallback - using the HTML5 History API, the index.html page will likely have to be served in place of any 404 responses

  • Origin: combination of a scheme (e.g. HTTP or HTTPS), a hostname, and a port.
  • CORS - cross origin resource sharing
  • A server returning Access-Control-Allow-Origin: * means that the resource can be accessed by any ORIGIN.
  • Using the webpack-dev-server to proxy requests to the HTTP API, as a way to avoid cross-origin requests.

  • Using Cookies for storing and transporting authentication tokens.
  • Comparison between Cookie usage and the Authorization header with explicit storage.
  • Set-Cookie attributes:
    • The httpOnly attribute and the protection against XSS attacks.
    • The SameSite attribute and the protection against CSRF attacks.
    • The secure attribute.

  • The context concept in React.
  • React Context API:
    • Definition:
      1. Define the type of context T
      2. createContext<T>(): Context<T>: Creates a new context object for the type T.
      3. Context<T>.Provider: A React component used to provide the context value to its descendants.
    • Provider:
      • Supplies a value to its descendants via the Context<T>.Provider component, e.g. used in JSX.
    • Consumers:
      • Components that are descendants of the Provider and access the context value.
      • Use the useContext(Context<T>): T hook to consume the provided context value.

  • React Context API
  • Example: ThemeContextType, ThemeContext, ThemeProvider, ThemeSwitcher
  • Example for Authentication: AuthContextType, AuthContext, AuthProvider
  • Example of Authentication consumers:
    • Home - displays logged user profile
    • Login - updates logged user via setUser of the AuthContext
    • AuthRequire - wraps Components requiring authentication and redirects to Login
  • React Router DOM:
    • Navigate component
    • Location - contains information about the URL path, as well as possibly some arbitrary state and a key.

  • Login form
  • Distinguish between SSR redirect and CSR redirect.
  • Form state machine: editing, submitting, redirect
  • Form actions: edit, submit, success, error
  • Playwright - Automation framework for Browser Testing.
  • Playwright supports rendering engines including Chromium, WebKit, and Firefox.
  • Installation through npm init playwright@latest:
    1. Name of your Tests folder (default is tests)
    2. Add a GitHub Actions workflow to easily run tests on CI
    3. Install Playwright browsers (default is true)
  • Scripts on package.json:
    • "test": "npx playwright test"
    • "test-report": "npx playwright show-report"
  • Configure local dev server on playwright.config.ts:
webServer: {
  command: 'npm run start',
  url: 'http://127.0.0.1:8000',
  reuseExistingServer: !process.env.CI,
}
  • assemble - builds a fat or Uber JAR containing the application classes and all dependency JARs.
  • ./gradlew :lesson15-host:assemble ---> lesson15-host-0.1.0-SNAPSHOT.jar (fat or Uber JAR):
    • META-INF - Contains metadata, including the MANIFEST.MF with metadata such as the main class and classpath.
    • BOOT-INF/lib - all the external dependencies (JAR files), e.g. jackson-annotations-2.17.2.jar, lesson09-agendify-domain-0.1.0.jar, etc
    • BOOT-INF/classes - your application's compiled classes, e.g. AppAgendify.class, Environment.class, etc
    • org/springframework/boot/loader/ - classes responsible for loading the Spring Boot application from the Uber JAR.
  • Build JVM Image with agendify Spring MVC web application:
    1. assemble - builds the Uber Jar
    2. extractUberJar - extract classes and JARs from the Uber JAR into build/dependency folder
    3. Uses the openjdk:21 image as the base and copies the extracted contents from build/dependency to the container's /app directory.

  • Load balancing
  • Improving performance via horizontal scaling.
  • High availability by using multiple nodes.
  • Balancing policies, such as "round-robin".
  • Retry policies.
Clone this wiki locally