Thursday, March 14, 2019

Spring Boot





Spring employs four key strategies:
  • ¡  Lightweight and minimally invasive development with plain old Java objects (POJOs)
  • ¡  Loose coupling through dependency injection and interface orientation
  • ¡  Declarative programming through aspects and common conventions
  • ¡  Boilerplate reduction through aspects and templates

The objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and otherwise managed by a Spring IoC container. 

POJO

Injection of dependencies
The act of creating associations between application components is the essence of dependency injection (DI) and is commonly referred to as wiring.

AOP:
Aspect-oriented programming is often defined as a technique that promotes separation of concerns within a software system.
System services such as logging, transaction management, and security often find their way into components whose core responsibility is something else. These system services are commonly referred to as cross-cutting concerns because they tend to cut across multiple components in a system.
In Spring, aspects are woven into Spring-managed beans at runtime by wrapping them with a proxy class. The proxy class poses as the target bean, intercepting advised method calls and forwarding those calls to the target bean. Between the time when the proxy intercepts the method call and the time when it invokes the target bean's method, the proxy performs the aspect logic.



Container:
Spring comes with several container implementations that can be categorized into two distinct types. Bean factories (defined by the org.springframework.beans.factory.BeanFactory interface) are the simplest of containers, providing basic support for DI. Application contexts (defined by the org.springframework.context.ApplicationContext interface) build on the notion of a bean factory by providing application framework services, such as the ability to resolve textual messages from a properties file and the ability to publish application events to interested event listeners.
The ApplicationContext container includes all functionality of the BeanFactorycontainer, so it is generally recommended over BeanFactory. BeanFactory can still be used for lightweight applications like mobile devices or applet-based applications where data volume and speed is significant.

Spring comes with several flavors of application context. The three that you’ll most likely encounter are

¡ ClassPathXmlApplicationContext—Loads a context definition from an XML file located in the classpath, treating context definition files as classpath resources.

¡ FileSystemXmlApplicationContext—Loads a context definition from an XML file in the file system.
¡ XmlWebApplicationContext—Loads context definitions from an XML file contained within a web application.



Annotations:
@SpringBootApplication is the combination of @Configuration@EnableAutoConfiguration and @ComponentScan annotations. 

@RestController annotation in Spring MVC is nothing but a combination of @Controller and @ResponseBody annotation. 

Read more: 
https://javarevisited.blogspot.com/2017/08/difference-between-restcontroller-and-controller-annotations-spring-mvc-rest.html#ixzz5hLnDcXlY

Common application properties:








Spring Boot

Make Spring coding easier.


·      AutoConfiguration

·      Spring Boot Starters

How to create Spring Boot cloud bootstrapping:


Spring Boot, Nginx and Docker:


Spring cloud vs. Kubernetes:





Combine them:




Develop a Spring Boot application for Kubernetes:




Spring Boot for GAE Standard:  see “Google Cloud Platform.pdf”

application.properties file:


Read properties from application.properties:

public class DemoApplication {
   @Value("${spring.application.name}")
   private String name;
   public static void main(String[] args) {
      SpringApplication.run(DemoApplication.class, args);
   }
   @RequestMapping(value = "/")
   public String name() {
      return name;
   }
}  
Enable DEBUG in application.properties:

#show sql statement
logging.level.org.hibernate.SQL=debug

#show sql values
logging.level.org.hibernate.type.descriptor.sql=trace

logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=DEBUG

Important:
Always run ‘mvn clean’ if you change the dependencies in pom.xml

AOP in Spring Boot:

Add following into pom.xml:

<dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

Add following annotation to Spring application:

@SpringBootApplication
@EnableAspectJAutoProxy(proxyTargetClass=true)
public class SpringBootHelloWorldApplication {
         public static void main(String[] args) {
                  SpringApplication.run(SpringBootHelloWorldApplication.class, args);
         }
}

Add AccessAspect.java:

package com.example.demoGAESpringBoot2;



import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.ProceedingJoinPoint;

import org.aspectj.lang.annotation.*;

import org.springframework.stereotype.Component;



@Aspect

@Component

public class AccessAspect {

    @Before(value = "execution(* com.example.demoGAESpringBoot2.DemoGaeSpringBoot2Application.addUser(..))")

    public void beforeAdvice(JoinPoint joinPoint) {

        System.out.println("Before method:" + joinPoint.getSignature());

    }



    @After(value = "execution(* com.example.demoGAESpringBoot2.DemoGaeSpringBoot2Application.addUser(..))")

    public void afterAdvice(JoinPoint joinPoint) {

        System.out.println("After method:" + joinPoint.getSignature());

    }



    @Around(value = "execution(* com.example.demoGAESpringBoot2.DemoGaeSpringBoot2Application.addUser(..))")

    public Object wrapResponse(ProceedingJoinPoint joinPoint) {

        StringBuilder str = new StringBuilder();



        str.append("Do decorations from Aspect class " + this.getClass().getCanonicalName());

        str.append("\n");

        str.append("The result from " + joinPoint.getSignature() + " is: \n");



        try {

            long start = System.currentTimeMillis();

            Object returnValue = joinPoint.proceed();

            if (!(returnValue instanceof String))

                return returnValue;

            str.append(returnValue);

            str.append("\n");

            str.append("Execution time is " + (System.currentTimeMillis() - start) + " ms.");

        }

        catch (Throwable e) {

            return e.toString();

        }



        return str.toString();

    }

}


You define an expression that matches (like a regular expression matches) points in the code. These points are called join points, while the expressions that match them are called pointcuts. You can then opt to execute additional, arbitrary code, called advice, when any pointcut or combination of pointcuts are matched. An object that defines pointcuts and advice is called an aspect.

Good website about AOP:


The technologies to implement AOP:  AOP is proxy-based.

·      JDK Dynamic Proxy: for the classes with interface
·      CGLib (and javassist): for the classes without interface



Websocket support:

This is outdated:
This is explained here:



HTTP is used only for the initial handshake, which relies on a mechanism built into HTTP to request a protocol upgrade (or in this case a protocol switch) to which the server can respond with HTTP status 101 (switching protocols) if it agrees. Assuming the handshake succeeds the TCP socket underlying the HTTP upgrade request remains open and both client and server can use it to send messages to each other.

The Spring Framework provides such transparent fallback options based on the SockJS protocol.

SockJS consists of:
·       The SockJS protocol defined in the form of executable narrated tests.
·       The SockJS JavaScript client - a client library for use in browsers.
·       SockJS server implementations including one in the Spring Framework spring-websocket module.
·       As of 4.1 spring-websocket also provides a SockJS Java client.
SockJS is designed for use in browsers. It goes to great lengths to support a wide range of browser versions using a variety of techniques. For the full list of SockJS transport types and browsers see the SockJS client page. Transports fall in 3 general categories: WebSocket, HTTP Streaming, and HTTP Long Polling.

WebSocket RFC defines the use of sub-protocols. During the handshake, the client and server can use the header Sec-WebSocket-Protocol to agree on a sub-protocol, i.e. a higher, application-level protocol to use. The use of a sub-protocol is not required, but even if not used, applications will still need to choose a message format that both the client and server can understand. That format can be custom, framework-specific, or a standard messaging protocol.
The Spring Framework provides support for using STOMP — a simple, messaging protocol originally created for use in scripting languages with frames inspired by HTTP. 


Add following into pom.xml:


<dependency>

   <groupId>org.springframework.boot</groupId>

   <artifactId>spring-boot-starter-websocket</artifactId>

   <version>2.1.2.RELEASE</version>

</dependency>

<dependency>

   <groupId>com.google.code.gson</groupId>

   <artifactId>gson</artifactId>

</dependency>



<dependency>

   <groupId>org.webjars</groupId>

   <artifactId>webjars-locator</artifactId>

   <version>0.30</version>

</dependency>

<dependency>

   <groupId>org.webjars</groupId>

   <artifactId>webjars-locator-core</artifactId>

</dependency>

<dependency>

   <groupId>org.webjars</groupId>

   <artifactId>sockjs-client</artifactId>

   <version>1.0.2</version>

</dependency>

<dependency>

   <groupId>org.webjars</groupId>

   <artifactId>stomp-websocket</artifactId>

   <version>2.3.3</version>

</dependency>

<dependency>

   <groupId>org.webjars</groupId>

   <artifactId>bootstrap</artifactId>

   <version>3.3.7</version>

</dependency>

<dependency>

   <groupId>org.webjars</groupId>

   <artifactId>jquery</artifactId>

   <version>3.1.0</version>

</dependency>

Also, need to add following repo so we can find javascript dependencies:

<repository>

   <id>central</id>

   <name>Maven Repository Switchboard</name>

   <layout>default</layout>

   <url>http://repo1.maven.org/maven2</url>

   <snapshots>

      <enabled>false</enabled>

   </snapshots>

</repository>



GAE flexible’s support to WebSocket is still beta.  GAE standard’s support is 1 year later (as 2/28/2019):



Following website shows how load balance impacts WebSocket:



Examples of WebSocket:


1. Echo service: Java on server side and JSP (WebSocket) on client side


Java Servlet on server side:
org.eclipse.jetty.websocket.api.WebSocketAdapter
WebSocketAdapter.onWebSocketText(message);

logger.fine("Received message: " + message);
// echo message back to client

WebSocketAdapter.getRemote().sendString(message);
(not use Spring)
 
javascript in JSP:
         var websocket = new WebSocket(webSocketUri);
(not use STOMP)
 
Works when “mvn appengine:deploy” for App Engine Flex

2    2. Stock info service: Spring on server side and javascript (SockJS) on client side


Spring:
StompEndpoint at WebSocketMessageBrokerConfigurer
import org.springframework.messaging.core.MessageSendingOperations;
private final MessageSendingOperations<String> messagingTemplate;
this.messagingTemplate.convertAndSend("/topic/price.stock." + quote.getTicker(), quote);

SockJS over STOMP
stompClient = webstomp.over(new SockJS(url, null, {transports: sockJsProtocols}));

Works when “mvn jetty:run”

Does not work when “mvn appengine:deploy” for App Engine Standard:



Works when “mvn appengine:deploy” for App Engine Flex with a change to spring-websocket-portfolio-appflex/src/main/webapp/static/js/controllers.js:




The change is to modify line 65:
// tradeService.connect("/spring-websocket-portfolio/portfolio")

tradeService.connect("/portfolio")





3    3. Sending date constantly to client: Spring boot on server side and javascript (SockJS) on client side


Spring Boot:
StompEndpoint at AbstractWebSocketMessageBrokerConfigurer
import org.springframework.messaging.simp.SimpMessagingTemplate;
SimpMessagingTemplate.convertAndSend("/topic/message", "Date: " + new Date())

SockJS over STOMP
            var socket = new SockJS(‘/stomp’);
                  var stompClient = Stomp.over(socket);
(gradle)

Unable to build from ‘mvn’ since there is no pom.xml file

4    4. Greeting service: Spring boot on server side and javascript (SockJS) on client side



Spring Boot:
StompEndpoint at WebSocketMessageBrokerConfigurer
@MessageMapping("/hello")

@SendTo("/topic/greetings")

public Greeting greeting(HelloMessage message) throws Exception {

    Thread.sleep(1000); // simulated delay

    return new Greeting("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!");

}

SockJS over STOMP:
            var socket = new SockJS(‘/gs-guide-websocket’);
                  var stompClient = Stomp.over(socket);
(mvn)

Works when running at local: mvn spring-boot:run


Did not work when “mvn appengine:deploy” for App Engine Flex:




But after following changes, it works partially (server can be started; but client got 404 error due to failure of loading javascript library):

·      Add following to pom.xml:

<dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-websocket</artifactId>

    <exclusions>

        <exclusion>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-tomcat</artifactId>

        </exclusion>

    </exclusions>

</dependency>

<dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-jetty</artifactId>

</dependency>
 
<repositories>

    <repository>

        <id>spring-snapshots</id>

        <url>http://repo.spring.io/snapshot</url>

        <snapshots><enabled>true</enabled></snapshots>

        <releases><enabled>false</enabled></releases>

    </repository>

    <repository>

        <id>spring-milestones</id>

        <url>http://repo.spring.io/milestone</url>

        <snapshots><enabled>false</enabled></snapshots>

        <releases><enabled>true</enabled></releases>

    </repository>

    <repository>

        <id>java-net</id>

        <url>https://maven.java.net/content/repositories/releases</url>

    </repository>

</repositories>
 
<!-- for deployment of web application -->

<plugin>

    <groupId>com.google.cloud.tools</groupId>

    <artifactId>appengine-maven-plugin</artifactId>

    <!--<version>${appengine.maven.plugin}</version>-->

    <version>1.3.1</version>

    <configuration>

    </configuration>

</plugin>
 
 

·      Copy app.js, index.html, and main.css from ‘resources/static’ to ‘webapp’ (need to create ‘webapp’ under ‘src/main’ first)




5    5.  Spring boot





To turn a pom.xml project to appengine flexible instance, you need to do:

1.     Add appengine plugin to pom.xml
<!-- for deployment of web application -->

<plugin>

    <groupId>com.google.cloud.tools</groupId>

    <artifactId>appengine-maven-plugin</artifactId>

    <version>1.3.1</version>

    <configuration>

    </configuration>

</plugin>

2.     Add jetty plugin to pom.xml to support local running on jetty:
<plugin>

    <groupId>org.eclipse.jetty</groupId>

    <artifactId>jetty-maven-plugin</artifactId>

    <version>9.4.7.v20170914</version>

    <configuration>

        <webApp>

            <contextPath>/${project.artifactId}</contextPath>

        </webApp>

    </configuration>

</plugin>

3.     Since war is needed for google app engine, add following line to pom.xml
<packaging>war</packaging>
4.     Create app.yaml file through IDEA’s “Add App Engine Support”/”Google App Engine Flex” menu from “Tools” and put following lines into it:

runtime: java

env: flex



handlers:

- url: /.*

  script: this field is required, but ignored



runtime_config:  # Optional

  jdk: openjdk8

  server: jetty9





# Use only a single instance, so that this local-memory-only chat app will work

# consistently with multiple users. To work across multiple instances, an

# extra-instance messaging system or data store would be needed.

manual_scaling:

  instances: 1



network:

  session_affinity: true



env_variables:

  JETTY_MODULES_ENABLE: websocket

5.     Run ‘mvn package’ and ‘mvn appengine:deploy’ to deploy            
6.     Run ‘mvn jetty:run’ to test


Embedded Jetty or Tomcat


Reactive Web

start.spring.io has Websocket as dependencies


@Async in Spring:

Simply put – annotating a method of a bean with @Async will make it execute in a separate thread i.e. the caller will not wait for the completion of the called method.





No comments:

Post a Comment