diff --git a/2022-02/spring-33/manual-hateoas/pom.xml b/2022-02/spring-33/manual-hateoas/pom.xml
new file mode 100644
index 00000000..5b24b7df
--- /dev/null
+++ b/2022-02/spring-33/manual-hateoas/pom.xml
@@ -0,0 +1,45 @@
+
+
+ 4.0.0
+
+ ru.otus
+ manual-hateoas
+ 1.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.6.6
+
+
+
+
+ 11
+ 11
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ com.h2database
+ h2
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+
+ org.springframework.boot
+ spring-boot-starter-hateoas
+
+
+
+
+
diff --git a/2022-02/spring-33/manual-hateoas/src/main/java/ru/otus/spring/microservice/App.java b/2022-02/spring-33/manual-hateoas/src/main/java/ru/otus/spring/microservice/App.java
new file mode 100644
index 00000000..045da3f5
--- /dev/null
+++ b/2022-02/spring-33/manual-hateoas/src/main/java/ru/otus/spring/microservice/App.java
@@ -0,0 +1,27 @@
+package ru.otus.spring.microservice;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import ru.otus.spring.microservice.domain.Person;
+import ru.otus.spring.microservice.repostory.PersonRepository;
+
+import javax.annotation.PostConstruct;
+
+@SpringBootApplication
+public class App {
+
+ @Autowired
+ private PersonRepository repository;
+
+ public static void main(String[] args) {
+ SpringApplication.run(App.class);
+ }
+
+ @PostConstruct
+ public void init() {
+ for(int i = 0 ; i < 18; ++i) {
+ repository.save(new Person("Пёрсона №" + i));
+ }
+ }
+}
diff --git a/2022-02/spring-33/manual-hateoas/src/main/java/ru/otus/spring/microservice/domain/Person.java b/2022-02/spring-33/manual-hateoas/src/main/java/ru/otus/spring/microservice/domain/Person.java
new file mode 100644
index 00000000..e3d66986
--- /dev/null
+++ b/2022-02/spring-33/manual-hateoas/src/main/java/ru/otus/spring/microservice/domain/Person.java
@@ -0,0 +1,37 @@
+package ru.otus.spring.microservice.domain;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+@Entity
+public class Person {
+
+ @Id
+ @GeneratedValue
+ private int id;
+ private String name;
+
+ public Person() {
+ }
+
+ public Person(String name) {
+ this.name = name;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/2022-02/spring-33/manual-hateoas/src/main/java/ru/otus/spring/microservice/repostory/PersonRepository.java b/2022-02/spring-33/manual-hateoas/src/main/java/ru/otus/spring/microservice/repostory/PersonRepository.java
new file mode 100644
index 00000000..5dc34cd8
--- /dev/null
+++ b/2022-02/spring-33/manual-hateoas/src/main/java/ru/otus/spring/microservice/repostory/PersonRepository.java
@@ -0,0 +1,7 @@
+package ru.otus.spring.microservice.repostory;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import ru.otus.spring.microservice.domain.Person;
+
+public interface PersonRepository extends JpaRepository {
+}
diff --git a/2022-02/spring-33/manual-hateoas/src/main/java/ru/otus/spring/microservice/rest/EntrypointRestController.java b/2022-02/spring-33/manual-hateoas/src/main/java/ru/otus/spring/microservice/rest/EntrypointRestController.java
new file mode 100644
index 00000000..c66a9ed2
--- /dev/null
+++ b/2022-02/spring-33/manual-hateoas/src/main/java/ru/otus/spring/microservice/rest/EntrypointRestController.java
@@ -0,0 +1,19 @@
+package ru.otus.spring.microservice.rest;
+
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
+import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;
+
+@RestController
+public class EntrypointRestController {
+ @GetMapping("api/entrypoint")
+ public ResponseEntity> getApiEntrypoint() {
+ var link = linkTo(methodOn(PersonsRestController.class).findAllPersons()).withRel("all");
+ return new ResponseEntity<>(link, HttpStatus.OK);
+ }
+}
diff --git a/2022-02/spring-33/manual-hateoas/src/main/java/ru/otus/spring/microservice/rest/PersonsRestController.java b/2022-02/spring-33/manual-hateoas/src/main/java/ru/otus/spring/microservice/rest/PersonsRestController.java
new file mode 100644
index 00000000..64c16b8a
--- /dev/null
+++ b/2022-02/spring-33/manual-hateoas/src/main/java/ru/otus/spring/microservice/rest/PersonsRestController.java
@@ -0,0 +1,67 @@
+package ru.otus.spring.microservice.rest;
+
+
+import org.springframework.hateoas.RepresentationModel;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RestController;
+import ru.otus.spring.microservice.domain.Person;
+import ru.otus.spring.microservice.repostory.PersonRepository;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
+import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;
+
+@RestController
+public class PersonsRestController {
+
+ private final PersonRepository repository;
+
+ public PersonsRestController(PersonRepository repository) {
+ this.repository = repository;
+ }
+
+ @GetMapping("api/persons")
+ public ResponseEntity> findAllPersons() {
+ List persons = repository.findAll();
+ List resources = persons.stream().map(this::person2Resource)
+ .collect(Collectors.toList());
+ return new ResponseEntity<>(resources, HttpStatus.OK);
+ }
+
+ @GetMapping("api/persons/{id}")
+ public ResponseEntity> findById(@PathVariable("id") int id) {
+ Optional person = repository.findById(id);
+ return new ResponseEntity<>(person2Resource(person.orElseThrow()), HttpStatus.OK);
+ }
+
+ private PersonResource person2Resource(Person person) {
+ var resource = new PersonResource(person);
+ resource.add(linkTo(methodOn(PersonsRestController.class).findById(person.getId())).withSelfRel());
+ resource.add(linkTo(methodOn(PersonsRestController.class).findAllPersons()).withRel("all"));
+ return resource;
+ }
+
+ private static class PersonResource extends RepresentationModel {
+
+ private final Person person;
+
+ public PersonResource(Person person) {
+ this.person = person;
+ }
+
+ public int getId() {
+ return person.getId();
+ }
+
+ public String getName() {
+ return person.getName();
+ }
+ }
+
+}
diff --git a/2022-02/spring-33/manual-hateoas/src/main/resources/application.yml b/2022-02/spring-33/manual-hateoas/src/main/resources/application.yml
new file mode 100644
index 00000000..e69de29b
diff --git a/2022-02/spring-33/manual-hateoas/src/main/resources/static/index.html b/2022-02/spring-33/manual-hateoas/src/main/resources/static/index.html
new file mode 100644
index 00000000..97be2d13
--- /dev/null
+++ b/2022-02/spring-33/manual-hateoas/src/main/resources/static/index.html
@@ -0,0 +1,67 @@
+
+
+
+
+ Пёрсоны
+
+
+
+
+
+
\ No newline at end of file
diff --git a/2022-02/spring-33/plain-api/pom.xml b/2022-02/spring-33/plain-api/pom.xml
new file mode 100644
index 00000000..4fbfd9ad
--- /dev/null
+++ b/2022-02/spring-33/plain-api/pom.xml
@@ -0,0 +1,40 @@
+
+
+ 4.0.0
+
+ ru.otus
+ plain-api
+ 1.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.6.6
+
+
+
+
+ 11
+ 11
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ com.h2database
+ h2
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+
+
+
diff --git a/2022-02/spring-33/plain-api/src/main/java/ru/otus/spring/microservice/App.java b/2022-02/spring-33/plain-api/src/main/java/ru/otus/spring/microservice/App.java
new file mode 100644
index 00000000..045da3f5
--- /dev/null
+++ b/2022-02/spring-33/plain-api/src/main/java/ru/otus/spring/microservice/App.java
@@ -0,0 +1,27 @@
+package ru.otus.spring.microservice;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import ru.otus.spring.microservice.domain.Person;
+import ru.otus.spring.microservice.repostory.PersonRepository;
+
+import javax.annotation.PostConstruct;
+
+@SpringBootApplication
+public class App {
+
+ @Autowired
+ private PersonRepository repository;
+
+ public static void main(String[] args) {
+ SpringApplication.run(App.class);
+ }
+
+ @PostConstruct
+ public void init() {
+ for(int i = 0 ; i < 18; ++i) {
+ repository.save(new Person("Пёрсона №" + i));
+ }
+ }
+}
diff --git a/2022-02/spring-33/plain-api/src/main/java/ru/otus/spring/microservice/domain/Person.java b/2022-02/spring-33/plain-api/src/main/java/ru/otus/spring/microservice/domain/Person.java
new file mode 100644
index 00000000..553a8a7d
--- /dev/null
+++ b/2022-02/spring-33/plain-api/src/main/java/ru/otus/spring/microservice/domain/Person.java
@@ -0,0 +1,39 @@
+package ru.otus.spring.microservice.domain;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+@Entity
+public class Person {
+
+ @Id
+ @GeneratedValue
+ private int id;
+ private String name;
+
+ public Person() {
+ }
+
+ public Person(String name) {
+ this.name = name;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/2022-02/spring-33/plain-api/src/main/java/ru/otus/spring/microservice/repostory/PersonRepository.java b/2022-02/spring-33/plain-api/src/main/java/ru/otus/spring/microservice/repostory/PersonRepository.java
new file mode 100644
index 00000000..5dc34cd8
--- /dev/null
+++ b/2022-02/spring-33/plain-api/src/main/java/ru/otus/spring/microservice/repostory/PersonRepository.java
@@ -0,0 +1,7 @@
+package ru.otus.spring.microservice.repostory;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import ru.otus.spring.microservice.domain.Person;
+
+public interface PersonRepository extends JpaRepository {
+}
diff --git a/2022-02/spring-33/plain-api/src/main/java/ru/otus/spring/microservice/rest/PersonsRestController.java b/2022-02/spring-33/plain-api/src/main/java/ru/otus/spring/microservice/rest/PersonsRestController.java
new file mode 100644
index 00000000..8a7d647e
--- /dev/null
+++ b/2022-02/spring-33/plain-api/src/main/java/ru/otus/spring/microservice/rest/PersonsRestController.java
@@ -0,0 +1,34 @@
+package ru.otus.spring.microservice.rest;
+
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RestController;
+import ru.otus.spring.microservice.domain.Person;
+import ru.otus.spring.microservice.repostory.PersonRepository;
+
+import java.util.List;
+
+@RestController
+public class PersonsRestController {
+
+ private final PersonRepository repository;
+
+ public PersonsRestController(PersonRepository repository) {
+ this.repository = repository;
+ }
+
+ @GetMapping("api/persons")
+ public ResponseEntity> findAllPersons() {
+ List persons = repository.findAll();
+ return new ResponseEntity<>(persons, HttpStatus.OK);
+ }
+
+ @GetMapping("api/persons/{id}")
+ public ResponseEntity> findById(@PathVariable("id") int id) {
+ Person person = repository.findById(id).orElseThrow();
+ return new ResponseEntity<>(person, HttpStatus.OK);
+ }
+}
diff --git a/2022-02/spring-33/plain-api/src/main/resources/application.yml b/2022-02/spring-33/plain-api/src/main/resources/application.yml
new file mode 100644
index 00000000..e69de29b
diff --git a/2022-02/spring-33/plain-api/src/main/resources/static/index.html b/2022-02/spring-33/plain-api/src/main/resources/static/index.html
new file mode 100644
index 00000000..ef9a23e1
--- /dev/null
+++ b/2022-02/spring-33/plain-api/src/main/resources/static/index.html
@@ -0,0 +1,62 @@
+
+
+
+
+ Пёрсоны
+
+
+
+
+
+
\ No newline at end of file
diff --git a/2022-02/spring-33/pom.xml b/2022-02/spring-33/pom.xml
new file mode 100644
index 00000000..a4ee7368
--- /dev/null
+++ b/2022-02/spring-33/pom.xml
@@ -0,0 +1,18 @@
+
+
+ 4.0.0
+
+ ru.otus
+ spring-data-rest-demo
+ 1.0
+
+ pom
+
+
+ plain-api
+ manual-hateoas
+ spring-data-rest
+
+
diff --git a/2022-02/spring-33/spring-data-rest/pom.xml b/2022-02/spring-33/spring-data-rest/pom.xml
new file mode 100644
index 00000000..ae57eeb6
--- /dev/null
+++ b/2022-02/spring-33/spring-data-rest/pom.xml
@@ -0,0 +1,51 @@
+
+
+ 4.0.0
+
+ ru.otus
+ spring-data-rest
+ 1.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.6.6
+
+
+
+
+ 11
+ 11
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ com.h2database
+ h2
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-rest
+
+
+
+ org.springframework.data
+ spring-data-rest-hal-explorer
+
+
+
+
+
diff --git a/2022-02/spring-33/spring-data-rest/src/main/java/ru/otus/spring/microservice/App.java b/2022-02/spring-33/spring-data-rest/src/main/java/ru/otus/spring/microservice/App.java
new file mode 100644
index 00000000..045da3f5
--- /dev/null
+++ b/2022-02/spring-33/spring-data-rest/src/main/java/ru/otus/spring/microservice/App.java
@@ -0,0 +1,27 @@
+package ru.otus.spring.microservice;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import ru.otus.spring.microservice.domain.Person;
+import ru.otus.spring.microservice.repostory.PersonRepository;
+
+import javax.annotation.PostConstruct;
+
+@SpringBootApplication
+public class App {
+
+ @Autowired
+ private PersonRepository repository;
+
+ public static void main(String[] args) {
+ SpringApplication.run(App.class);
+ }
+
+ @PostConstruct
+ public void init() {
+ for(int i = 0 ; i < 18; ++i) {
+ repository.save(new Person("Пёрсона №" + i));
+ }
+ }
+}
diff --git a/2022-02/spring-33/spring-data-rest/src/main/java/ru/otus/spring/microservice/config/RestConfig.java b/2022-02/spring-33/spring-data-rest/src/main/java/ru/otus/spring/microservice/config/RestConfig.java
new file mode 100644
index 00000000..110f7858
--- /dev/null
+++ b/2022-02/spring-33/spring-data-rest/src/main/java/ru/otus/spring/microservice/config/RestConfig.java
@@ -0,0 +1,20 @@
+package ru.otus.spring.microservice.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
+import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurer;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import ru.otus.spring.microservice.projections.PersonLowerNameProjection;
+import ru.otus.spring.microservice.projections.PersonUpperNameProjection;
+
+//@Configuration
+public class RestConfig implements RepositoryRestConfigurer {
+
+ @Override
+ public void configureRepositoryRestConfiguration(RepositoryRestConfiguration repositoryRestConfiguration,
+ CorsRegistry cors) {
+ repositoryRestConfiguration.getProjectionConfiguration()
+ .addProjection(PersonUpperNameProjection.class)
+ .addProjection(PersonLowerNameProjection.class);
+ }
+}
diff --git a/2022-02/spring-33/spring-data-rest/src/main/java/ru/otus/spring/microservice/domain/Person.java b/2022-02/spring-33/spring-data-rest/src/main/java/ru/otus/spring/microservice/domain/Person.java
new file mode 100644
index 00000000..aa4738a0
--- /dev/null
+++ b/2022-02/spring-33/spring-data-rest/src/main/java/ru/otus/spring/microservice/domain/Person.java
@@ -0,0 +1,41 @@
+package ru.otus.spring.microservice.domain;
+
+import ru.otus.spring.microservice.listeners.PersonEntityEventListener;
+
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+@Entity
+@EntityListeners(PersonEntityEventListener.class)
+public class Person {
+
+ @Id
+ @GeneratedValue
+ private int id;
+ private String name;
+
+ public Person() {
+ }
+
+ public Person(String name) {
+ this.name = name;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/2022-02/spring-33/spring-data-rest/src/main/java/ru/otus/spring/microservice/listeners/PersonEntityEventListener.java b/2022-02/spring-33/spring-data-rest/src/main/java/ru/otus/spring/microservice/listeners/PersonEntityEventListener.java
new file mode 100644
index 00000000..87ca0db7
--- /dev/null
+++ b/2022-02/spring-33/spring-data-rest/src/main/java/ru/otus/spring/microservice/listeners/PersonEntityEventListener.java
@@ -0,0 +1,12 @@
+package ru.otus.spring.microservice.listeners;
+
+import ru.otus.spring.microservice.domain.Person;
+
+import javax.persistence.PrePersist;
+
+public class PersonEntityEventListener {
+ @PrePersist
+ public void prePersist(Person p) {
+ p.setName(p.getName() + " (Человек и пароход)");
+ }
+}
diff --git a/2022-02/spring-33/spring-data-rest/src/main/java/ru/otus/spring/microservice/projections/PersonLowerNameProjection.java b/2022-02/spring-33/spring-data-rest/src/main/java/ru/otus/spring/microservice/projections/PersonLowerNameProjection.java
new file mode 100644
index 00000000..8f96c384
--- /dev/null
+++ b/2022-02/spring-33/spring-data-rest/src/main/java/ru/otus/spring/microservice/projections/PersonLowerNameProjection.java
@@ -0,0 +1,14 @@
+package ru.otus.spring.microservice.projections;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.rest.core.config.Projection;
+import ru.otus.spring.microservice.domain.Person;
+
+@Projection(name = "withlowername", types = Person.class)
+public interface PersonLowerNameProjection {
+
+ String getName();
+
+ @Value("#{target.name.toLowerCase()}")
+ String getNameLowerCase();
+}
diff --git a/2022-02/spring-33/spring-data-rest/src/main/java/ru/otus/spring/microservice/projections/PersonUpperNameProjection.java b/2022-02/spring-33/spring-data-rest/src/main/java/ru/otus/spring/microservice/projections/PersonUpperNameProjection.java
new file mode 100644
index 00000000..96ddffc5
--- /dev/null
+++ b/2022-02/spring-33/spring-data-rest/src/main/java/ru/otus/spring/microservice/projections/PersonUpperNameProjection.java
@@ -0,0 +1,14 @@
+package ru.otus.spring.microservice.projections;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.rest.core.config.Projection;
+import ru.otus.spring.microservice.domain.Person;
+
+@Projection(name = "withuppername", types = Person.class)
+public interface PersonUpperNameProjection {
+
+ String getName();
+
+ @Value("#{target.name.toUpperCase()}")
+ String getNameUpperCase();
+}
diff --git a/2022-02/spring-33/spring-data-rest/src/main/java/ru/otus/spring/microservice/repostory/PersonRepository.java b/2022-02/spring-33/spring-data-rest/src/main/java/ru/otus/spring/microservice/repostory/PersonRepository.java
new file mode 100644
index 00000000..b76263b6
--- /dev/null
+++ b/2022-02/spring-33/spring-data-rest/src/main/java/ru/otus/spring/microservice/repostory/PersonRepository.java
@@ -0,0 +1,11 @@
+package ru.otus.spring.microservice.repostory;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.rest.core.annotation.RepositoryRestResource;
+import ru.otus.spring.microservice.domain.Person;
+
+import java.util.List;
+
+@RepositoryRestResource(path = "persons", collectionResourceRel = "persons")
+public interface PersonRepository extends JpaRepository {
+}
diff --git a/2022-02/spring-33/spring-data-rest/src/main/resources/application.yml b/2022-02/spring-33/spring-data-rest/src/main/resources/application.yml
new file mode 100644
index 00000000..2db35bd1
--- /dev/null
+++ b/2022-02/spring-33/spring-data-rest/src/main/resources/application.yml
@@ -0,0 +1,4 @@
+spring:
+ data:
+ rest:
+ basePath: /api
\ No newline at end of file
diff --git a/2022-02/spring-33/spring-data-rest/src/main/resources/static/index.html b/2022-02/spring-33/spring-data-rest/src/main/resources/static/index.html
new file mode 100644
index 00000000..b8456b35
--- /dev/null
+++ b/2022-02/spring-33/spring-data-rest/src/main/resources/static/index.html
@@ -0,0 +1,89 @@
+
+
+
+
+ Пёрсоны
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file