Sunday, 3 May 2020

Filebeat Udemy


filebeat.yml
Explore filebeat.reference.yml

  1. Comment out the "Elasticsearch Output"
  2. Uncomment Logstash Output and hosts
  3. Default port of logstash is 5044 and you get in this setting.


Enabling Apache Module
./filebeat modules enable apache

  1. Go to modules folder not modules.d
  2. Go to module/apache2 and open manifest.yml and we have the default location here. We should not modify the directory in this file.
  3. Go to modules.d/apache2.yml. put enabled: false for error logs. In access log section:
var.paths: ["/path/for/log/*log"]
  1. This enables apache module. Now setup logstash pipeline

Logstash Pipeline:
  1. Open pipelines.yml file under config/pipelines. Add one pipeline for access log
    • pipeline.id: access_logs
path.config: "/Users/andy/desktop/logstash/config/pipelines/access.conf"
  1. Now open the access.conf file
input{
beats {
port => 5044
host => "0.0.0.0"
}
}

output{
stdout{
codec => rubydebug{
metadata => true
}

}

}
  1. Now run logstash  bin/logstash

Starting up filebeat and processing logs
  1. Start filebeat. It will harvest the logs. If we investigate further we can see it is connecting to logstash. "Connecting to backoff" in pipeline/output
./filebeat -e
  1. Some information that are passed by filebeat also will be useful.
@metadata => { beat, type, version, pipeline, ip_address}

log => { path} - DON’T USE THIE FIELD TO DO FILTERING. It just increases the risk and it is tightly coupled. Instaed there is configuration option within filebeat.yml -> TAGS. We can specify number of option and will be sent to logstash. You can also use module to filter
module => apache
dataset => apache.access

Another field name fileset which will have "name => access "

Adding elasticsearch template index
Before enabling elasticsearch plugin in logstash we need few setup. It is only required if we want to use default configuration like Kibana dashboard.

index template -> is the configuaration about how our data should be mapped.

Here we are looking at loading index template in elasticsearch.

./filebeat setup --index-management -E output.logstash.enabled=false -E 'output.elasticsearch.hosts=["localhost:9200"]'

We invoke setup command setup template flag. This is temporarily changed. It says "Index setup complete". To check, we can use Kibana console tools. After the port number put this URL (/app/kibana#/dev_tools)

GET /_template/filebeat-*

Apache will have only few fields and it is Elastic Common Fields. These fields come from fileds.yml in filebeat. Search apache and you will see the same fields.

Take away:
  1. Index templates specify settings and mappings for indices matching patterns
  2. Filebeat version is included in the index template name and patterns to make upgarding filebeat easy
  3. When disabling the Elasticsearch output, you must run the command to add the index template after upgrading filebeat.
  4. ECS (Elastic Common schema) is a specification of common fields
  5. The fields.yml file contains the fields for Filebeat modules. Used for both the index template & the Filebeat documentation.

If our machine where we are running filebeat don’t have access to elasticsearch, we need to use alternative method.

./filebeat export template > filebeat.template.json



Adding Kibana Dashboard:
  1. open filebeat.yml
  2. Got to kibana and uncomment the host. Default port is 5601
  3. To setup dashboard
./filebeat setup --dashboards
  1. Enable Dashboards. Dashboards also have versions. So if filebeat upgrades the dashboard also need to be upgraded. However it requires filebeat to have access to Kibana at startup. We can have kibana running isolated from filebeat (like my org). In that case you can do setup from anymachine that has access to kibana. Then we need to do this again only after upgrading to new filebeat.
setup.dashboards.enabled: true

Finishing the pipeline:
The configuration is now complete, we just need to do some event processing
  1. open access.conf and implement the ingest_pipeline.json as logstash pipleline.
NOTE: Useragent filter plugin is not updated to support ECS so we need to do it on our own
input{
beats {
port => 5044
host => "0.0.0.0"
}
}

filter{
if[event][dataset] =! "apache.access" {
drop { }
}

grok {
match => {
"message"=> [
Copy the Pattern from ingest pipleline. What we copied is json form, so change double escape (\\) to \. Add square bracket to all. For example: in json we will have just source then change to [source]
]
}

//Adding after match option
remove_field => "message"

}
}
if "_grokparsefailure" in [tags]{
drop { }
}

grok{
match => {
"[source][address]" => "^(%{IP:[source][ip]}|%{HOSTNAME:[source][domain]})"
}
}

mutate{
add_field => { "[event][created]" => "%{@timestamp}"}
}

date {
match => [ "[apache][access][time]", "dd/MMM/yyyy:H:m:s Z" ]
remove_field => "[apache][access][time]"
}

<There is big code for Useragent because of non-compatible with ECS>

mutate{
remove_field => ["ua_tmp"]
}

geoip{
source => "[source][ip]"
target => "[source][geo]"
}
}
output{
elasticsearch{
hosts => "localhost"
manage_template => false
index => "%{[@metadata][beat]-%{[@metadata][version]}-%{+yyyy-MM-dd}}"
}


}

In the above code @metadata should be the event sent from filebeat
  1. Open module/apache/access/manifest.yml
Check the value of ingest_pipeline and open ingest/default.json. Then open the json, you can see the definition of ingest pipeline. Since we have logstash, we need to use the same pipeline in  logstash.
  1. Key takeaway:
Porting elasticsearch ingent pipeline to logstash ensures that Elasticsearch receives the data it expects
Feel free to do additional filtering within the pipeline
The useragent filter plugin add fields in a format that is not ECS compatible; therefore we must manually restructure the data for now
Make sure that the Elasticsearch index matches the index pattern defined within the index template.


How Filebeat Works:
Filebeat also maintains sincedb files like logstash.

Harvester -> Read files and  Keeps track of how much of the file is read. It store how much of the file is read in registry file. Since there are too many files it will track all the files. It will send the data to libbeat.

Libbeat -> Receives file from harvester, it is shared library. It aggregates data and send to the output that is configured. Elasticsearch and libbeat can group multiple lines together to single line, it uses bulk API which is more efficeint that sending multiple requests.

Registry -> Stored in memory, but flushed to disk when filebeat is shutdown. It is formatted as json with file path and offset. It is byte offset. Filebeat keep tracks of each event.

Preventing sending events twice -> Filebeat always wait for acknowledgement from output. If the filebeat is shutdown before acknowledgement is received then it will send duplicate. In that case, we can add a option shutdown_timeout to 5 sec so that it waits. It is not 100%, but reduces risk.

Takeaway:
  1. An input starts up harvester for each file matched by its file pattern
  2. Harversters read files and keep track of their offsets
  3. The file offsets and other information is persisted to a registry

Clearing the registry:
It is under data/registry/filebeat.

data.json -> contains information about registry. It will be present only if harvester starts reading. Typically don’t modify the registry. You can either reset the offset value to 0 or jus delete it.

Processing More Logs:
First deleting the document that we loaded from Kibana Dev Tools

DELETE /filebeat-*

Manual Input Configuration:
  1. Disabling apache module
./filebeat modules disable apache
  1. Open filebeat.yml
enabled: true
paths:
  • <log path>

fields:
events:
module: apache
dataset: "apache.access"

fileds_under_root: true

Uncomment exclude _files

//We are adding fields to match the logstash pipeline.
//[fields][event][dataset] instead of [event][dataset]
  1. No changes needed in logstash pipeline.


Evaluation of modules:
Using modules with Logstash requires additional configuration
Reduces simplicity and convenience, but increases flexibility
In some cases you save a lot of config with modules
Automatically benefit from boilerplate config
Reduce the risk of mistakes. Example fogetting excluding gz file.
Make use of module as much as possible.
Prefer either using modules or not using modules at all; a combination is harder to maintain.

Tagging Events:
It alows tag field to be sent along, can be used for filtering.
tags: ["web-server"]

We cannot always use tags, as we have multiple inputs using same tags. It is better to use fields

Takeaway:
Use  tags option to add one or more tags to Filebeat
These tags can then be used withing the configured output (eg:logstash)
Tags can be used for filtering in logstash, exactly as with any other tas
Tags are added to all events, Ie for all inputs


Approaches for handling multiple log types:
We cannot have two inputs listening on same port. It is limitation of OS, two process cannot listen to same port. So we can have different ports. It is possible by enabling logstash loadbalancer. We can enable multiple enpoints for logstash.  But it is just workaround and exploiting the load balancer.

Solution 1: Start multiple instance of filebeat. So we have two installation of filebeat and run side by side. Then configure data to send to different endpoint.

Solution 2: Managing everything in single logstash pipeline. It will add complexity to pipeline. Running in singlepipeline means need to process lots of log and it is bottleneck

Processing Apache Error Logs:
When using filebeat, we get multiple logs to the port so either we need to have multiple file beat instance or have one filebeat and handle in a single pipeline. He choosed single pipeline.

  1. Go to filebeat.yml and disable filebeat.input. In above example he showed using filebeat without default apache module so he turned it off.
enabled: false (under filebeat.inputs)
  1. Enable apache module
./filebeat modules enable apache
  1. Open apache.yml under modules.d and enable error log. And copy the path.
var.path:["/users/andy/desktop/error.log"]

  1. Create new file apache.conf under /config/pipelines/
  2. Add the reference in pipleline.yml, previously we had access_logs now he edited the same to have just this pipeline.
    • pipeline.id: apache_logs
path.config: "/Users/andy/desktop/logstash/config/pipelines/apache.conf"

  1. In apache.conf
input{
beats {
port => 5044
host => "0.0.0.0"
}
}

filter{
if[event][module] != "apache"{
drop { }
}
if[event][dataset] == "apache.access" {

//NOTE: All code from previous section for acces.log is now copied under this
grok {
match => {
"message"=> [
Copy the Pattern from ingest pipleline. What we copied is json form, so change double escape (\\) to \. Add square bracket to all. For example: in json we will have just source then change to [source]
]
}

//Adding after match option
remove_field => "message"

}
}
if "_grokparsefailure" in [tags]{
drop { }
}

grok{
match => {
"[source][address]" => "^(%{IP:[source][ip]}|%{HOSTNAME:[source][domain]})"
}
}

mutate{
add_field => { "[event][created]" => "%{@timestamp}"}
}

date {
match => [ "[apache][access][time]", "dd/MMM/yyyy:H:m:s Z" ]
remove_field => "[apache][access][time]"
}

<There is big code for Useragent because of non-compatible with ECS>

mutate{
remove_field => ["ua_tmp"]
}

geoip{
source => "[source][ip]"
target => "[source][geo]"

}

} else if [event][dataset] == "apache.error"
{
// Convert the pipline.json from ingest directory under apache module.
grok {
match => {
"message" => [
//Copy the GROK pattern from ingest pipeline, convert // to / and add square bracket.
]
}

pattern_definitions => {

 "APACHE_TIME" => "%{DAY} %{MONTH} %{MONTHDAY} %{TIME} %{YEAR}"
}
}

date {
match => [ "[apache][error][timestamp]", "EEE MMM dd H:m:s yyyy", "EEE MMM dd H:m:s.SSSSSS yyyy" ]
remove_field => [apache][error][timestamp]
}

grok{
match => {
"[source][address]" => "^(%{IP:[source][ip]}|%{HOSTNAME:[source][domain]})"
}
}

geoip{
source => "[source][ip]"
target => "[source][geo]"

}

}


}
output{
elasticsearch{
hosts => "localhost"
manage_template => false
index => "%{[@metadata][beat]-%{[@metadata][version]}-%{+yyyy-MM-dd}}"
}


}



Handling Multiline Using Filebeat:
Now he is creating new logstash pipeline and he not using access.config because it will be too complicated.

  1. Create new config java-errors.conf. To avoid conflict he is increasing the port by one.
input{
beats {
port => 5045
host => "0.0.0.0"
}
}

output{
stdout{ }

}
  1. Add this pipeline to pipeline.yml:
    • pipeline.id: java_logs
path.config: "/Users/andy/desktop/logstash/config/pipelines/java_errors.conf"
  1. Now he has fresh installation of filebeat which runs side by side:
  2. Disable elasticsearch output and enable logstash. Use the port here as 5045 for logstash.
  3. Configure input. Under filebeat.inputs:
enabled: true

paths:
  • /Users/Andy/Desktop/java_errors.log
  1. Multiline options in filebeat.
uncomment multiline.negate: false

In logstash we configured as previous, and the equivalent is after.

Just uncomment multiline.match: after

Uncomment multiline.pattern: '^(\s+|\t)|(Caused by:)'
  1. Start logstash.
  2. Start filebeat

Handling multiline - V2
He now wants to match the file line of stack trace. So far we were matching the next line.

  1. Set negate to true
multiline.negate: true

multiline.pattern: <Copy from GIT it is so big>
  1. Start filebeat


Spring Framework: Spring MVC Fundamentals - Pluralsight

DispatcherServlet -> Entry Point
ViewResolvers -> JSP, Restful service, html page
servlet-config -> Configuration file
POJO -> Plain old java object
Bean -> Spring configured POJO

After downloading from Spring Initializr:
1. Import the project in IntelliJ
2. Just follow the  Problems Faced: in Spring Boot
3. Then RUN. It should give WhiteLabel Error
4. Add html file in src/resources/static. Just add hello in index.html
5. And restart. You should be able to see hello.



Demo: Greeting Controller

src/main/ -> Root Folder
<root>/java
<root>/webapp -> You can keep index.html and serve it from here
/webapp/WEB-INF/jsp -> To keep jsp file


greetings.jsp:

This will be similar to  html but we can have variables here we have

${message}

/com.pluralsight.conference -> Keep our java class (ConferenceApplication.java)

We have annotation -> @SpringBootApplication. On top of default java code we do extend

public class ConferenceApplication extends SpringBootServletInitializer


Create  a Java Class with name controller.GreetingController. In this controller is directory.



Controller -> Is use to control what to put in web page. Only handle request/response. Don't put business logic. @Controller
Service -> Business logic. Describe verbs/action of system. @Service
Repository -> Data access object. Describe nouns. Database interaction. @Repository



Controller:
Heart and soul of spring MVC. Lightweight. In our example we just used @Controller annotation and Request Mapping @GetMapping. There are other ways to do it by extending a class but the method shown here is preferred.

DEMO: Registration Controller + Greetings Controller
1. Create directory under main -> webapp/WEB-INF/JSP
2. Go to Setting CTRL + ALT + s. Under Build Execution & Deployment -> Application Server choose Tomcat (NOTE: We do this because if we right click we don't get JSP, so just following tutorial). Also download and install tomcat (unzip)
3. Change the packaging type to WAR. In pom.xml ad <packaging>war</packaging> This need to be added between version and name of com.pluralsight groupid XML tags.
4. Add tomcat dependency in pom.xml, this will be second dependancy, next to org.springframework.boot
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
5. Click on "Conference Application" which will allow to edit config. It is near hammar symbol in tool bar and press "Edit Configuration"
6. Click + sign and add tomcat server. Check JRE is 11. Click deployments tab -> + sign -> Artifacts -> Conference.war. Change application context to /conference instead of /conference_war
7. JSP Files and Index.html - Create greetings.jsp under webapp/WEB-INF/JSP and add this tag <h1>${message}</h1>. Also create registration.jsp webapp/WEB-INF/JSP and add this tag <h1>Registration</h1>. In resource/static/index.html put below lines:
<a href="registration">Registration</a>
<a href="greeting">Greeting</a>

Note: Intellij add '/' to href. But it is not required.
8. Modify ConferenceApplication.
public class ConferenceApplication extends SpringBootServletInitializer -> We do this basically to support tomcat

Add below parameters
src/main/resources -> application.properties
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp

9. Under com.pluralsight.controller, create controller.GreetingController class

GreetingController.java
@Controller
public class GreetingController{
@GetMapping("greeting")                             --------> This is what we see in URL. When we hit greeting URL we will run below method
public String greeting (Map<String, Object> model){    ------>  Here the name greeting is the method can be anything. foo or bar. Mapping string to object
model.put("message", "Hello Google");    ------>  The above model variable is defined here. message is the variable in JSP page. Hello Google is the value
return "greeting";    ------>  Here greeting is the JSP page not our method name. It will look for jsp page named greeting to substitute variable. We use only "greeting" because we have mentioned prefix as /WEB-INF/jsp/ and suffix and .jsp in application.properties. It know to look for application.properties because of @SpringBootApplication and public class ConferenceApplication extends SpringBootServletInitializer in our Main program.

}
}

10. Run the code. Go to this URL -> http://localhost:8080/conference/greeting

NOTE: While following tutorial I created index.hml under Resources/Static and when I hit /conference it pulled that page automatically. There is not configuration anywhere. It is hosted in /conference because when setting up tomcat we set our application context as /conference in step 6.

Whitelabel Error -> It occurs when either no html page is present or asp page is present but no code for it. Or code present no asp page for it.

11. Creating RegistrationController.java. It is same as greeting we just don't have model.put as we don't use any variable in the jsp for registration.
@Controller

public class RegistrationController {
    @GetMapping("regsitration")
    public String GetRegistration(Map<String, Object> model){
                return "registration";
    }
}




Model Attribute
This is for getting input from the user.
DEMO:  Passing Parameters

1. In registration.jsp, create form tag:
In 2nd line:
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

Below h1 tag:
<form:form>
<table>
<tr>
<td>
Name:
</td>
<td>
<form:input path="name" />
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Add Registration">
</td>
</tr>
</table>

</form:form>

2. Save above and just restart. It will give error for path="name". It is because binding is missing. Right click on src/main/java/com.pluralsight.conference and create new class. model.Registration.
Registration.java

public class Registration {

private String name;

1. Right click -> Generate -> Getters and Setters

}

3. Go to RegistrationController.java
Change this line from public String GetRegistration(Map<String, Object> model) to public String GetRegistration(@ModelAttribute("registration")Registration registration)   ---> Here we are naming our Model Attribute as registration, We can name anything, but the same name has to go inside the form in registration.jsp. Registration registration  is the Registration Model object, and we are instantiating one registration.

4. Go to registration.jsp
<form:form> to <form:form modelAttribute="registration">

5. Restart the server. It will work and display HTML page properly but it won't be able to get input and store. Because in we need to do "post" mapping. If we look at registrationContoller.java we just have @GetMapping.
6. Open registrationContoller.java add below lines after return "registration"; }. Add below block

  @PostMapping("regsitration")
    public String addRegistration(@ModelAttribute("registration")Registration registration){
System.out.println("Registration: " + registration.getName());          //getName() is getter, it showed automatically in intelliJ
                return "registration";
    }



Creating Views in Spring MVC:
We created WEB-INF so that we serve our application via code. If we just add "registration.jsp" in the URL it won't serve, it just give error. We do this because use can't deeplink our application. In above code, we are making service call to registration to greeting.


Overriding extends SpringBootServletInitializer which we defined in Main class. Without using that we have to write below code to get same feature. But we don’t have to remove that extends SpringBootServletInitializer .


1. Right click on com.pluralsight.conference and add new class -> ConferenceConfig

ConferenceConfig.java

@Configuration

{
@Bean
public ViewResolver viewResolver(){
InternalResourceViewResolver bean =  new InternalResourceViewResolver();
bean.setPrefix("/WEB-INF/jsp/");
bean.setSuffix(".jsp");
bean.setOrder(0);
return bean;

}


}

2. Comment the prefix and suffix settings in application.properties. Restart application


Creating Static Files in Spring MVC - PDF:
1. Right click on WEB-INF and create new directory pdf
2. Drag and drop a sample PDF file in the application
3. Go to Conference config.java


public class ConferenceConfig implements WebMvcConfigurer{

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/files/**").addResourceLocations("/WEB-INF/pdf/");  //files is the URL and ResourceLocation is the path in our project
    }

//Do it above @Bean

}

}
4. Restart the server and go to URL conference/files/<pdfname>.pdf

Demo: Adding Internationalization:
1.  Open ConferenceConfig.java
2. Add below bean
<PDF Code>

    //We are going to override a feature from WEB MVC. We are registering localechange interceptor
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(localeChangeInterceptor());
    }

    //It ties our current session to a locale. Below bean will create a instance and put in spring registry. Here we are using US locale
    @Bean
    public LocaleResolver localeResolver(){
        SessionLocaleResolver slr = new SessionLocaleResolver();
        slr.setDefaultLocale(Locale.US);
        return slr;
    }

    //LocaleChangeInterceptor will look for a parameter either through hidden element or URL string as a query parameter. We are looking for program name lang
    @Bean
    public LocaleChangeInterceptor localeChangeInterceptor(){
        LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
        lci.setParamName("lang");
        return lci;
    }
<View Resolver Code>

3. Right click on "Resources" directory and create file -> "messages.properties". Notice the messages is plural and it matters
4. Inside messages.properties files write below
#lables
name=Name

#buttons
save.changes=Save Changes

5. Right click on "Resources" directory and create file -> "messages_es.properties".
name=Nombre
save.changes=Guardar cambios
6. Open registration.jsp (webapp/WEB-INF/jsp) and add below tag
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
7. Change the JSP code to accommodate the internationalization:
Replace "Name" with <spring:message code="name" />
8. Restart and see whether it worked.
Open regsitraiton link and add query parameter at end ?lang=es
9. For post-redirect-get: Once we submit the form, we need to again reload the page with no values. To do that GET request is sent locally. This is easy in this tutorial because @GET and @POST is separate.
In RegistrationController.java just makes changes to return under @PostMapping("registration"):

return "redirect:registration";


Demo: Thymleaf
Backup the old code before moving to this.

1. First add dependancy in pom.xml between spring-boot-starter-tomcat and spring-boot-starter-test, So this order matters because that’s how it get loaded in the class path.
<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf-spring5</artifactId>
    <version>3.0.11.RELEASE</version>
</dependency>

2. Template Resolver is not same as view resolver, but feels same like it.
In ConferenceConfig.java

public class ConferenceConfig implements WebMvcConfigurer{
@Autowired
private ApplicationContext applicationcontext;

//After ViewResolver Bean
    @Bean
    public SpringResourceTemplateResolver templateResolver() {
        SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
        templateResolver.setApplicationContext(applicationContext);
        templateResolver.setPrefix("/WEB-INF/views/");
        templateResolver.setSuffix(".html");
        templateResolver.setTemplateMode(TemplateMode.HTML);
        return templateResolver;
    }

3. Template Engine: We don't need engine when we use jsp but required when thymleaf is used. This will call template resolver method.

//After SpringResourceTemplateResolver Bean

    @Bean
    public SpringTemplateEngine templateEngine() {
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver());
templateEngine.setEnableSpringELCompiler(true);
        return templateEngine;
    }
4. View Resolver: It is different from template resolver. Template resolver will lookup the actual template ViewResolver just takes whicever template was loaded. They work in conjunction.
//After viewresolver for jsp

    @Bean
    public ViewResolver thymeleafResolver() {
        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
        viewResolver.setTemplateEngine(templateEngine());
viewResolver.setOrder(0);
        return viewResolver;
    }

Then edit viewResolver.setOrder(0); of JSP and set it to 1. So we are giving priority to Thymeleaf

5. Right click on webapp/WEB-INF -> Create directory "views" -> Create new HTML5 "thyme.html"
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <title>Template</title>
  </head>
  <body>
    <h1>Thymeleaf Integration</h1>
    <p th:text="${message}"></p>
  </body>
</html>
6. In above code we have "message" so this needs to populated using greetings controller:
In GreetingController.java, below the existing jsp code copy below, here we are creating new mapping for thyme.

@GetMapping("thyme")                           
public String thyme (Map<String, Object> model){   
model.put("message", "Hello Thymeleaf");   
return "thyme";   

7. Save and restart the server and go to conference/thyme we will get the "Hello Thymeleaf". If we go to greeing or registration page it will break with 500 error.


JSR Bean Validation - Theory

JSR 303 -> Original Specification.
JSR 349 -> Targetted JAVA 7
JSR 380 -> Java 8 and focusses modularity changes in Java 9

Validator Interface: Theory
Bean validator reference implementation is instance of hibernate validator. In pom.xml between spring-boot-starter-tomcat and


Demo Validation: (We are using JSR 389)
1. Add below dependancy in pom.xml
spring-boot-starter-test add below dependancy:
<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.1.1.Final</version>
</dependency>

Hibernate is for database however hibernate_validator can be used for data validation.


2. Open Model -> Registration:

public class Regsitration{
@NotEmpty  //Validating input is not empty
3. Open RegistrationController.java

@PostMapping("regsitration")
    public String addRegistration(@Valid @ModelAttribute("registration")Registration registration, BindingResult result){


if(result.hasErrors()){
System.out.println("There were errors");
return "registration";

}

4. Open registration.jsp
Inside head tag put following css
<style>
.error {
color: #ff0000;
}

.errorblock {
color: #000;
background-color: #ffEEEE;
border: 3px solid #ff0000;
padding: 8px;
margin: 16px;
}
</style>

Below <form:form moduleAttribute
<form:errors path="*" cssClass="errorblock" element="div" />
5. Restart server and try submitting without anything in box. It is validating for empty submits.
6. To get more errors

Under <form:input path="name"

<td>
<form:errors path="name" cssClass="error" />
</td>

Change <td colspan="2" to <td colspan="3"

7. In messages:

In messages.properties:

#validations
NotEmpty.registration.name=Name can not be empty. please fix

In messages_es.properties:
NotEmpty.registration.name=Name can not be empty, in Spanish
8. Restart, it should now show "Name can not be empty"


Demo: @RestController
1. Right click on Model and create new java class -> User. Below we are creating model object which we can pass back and forth to controller.
public class User {

private String firstname;
private String lastname;
private int age;

Right Click -> Generate -> Getter and Setter -> Select all three
}
2. Right click on Controller -> UserController. In RestController we are returning Body but in @Controller we were returning actual JSP page.
@RestController
public class UserController{
@GetMapping("/user")
public User getUser(@RequestParam(value = "firstname", defaultValue = "Bryan") String firstname,
@RequestParam(value = "lastname", defaultValue = "Hansen") String lastname,
@RequestParam(value = "age", defaultValue = "43") int age
) {
User user = new User();
user.setFirstname(firstname);
user.setLastname(lastname);
user.setAge(age);
return user;
}
}


Normally line  with set will be a database call.
3. Now restart and add conference/user to the end. You will get json.


Demo: @PostMapping:
In usercontroller.java
1. Under the RestController logic
@PostMapping("/user")
public User postUser (User user) {
System.out.println("User firstname:" + user.getFirstname());
return user
}

Demo: Jquery
1. Right click on Resource -> Static -> New -> user.html and user.js
2. In user.js page below script
$(document).ready(function() {
$.ajax({
url: "http://localhost:8080/conference/user"
}).then(function(data) {
$('.firstname').append(data.firstname);
$('.lastname').append(data.lastname);
$('.age').append(data.age);
});

});
3. Copy HTML file from the exercise and paste to user.html

Golang - RegEx - SCW

import (     "errors"     "regexp" ) ​ var (     upperCaseRegex = `(.*[A-Z].*)`     lowerCaseRegex = `(.*[a-z].*)`     n...