Tuesday, January 25, 2022

Template Driven and Reactive Forms Datepicker Angular Material 12

Template Driven and Reactive Forms Datepicker Angular Material 12



In this post, we will learn how to use the Angular Forms API with Datepicker, also we will learn with Template Driven Forms (ngModel).

Let's start.

We will work with Angular forms. You will have the next advantages, reactive por example is Explicit, Created in component class, Structured and immutable, Synchronous and form validation through functions.

We will work with Template Driven. You will have the next advantages,  is implicit, created by directives, unstructured and mutable, Asynchronous  and form validation through directives.

In my case both are useful however it depends on what will be done in your application.

If you want more documentacion go to Angular documentacion.


In this post. I will give two basic examples.

Case: we will have two calendars from the first Datepicker to update second Datepicker, with Angular Forms and Template Driven. ok let go. 


In both examples I used moment js for format date.

Run both examples on Stackbliz.


Angular Forms


Ts class.

import { Component, OnInit, VERSION } from '@angular/core';
import {
FormBuilder,
FormGroup,
FormControl,
Validators,
} from '@angular/forms';

import {
MomentDateAdapter,
MAT_MOMENT_DATE_ADAPTER_OPTIONS,
} from '@angular/material-moment-adapter';
import {
DateAdapter,
MAT_DATE_FORMATS,
MAT_DATE_LOCALE,
} from '@angular/material/core';


import * as _moment from 'moment';

import moment from 'moment';

export const MY_FORMATS = {
parse: {
dateInput: 'DD/MM/YYYY',
},
display: {
dateInput: 'DD/MM/YYYY',
monthYearLabel: 'MMM YYYY',
dateA11yLabel: 'LL',
monthYearA11yLabel: 'MMMM YYYY',
},
};

@Component({
selector: 'app-fdatepicker',
templateUrl: './fdatepicker.component.html',
styleUrls: ['./fdatepicker.component.css'],
providers: [
// `MomentDateAdapter` can be automatically provided by importing `MomentDateModule` in your
// application's root module. We provide it at the component level here, due to limitations of
// our example generation script.
{
provide: DateAdapter,
useClass: MomentDateAdapter,
deps: [MAT_DATE_LOCALE, MAT_MOMENT_DATE_ADAPTER_OPTIONS],
},

{ provide: MAT_DATE_FORMATS, useValue: MY_FORMATS },
],
})
export class fdatepickerComponent implements OnInit {
constructor(private fb: FormBuilder) {}

formPopPup: any;

date1 = new FormControl(moment());
date2 = new FormControl(moment());

ngOnInit() {
this.formPopPup = new FormGroup({
firstDate: new FormControl(),
secondDate: new FormControl(),
});

this.formPopPup = this.fb.group({
firstDate: [null, Validators.required],
secondDate: [null, Validators.required],
});
}

OnDateChange(e: any) {
var new_date = moment(e, 'DD-MM-YYYY').add(0, 'days').add(2, 'months');

this.formPopPup.get('secondDate').setValue(new_date);
}
}




Html

<p>Angular Forms Example</p>
<mat-sidenav-container>
<form [formGroup]="formPopPup">
<table>
<tr>
<td>
<mat-form-field>
<input
matInput
[matDatepicker]="fi"
formControlName="firstDate"
#firstDate
[formControl]="date1"
(dateInput)="OnDateChange($event.value)"
/>
<mat-datepicker-toggle matSuffix [for]="fi"></mat-datepicker-toggle>
<mat-datepicker #fi> </mat-datepicker>
</mat-form-field>
</td>
<td>
<mat-form-field>
<input
matInput
[matDatepicker]="se"
formControlName="secondDate"
[formControl]="date2"
/>
<mat-datepicker-toggle matSuffix [for]="se"></mat-datepicker-toggle>
<mat-datepicker #se> </mat-datepicker>
</mat-form-field>
</td>
</tr>
</table>
</form>
</mat-sidenav-container>




Template Driven


Ts class.


import { Component, VERSION } from '@angular/core';

import * as _moment from 'moment';

import moment from 'moment';

@Component({
selector: 'app-tdatepicker',
templateUrl: './tdatepicker.component.html',
styleUrls: ['./tdatepicker.component.css'],
})
export class tdatepickerComponent {
date1: any;
date2: any;

dateChangeHandler(e: any) {
var new_date = moment(new Date(this.date1), "DD-MM-YYYY").add(0, 'days').add(3, 'months');
this.date2 = new_date;
}
}


Html

<p>Template driven</p>
<mat-sidenav-container>
<table>
<tr>
<td>
<mat-form-field>
<input
matInput
[matDatepicker]="d1"
(dateChange)="dateChangeHandler($event)"
[(ngModel)]="date1"
/>
<mat-datepicker-toggle matSuffix [for]="d1"></mat-datepicker-toggle>
<mat-datepicker #d1> </mat-datepicker>
</mat-form-field>
</td>
<td>
<mat-form-field>
<input
matInput
[matDatepicker]="d2"
[(ngModel)]="date2"
/>
<mat-datepicker-toggle matSuffix [for]="d2"></mat-datepicker-toggle>
<mat-datepicker #d2> </mat-datepicker>
</mat-form-field>
</td>
</tr>
</table>
</mat-sidenav-container>




In both cases will be the same and add three months to the second calendar however the angular forms using FormControl in reactive way, whereas  Template is driven using ngModel.







References: https://material.angular.io/




Monday, January 17, 2022

Deploy Spring Boot 2 Kotlin Java 11 on Heroku

Deploy Spring Boot 2  Kotlin  Java 11 on Heroku.

Heroku concepts is extract from Heroku is a cloud platform that lets companies build, deliver, Monitor and scale apps, we are the fastest way to go from idea to URL, by passing all those infrastructure headches.


we will create a free account from deploy your apps. in next link, this way, 




















Next to will be do login. and will have the next page.









Click right corner -> New -> Create new app. set name the app. This way.
















Click on button Create app. and will have the next page.



















In this case I used Heroku Cli, check the link for install Heroku Cli. and the next just follow steps, Heroku provide.

$ heroku login -i


Eg:






Create a new Git repository


Initialize a git repository in a new or existing directory

$ cd my-project/
$ git init
$ heroku git:remote -a backend-eg


Deploy your application
Commit your code to the repository and deploy it to Heroku using Git.

$ git add .
$ git commit -am "make it better"
$ git push heroku master



Succes install.








Public URL, for access my webservice.

https://backend-eg.herokuapp.com/services/hello
https://backend-eg.herokuapp.com/services/hello/henry






Source code.

Here on GitHub.









Tuesday, December 7, 2021

Secure Spring boot 2 with Keycloak 15

Secure Spring boot 2 with Keycloak 15

We'll cover the basics of setting up a keycloak server, connecting spring boot microservices, also using spring security.

1. Setting Up a keycloack server.

Please check the steps to install keycloak server here.

2. Creating a Realm

For default the console opens up Master realm, Let's navigate left corner Add realm button.













For this example I typed the name demo1. we'll click the button create.













3. Creating a client









Add a new client with the name springboot-keycloak with openid-connect. click button save.
































We'll be creating a spring boot microservices running at the port 8081, we've used a redirect URL of http://localhost:8081 above on image.

4. Creating a Role








Add next roles, "admin" and "user".
















5. Creating a Users

Add next users: user1 to role user and user2 to role admin.










Set a password. I typed the password for the same user1 and user2. For this example.






















Set a role(s).

















You'll do the same steps with de user2 however the role is "admin".







5. Creating a Spring Boot Application

In this examples we're intregation Spring Boot and keycloack.

  • Configuration Spring boot, Spring Data and Keycloack.
  • Define Datas Models, Repository.
  • Spring Rest Controllers  


Spring Boot Rest  API 

These are APIs that we need to provide:

MethodsUrls
POST/users
GET/users

Technology

  • Java 11
  • Spring Boot 2.6.1
  • Mysql 8.0.23
  • Maven 3.6.3
  • Postman v9.0.8
  • IntelliJ IDEA 2021.2.3 

Project Structure


























Configuration Spring Boot Keycloak project 


pom.xml


<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<!-- Exclude the Tomcat dependency -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Use Jetty instead -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-starter</artifactId>
</dependency>

application.yml


server:
port: 8081

keycloak:
auth-server-url: http://127.0.0.1:9080/auth
realm: demo1
resource: springboot-keycloack
public-client: true
bearer-only: true

spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/backend?allowPublicKeyRetrieval=true&useSSL=false
username: henry
password: *********
hikari:
initialization-fail-timeout: 0
jpa:
database-platform: org.hibernate.dialect.MySQL5Dialect
generate-ddl: true
show-sql: true
hibernate:
ddl-auto: create

Class Security configuration


I suggest to you, we 'll be reading Spring Boot Adapters, I copied from Spring Boot Adapters the configuration class.

package com.henry.keycloack.springboot2keycloak.configuration;

import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
import org.keycloak.adapters.springsecurity.KeycloakConfiguration;
import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;

@KeycloakConfiguration
@Import(KeycloakSpringBootConfigResolver.class)
@EnableGlobalMethodSecurity(jsr250Enabled = true)//so i need the roles exist environment, @RolesAllowed
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter
{
/**
* Registers the KeycloakAuthenticationProvider with the authentication manager.
*/
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {

KeycloakAuthenticationProvider keycloakAuthenticationProvider = new KeycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider);
}

/**
* Defines the session authentication strategy.
*/
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}

@Override
protected void configure(HttpSecurity http) throws Exception
{
super.configure(http);
http
.authorizeRequests()
.anyRequest().permitAll();
http.csrf().disable();
}
}


Data class model


package com.henry.keycloack.springboot2keycloak.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.*;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
@Table
public class User {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
}

Repository Interface

package com.henry.keycloack.springboot2keycloak.repository;

import com.henry.keycloack.springboot2keycloak.model.User;
import org.springframework.data.repository.CrudRepository;

public interface UserRepository extends CrudRepository<User,Integer> {
}


Spring Rest APIs Controller

package com.henry.keycloack.springboot2keycloak.controller;

import com.henry.keycloack.springboot2keycloak.model.User;
import com.henry.keycloack.springboot2keycloak.repository.UserRepository;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.security.RolesAllowed;

@RestController
public class UserController {

private final UserRepository userRepository;

public UserController(UserRepository userRepository) {
this.userRepository = userRepository;
}

@PostMapping("/users")
@RolesAllowed({"user"})
public ResponseEntity<User> save(@RequestBody User user){
return ResponseEntity.ok(userRepository.save(user));
}

@GetMapping("/users")
@RolesAllowed("admin")
public ResponseEntity<Iterable<User>> findAll(){
return ResponseEntity.ok(userRepository.findAll());
}
}

Run & Test


Run Spring Boot application with command: mvn spring-boot:run. by console, IntelliJ etc.

Keycloak provides a REST API for generating and refreshing access tokens. 

Let's go.


1. We need to acquire an access token from Keycloak from this url. 

  • 127.0.0.1 if you want will change to localhost.
  • Port: 9080 in my case.
  • auth/realms url defined by keycloak.
  • demo1 is the name of your realm.
  • protocol/openid-connect/token url defined by keycloak.

 http://127.0.0.1:9080/auth/realms/demo1/protocol/openid-connect/token


2. Configurate on Postman.


GET. 

I used the user "user2" role "admin", we'll check images. 















Access Token url. http://127.0.0.1:9080/auth/realms/demo1/protocol/openid-connect/token















Click on Get New Acces token.


















Click Use Token.






































POST. 

I used the user "user1" role "user", we'll check images. 




































Source Code


Here on Github.




References.

https://www.baeldung.com/spring-boot-keycloak
https://www.youtube.com/watch?v=rcvAmBoDlLk






🚀 Spring Boot 3.5 → 4.0.3 Migration Summary

Import Changes, API Adjustments & Compatibility Results Migration summary from Spring Boot 3.5 → 4.0, including breaking changes, depend...