Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

Angular for Java Enterprise Developers: Oracle Code One 2018

532 Aufrufe

Veröffentlicht am

Session presented at Oracle Code One - Oct 23 2018 - San Francisco

Veröffentlicht in: Technologie
  • Login to see the comments

Angular for Java Enterprise Developers: Oracle Code One 2018

  1. 1. Angular for Java Enterprise Developers @loiane loiane.com
  2. 2. Agenda • High-level overview of Angular + TypeScript • TypeScript/Java common pa=erns • Do’s and Dont’s - Angular (Java dev ediCon) • Angular CLI • Java REST with Spring Boot • Bundling Angular for producCon • Guide to deploy Angular + Java/Spring to the cloud (maven + docker)
  3. 3. #itsJustAngular v2+
  4. 4. Angular •Based on Components •Uses TypeScript •Dependency InjecCon •Angular CLI •Very popular with Java/.Net developers
  5. 5. TypeScript •JavaScript that escales •StaCc typing - compiling 9me •Transpiles to JavaScript (ES201X) •More produc9ve than JavaScript (personal opinion)
  6. 6. TypeScript 2018 Dev Environment TypeScript 3.1 EcmaScript 2015+ ES5
  7. 7. TypeScript my-script.ts transpiler my-script.js ES5
  8. 8. Getting Started npm install -g typescript mv main.js main.ts tsc main.ts
  9. 9. TypeScript: Strongly Typed? https://twitter.com/ahejlsberg/status/792762247239995392?s=09
  10. 10. TypeScript Type Sytem
  11. 11. Don’t Repeat Yourself
  12. 12. Java 10: var AWer compiling the variables are strongly typed var number10 = 10; var user = new User(); var myList = List.of("1","2","3","4","5"); !// after compiled int number10 = 10; User user = new User(); List<String> myList = List.of("1","2","3","4","5");
  13. 13. Java 10: var !// No!!! var userName; userName = user.getName(); !// Yes! var userName = user.getName();
  14. 14. TypeScript: Avoid Verbosity !// Yes let myString = 'Code One'; !// No!!! let myString2: string = 'Code One';
  15. 15. Optional: adding return types function orderByName(a: User[]): User[] { let result = a.slice(0); result.sort((x, y) !=> x.name.localeCompare(y.name)); return result; } But someCmes it might help finding bugs in the code
  16. 16. Interfaces: two concepts (1/2) interface Person { name: string; age: number; } Interface is a type, a definiCon
  17. 17. Interfaces: two concepts (2/2) interface Person { name: string; age: number; } interface Contact extends Person { phone: string; } Or it can be used in the OO concept
  18. 18. Duck Typing
  19. 19. Defining Types on the go + Unions type Shape = | { type: 'circle'; radius: number } | { type: 'square'; w: number } | { type: 'rectangle'; w: number, h: number };
  20. 20. Defining Types on the go + unions function calculateArea(shape: Shape) { switch (shape.type) { case 'circle': return Math.PI * shape.radius !** 2; case 'rectangle': return shape.w * shape.h; case 'square': return shape.w !** 2; } throw new Error('Invalid Shape'); } const myCircle: Shape = { type: 'circle', radius: 2 }; calculateArea(myCircle);
  21. 21. Enums enum UserActionTypes { LOAD_REQUEST = '[User] Load Request', LOAD_SUCCESS = '[User] Load Success' } type UsuarioActions = | { type: UserActionTypes.LOAD_REQUEST } | { type: UserActionTypes.LOAD_SUCCESS; payload: User[]; };
  22. 22. Getters and Setters: Don’t export class Contact { private _name: string; get name() { return this._name; } set name(name: string) { this._name = name; } }
  23. 23. Getters and Setters: Do export class AuthService { private loggedIn = new BehaviorSubject(false); get isLoggedIn() { return this.loggedIn.asObservable(); } } isLoggedIn = AuthService.isLoggedIn;
  24. 24. EcmaScript
  25. 25. Arrow Functions function orderByName(a: User[]): User[] { let result = a.slice(0); return result.sort((x, y) !=> x.name.localeCompare(y.name)); } Similar to Java lambdas
  26. 26. > npm install -g @angular/cli > ng new my-project > cd my-project > ng serve || npm run start
  27. 27. Angular CLI
  28. 28. COMPONENTS DIRECTIVES ROUTINGSERVICES TEMPLATE DATA BINDINGDEPENDENCY INJECTION MODULES Main Blocks
  29. 29. COMPONENT {…} TEMPLATE <..> DIRECTIVES {..} SERVICES SERVICE B SERVICE A MODULE X MODULE A MODULE B Property Binding Event Binding
  30. 30. Modules
  31. 31. Admin Users Permissions Shared/Common Validations Pipes Products ProductsPanel ProductsList ProductDetail ProductForm Clients ClientsPanel ClientList ClientDetail ClientForm Order OrdersPanel OrdersList OrderDetail OrderForm OrderProductForm Reports MainReport ClientsReport ClientSearch ProductsReport ProductsSearch OrdersReport OrdersSearch ExportPDFButton Root AppComponent NavBar Menu
  32. 32. import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { ReactiveFormsModule } from '@angular/forms'; import { ModalModule } from 'ngx-bootstrap/modal'; import { ContactDetailsComponent } from './components/contact-details/contact-details.component'; import { ContactFormComponent } from './components/contact-form/contact-form.component'; import { ContactListComponent } from './components/contact-list/contact-list.component'; import { ContactsContainerComponent } from './contacts-container/contacts-container.component'; import { ContactsRoutingModule } from './contacts-routing.module'; @NgModule({ imports: [ CommonModule, ReactiveFormsModule, ContactsRoutingModule, ModalModule.forRoot() ], declarations: [ ContactsContainerComponent, ContactListComponent, ContactFormComponent, ContactDetailsComponent ], entryComponents: [ContactDetailsComponent] }) export class ContactsModule {} Import classes
  33. 33. import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { ReactiveFormsModule } from '@angular/forms'; import { ModalModule } from 'ngx-bootstrap/modal'; import { ContactDetailsComponent } from './components/contact-details/contact-details.component'; import { ContactFormComponent } from './components/contact-form/contact-form.component'; import { ContactListComponent } from './components/contact-list/contact-list.component'; import { ContactsContainerComponent } from './contacts-container/contacts-container.component'; import { ContactsRoutingModule } from './contacts-routing.module'; @NgModule({ imports: [ CommonModule, ReactiveFormsModule, ContactsRoutingModule, ModalModule.forRoot() ], declarations: [ ContactsContainerComponent, ContactListComponent, ContactFormComponent, ContactDetailsComponent ] }) export class ContactsModule {} Import other modules Import components used in this module
  34. 34. Project Organization Core Shared Feature A Feature B Feature C
  35. 35. Modules, Modules Everywhere!
  36. 36. Lazy Loading
  37. 37. Lazy Loading Strategies const routes: Routes = [ { path: 'module-2', loadChildren: './module-2/module-2.module#Module2Module', data: { preload: true } !// pre-load - background }, { path: 'module-3', loadChildren: './feature-3/module-3.module#Module3Module' } ]; @NgModule({ imports: [ RouterModule.forRoot(routes, { preloadingStrategy: AppCustomPreloader }) ], !// our custom logic }) export class AppRoutingModule {}
  38. 38. Lazy Loading Strategies import { PreloadingStrategy, Route } from '@angular/router'; import { Observable, of } from 'rxjs'; export class AppCustomPreloader implements PreloadingStrategy { preload(route: Route, load: Function): Observable<any> { return route.data !&& route.data.preload ? load() : of(null); } }
  39. 39. Routing: use Hash @NgModule({ imports: [RouterModule.forRoot(routes, { useHash: true })], exports: [RouterModule] }) export class AppRoutingModule {}
  40. 40. Routing: use Hash •h=p://locahost:4200/contacts •h=p://locahost:4200/#contacts
  41. 41. Common Patterns •Interfaces •Extending Classes •Generics
  42. 42. Create Wrappers @Injectable() export class ApiService { constructor(public http: HttpClient) { } getRequest<T>(url: string, params!?: any) { return this.http.get<ServerResponse<T!>>(url, { params: this.getQueryParams(params) }) .take(1); !// as simple Ajax call, we only need 1 value } postRequest(url: string, body: any) { !// POST } private getQueryParams(params: any) { !// logic to create the query params for http call } downloadFile(url: string, params!?: any) { !// logic for file download } }
  43. 43. Keep consistency @Injectable() export class TasksService { constructor(public http: ApiService) { } getAllTasksWithPaging(start = 0, limit = 100) { return this.http .getRequest<Task[]>(API.READ_TASKS, {start: start, limit: limit}); } getById(id: number) { return this.http.getRequest<Task>(`${API.READ_TASKS}/${id}`); } }
  44. 44. Keep consistency export interface ServerResponse<T> { data: T[]; total: number; success!?: boolean; errorMsg!?: string; }
  45. 45. Inheritance export abstract class BaseFormComponent implements IFormCanDeactivate { protected formSubmitAttempt: boolean; protected validateDirty = true; form: FormGroup; constructor() { this.formSubmitAttempt = false; } isFieldInvalid(field: string) { !// some logic here } onSubmit() { this.formSubmitAttempt = true; !// generic logic for all forms } canDeactivate(): Observable<boolean> { return this.modalService.showConfirm( 'DoYouWantToLeavePage', 'DoYouWantToLeavePageMsg' ); } onCancel() { this.location.back(); } }
  46. 46. Generic “Dao” Service @Injectable() export class CRUDService<T> { constructor(public http: HttpClient, private API_URL) {} load() { return this.http.get<T[]>(this.API_URL); } create(record: T) { return this.http.post<Task>(this.API_URL, record); } update(record: T) { return this.http.put<Task>(`${this.API_URL}/${record.id}`, record); } remove(id: string) { return this.http.delete<T>(`${this.API_URL}/${id}`); } }
  47. 47. Generic “Dao” Service @Injectable() export class TasksService extends CRUDService<Task> { constructor(public http: HttpClient) { super(http, API.TASKS_URL) } }
  48. 48. Generic “Dao” ServiceDebugging
  49. 49. Multiple Angular Environments Custom Environment Produc9on Development "scripts": { "ng": "ng", "dev": "ng serve !--configuration=dev", "start": "ng serve !--proxy-config proxy.conf.js", "build": "ng build !--prod !--aot !--build-optimizer -op !../webapps/app" },
  50. 50. Multiple Angular Environments !// environment.dev.ts export const environment = { production: false, baseUrl: '/' }; !// environment.ts export const environment = { production: false, baseUrl: '/api/' }; !// environment.prod.ts export const environment = { production: true, baseUrl: '!../' };
  51. 51. angular.json "configurations": { "production": { "fileReplacements": [ { "replace": "src/environments/environment.ts", "with": "src/environments/environment.prod.ts" } ], !!... }, "dev": { "fileReplacements": [ { "replace": "src/environments/environment.ts", "with": "src/environments/environment.dev.ts" } ] } !!... }
  52. 52. Back-end endpoints import { environment } from '@env/environment'; export class API { static readonly BASE_URL = environment.baseUrl; static readonly CLIENTS = `${API.BASE_URL}clients`; } !// this.http.get(API.CLIENTS)
  53. 53. Integration with Back-end: No CORs proxy.conf.json { "/api": { "target": "http:!//localhost:8080", "secure": false }, "logLevel": "debug" } const PROXY_CONFIG = [ { context: ['/api'], target: 'http:!//localhost:8080', secure: false, logLevel: 'debug', pathRewrite: { '^/api': '' } } ]; module.exports = PROXY_CONFIG; proxy.conf.js
  54. 54. Integration with Back-end: No CORs "scripts": { "ng": "ng", "start": "ng serve !--proxy-config proxy.conf.json", },
  55. 55. IE Support
  56. 56. Deploying to the cloud!
  57. 57. Different Approaches • MulCple Maven Projects (client, server and main pom.xml) (single jar/war) • Single Maven (server pom.xml with frontend plugin) (single jar/war) • MulC-stage Docker file (single jar/war) • MulCple docker containers (client and server docker files) (mulCple containers)
  58. 58. Code repo Angular src: Angular CLI Spring src: start.spring.io
  59. 59. Single jar/war package Angular prod bundle
  60. 60. Maven Front-end Plugin !!!<!-- Angular build !!--> <plugin> <groupId>com.github.eirslett!</groupId> <artifactId>frontend-maven-plugin!</artifactId> <version>1.6!</version> <configuration> <nodeVersion>v10.0.0!</nodeVersion> <npmVersion>6.4.1!</npmVersion> <workingDirectory>./!../angular-rest-crud!</workingDirectory> <installDirectory>${user.home}/.node!</installDirectory> !</configuration> <executions> !!!<!-- Steps for Angular prod build !!--> !</executions> !</plugin>
  61. 61. Maven Front-end Plugin <execution> <id>install node and npm!</id> <goals> <goal>install-node-and-npm!</goal> !</goals> <configuration> <nodeVersion>v10.0.0!</nodeVersion> <npmVersion>6.4.1!</npmVersion> !</configuration> !</execution> <execution> <id>npm install!</id> <goals> <goal>npm!</goal> !</goals> <configuration> <arguments>install !</arguments> !</configuration> !</execution>
  62. 62. Maven Front-end Plugin <execution> <id>npm build!</id> <goals> <goal>npm!</goal> !</goals> <configuration> <arguments>run build-op!</arguments> !</configuration> !</execution>
  63. 63. package.json "scripts": { "build-op": "ng build !--prod —output-path !../spring-rest-crud/target/classes/static”, },
  64. 64. Docker: Java / Spring FROM maven:3.5.4-jdk-10-slim WORKDIR /usr/src/java-code COPY . /usr/src/java-code/ RUN mvn package WORKDIR /usr/src/java-app RUN cp /usr/src/java-code/target!/*.jar ./app.jar EXPOSE 8080 CMD ["java", "-jar", "app.jar"]
  65. 65. Docker: Angular ##### Angular build FROM node:latest as angular-client WORKDIR /app COPY package.json package.json RUN npm install COPY . . RUN npm run build !--prod ##### Nginx FROM nginx:alpine VOLUME /var/cache/nginx COPY !--from=angular-client /app/dist/angular-rest-crud /usr/share/nginx/html COPY ./config/nginx.conf /etc/nginx/conf.d/default.conf
  66. 66. Docker: Angular + NGINX + proxy # proxy location /api { proxy_pass http:!//129.150.111.200:8083; proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504; proxy_buffering off; proxy_set_header Accept-Encoding ""; }
  67. 67. Oracle Application Container Cloud Service https://docs.oracle.com/en/cloud/paas/app-container-cloud/index.html
  68. 68. Oracle Application Container Cloud Service
  69. 69. Oracle Container Cloud Service https://docs.oracle.com/en/cloud/iaas/container-cloud/index.html
  70. 70. Thank you! @loiane github.com/loiane loiane.com loiane.training youtube.com/loianegroner
  71. 71. h=ps://github.com/loiane/ codeone-2018-angular-java-tutorial
  72. 72. Experts in Modern Development • Cloud • Microservices and Containers • Java, JavaScript/Node.js, PHP, Python • DevOps developer.oracle.com/ambassador @groundbreakers • Continuous Delivery • Open Source Technologies • SQL/NoSQL Databases • Machine Learning, AI, Chatbots

×