From 321156a16eb5ea83baef73faac434456b07d1b5a Mon Sep 17 00:00:00 2001 From: "brunocarreira.silva" Date: Fri, 14 Sep 2018 18:29:14 -0300 Subject: [PATCH 01/26] pom --- pom.xml | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 pom.xml diff --git a/pom.xml b/pom.xml new file mode 100644 index 000000000..3af7313f4 --- /dev/null +++ b/pom.xml @@ -0,0 +1,52 @@ + + + 4.0.0 + + com.picpay + trabalhe-conosco-backend-dev + 1.0-SNAPSHOT + jar + + PicPay User Manager Service + User Manager Service using Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 1.5.8.RELEASE + + + + + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.security + spring-security-test + + + junit + junit + 4.12 + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file From 3afe9780eadfb312ad80f9840731eb372d8c2902 Mon Sep 17 00:00:00 2001 From: "brunocarreira.silva" Date: Tue, 18 Sep 2018 16:56:00 -0300 Subject: [PATCH 02/26] code base --- pom.xml | 76 +++++++++++++++++-- src/main/java/com/picpay/DatabaseLoader.java | 46 +++++++++++ .../com/picpay/UserManagerApplication.java | 17 +++++ .../com/picpay/controller/HomeController.java | 19 +++++ src/main/java/com/picpay/model/User.java | 27 +++++++ .../picpay/repositories/UserRepository.java | 11 +++ src/main/java/com/picpay/util/CsvUtil.java | 19 +++++ src/main/resources/application.properties | 6 ++ 8 files changed, 213 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/picpay/DatabaseLoader.java create mode 100644 src/main/java/com/picpay/UserManagerApplication.java create mode 100644 src/main/java/com/picpay/controller/HomeController.java create mode 100644 src/main/java/com/picpay/model/User.java create mode 100644 src/main/java/com/picpay/repositories/UserRepository.java create mode 100644 src/main/java/com/picpay/util/CsvUtil.java create mode 100644 src/main/resources/application.properties diff --git a/pom.xml b/pom.xml index 3af7313f4..eb4b261c6 100644 --- a/pom.xml +++ b/pom.xml @@ -15,8 +15,8 @@ org.springframework.boot spring-boot-starter-parent - 1.5.8.RELEASE - + 1.5.12.RELEASE + @@ -27,18 +27,40 @@ org.springframework.boot - spring-boot-starter-web + spring-boot-starter-thymeleaf - org.springframework.security - spring-security-test + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-data-rest + + + org.springframework.boot + spring-boot-devtools - junit - junit - 4.12 + org.projectlombok + lombok + + + com.h2database + h2 + runtime + + + org.springframework.boot + spring-boot-starter-test test + + + com.fasterxml.jackson.dataformat + jackson-dataformat-csv + + @@ -47,6 +69,44 @@ org.springframework.boot spring-boot-maven-plugin + + \ No newline at end of file diff --git a/src/main/java/com/picpay/DatabaseLoader.java b/src/main/java/com/picpay/DatabaseLoader.java new file mode 100644 index 000000000..3847bd1d0 --- /dev/null +++ b/src/main/java/com/picpay/DatabaseLoader.java @@ -0,0 +1,46 @@ +package com.picpay; + +import com.picpay.model.User; +import com.picpay.repositories.UserRepository; +import com.picpay.util.CsvUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.CommandLineRunner; +import org.springframework.core.io.ClassPathResource; +import org.springframework.stereotype.Component; + +import java.io.InputStream; +import java.net.URL; +import java.util.List; +import java.util.zip.GZIPInputStream; + +/** + * @author Bruno Carreira + */ +// tag::code[] +@Component +public class DatabaseLoader implements CommandLineRunner { + + @Value("${com.picpay.csv.database.url}") + private final String csvDatabaseUrl = null; + + @Value("${com.picpay.csv.database.filename}") + private final String csvDatabaseFilename = null; + + private final UserRepository repository; + + @Autowired + public DatabaseLoader(UserRepository repository) { + this.repository = repository; + } + + @Override + public void run(String... strings) throws Exception { + InputStream zipFileInputStream = new ClassPathResource(csvDatabaseFilename).getInputStream(); + //InputStream zipFileInputStream = new URL(csvDatabaseUrl).openStream(); + GZIPInputStream is = new GZIPInputStream(zipFileInputStream); + List users = CsvUtil.read(User.class, is); + this.repository.save(users); + } +} +// end::code[] \ No newline at end of file diff --git a/src/main/java/com/picpay/UserManagerApplication.java b/src/main/java/com/picpay/UserManagerApplication.java new file mode 100644 index 000000000..ca4f5d9d1 --- /dev/null +++ b/src/main/java/com/picpay/UserManagerApplication.java @@ -0,0 +1,17 @@ +package com.picpay; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author Bruno Carreira + */ +// tag::code[] +@SpringBootApplication +public class UserManagerApplication { + + public static void main(String[] args) { + SpringApplication.run(UserManagerApplication.class, args); + } +} +// end::code[] \ No newline at end of file diff --git a/src/main/java/com/picpay/controller/HomeController.java b/src/main/java/com/picpay/controller/HomeController.java new file mode 100644 index 000000000..622e1a4ec --- /dev/null +++ b/src/main/java/com/picpay/controller/HomeController.java @@ -0,0 +1,19 @@ +package com.picpay.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * @author Bruno Carreira + */ +// tag::code[] +@Controller +public class HomeController { + + @RequestMapping(value = "/") + public String index() { + return "index"; + } + +} +// end::code[] \ No newline at end of file diff --git a/src/main/java/com/picpay/model/User.java b/src/main/java/com/picpay/model/User.java new file mode 100644 index 000000000..672216a74 --- /dev/null +++ b/src/main/java/com/picpay/model/User.java @@ -0,0 +1,27 @@ +package com.picpay.model; + +import lombok.Data; +import javax.persistence.Entity; +import javax.persistence.Id; + +/** + * @author Bruno Carreira + */ +// tag::code[] +@Data +@Entity +public class User { + @Id + private String id; + private String name; + private String username; + + private User() {} + + public User(String id, String name, String username) { + this.id = id; + this.name = name; + this.username = username; + } +} +// end::code[] \ No newline at end of file diff --git a/src/main/java/com/picpay/repositories/UserRepository.java b/src/main/java/com/picpay/repositories/UserRepository.java new file mode 100644 index 000000000..ba7dd0d06 --- /dev/null +++ b/src/main/java/com/picpay/repositories/UserRepository.java @@ -0,0 +1,11 @@ +package com.picpay.repositories; + +import com.picpay.model.User; +import org.springframework.data.repository.PagingAndSortingRepository; + +/** + * @author Bruno Carreira + */ +public interface UserRepository extends PagingAndSortingRepository { + +} \ No newline at end of file diff --git a/src/main/java/com/picpay/util/CsvUtil.java b/src/main/java/com/picpay/util/CsvUtil.java new file mode 100644 index 000000000..dba2a6ac2 --- /dev/null +++ b/src/main/java/com/picpay/util/CsvUtil.java @@ -0,0 +1,19 @@ +package com.picpay.util; + +import com.fasterxml.jackson.databind.ObjectReader; +import com.fasterxml.jackson.dataformat.csv.CsvMapper; +import com.fasterxml.jackson.dataformat.csv.CsvSchema; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +public class CsvUtil { + + public static List read(Class clazz, InputStream stream) throws IOException { + final CsvMapper mapper = new CsvMapper(); + CsvSchema schema = mapper.schemaFor(clazz).withColumnReordering(true); + ObjectReader reader = mapper.readerFor(clazz).with(schema); + return reader.readValues(stream).readAll(); + } +} \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 000000000..f28dd504b --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,6 @@ +server.port = 8090 + +spring.data.rest.base-path=/api + +com.picpay.csv.database.url=https://s3.amazonaws.com/careers-picpay/users.csv.gz +com.picpay.csv.database.filename=users.csv.gz \ No newline at end of file From fc156438e69d3cfc4fb3595ebef0f0db6912de38 Mon Sep 17 00:00:00 2001 From: "brunocarreira.silva" Date: Tue, 18 Sep 2018 18:05:08 -0300 Subject: [PATCH 03/26] changes --- src/main/java/com/picpay/DatabaseLoader.java | 12 +++++++++--- src/main/java/com/picpay/util/CsvUtil.java | 6 +++--- src/main/resources/application.properties | 2 ++ src/main/resources/static/main.css | 9 +++++++++ src/main/resources/templates/index.html | 15 +++++++++++++++ 5 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 src/main/resources/static/main.css create mode 100644 src/main/resources/templates/index.html diff --git a/src/main/java/com/picpay/DatabaseLoader.java b/src/main/java/com/picpay/DatabaseLoader.java index 3847bd1d0..b0973b754 100644 --- a/src/main/java/com/picpay/DatabaseLoader.java +++ b/src/main/java/com/picpay/DatabaseLoader.java @@ -1,5 +1,6 @@ package com.picpay; +import com.fasterxml.jackson.databind.MappingIterator; import com.picpay.model.User; import com.picpay.repositories.UserRepository; import com.picpay.util.CsvUtil; @@ -11,7 +12,7 @@ import java.io.InputStream; import java.net.URL; -import java.util.List; +import java.util.logging.Logger; import java.util.zip.GZIPInputStream; /** @@ -29,6 +30,8 @@ public class DatabaseLoader implements CommandLineRunner { private final UserRepository repository; + private static final Logger logger = Logger.getLogger(DatabaseLoader.class.getName()); + @Autowired public DatabaseLoader(UserRepository repository) { this.repository = repository; @@ -39,8 +42,11 @@ public void run(String... strings) throws Exception { InputStream zipFileInputStream = new ClassPathResource(csvDatabaseFilename).getInputStream(); //InputStream zipFileInputStream = new URL(csvDatabaseUrl).openStream(); GZIPInputStream is = new GZIPInputStream(zipFileInputStream); - List users = CsvUtil.read(User.class, is); - this.repository.save(users); + MappingIterator it = CsvUtil.read(User.class, is); + while (it.hasNext()) { + this.repository.save(it.next()); + } + logger.info("...........>>>>>>>>>>LOAD COMPLETE<<<<<<<<<<<..........."); } } // end::code[] \ No newline at end of file diff --git a/src/main/java/com/picpay/util/CsvUtil.java b/src/main/java/com/picpay/util/CsvUtil.java index dba2a6ac2..1c792de88 100644 --- a/src/main/java/com/picpay/util/CsvUtil.java +++ b/src/main/java/com/picpay/util/CsvUtil.java @@ -1,19 +1,19 @@ package com.picpay.util; +import com.fasterxml.jackson.databind.MappingIterator; import com.fasterxml.jackson.databind.ObjectReader; import com.fasterxml.jackson.dataformat.csv.CsvMapper; import com.fasterxml.jackson.dataformat.csv.CsvSchema; import java.io.IOException; import java.io.InputStream; -import java.util.List; public class CsvUtil { - public static List read(Class clazz, InputStream stream) throws IOException { + public static MappingIterator read(Class clazz, InputStream stream) throws IOException { final CsvMapper mapper = new CsvMapper(); CsvSchema schema = mapper.schemaFor(clazz).withColumnReordering(true); ObjectReader reader = mapper.readerFor(clazz).with(schema); - return reader.readValues(stream).readAll(); + return reader.readValues(stream); } } \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index f28dd504b..525c2e02f 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -2,5 +2,7 @@ server.port = 8090 spring.data.rest.base-path=/api +spring.data.rest.default-page-size=15 + com.picpay.csv.database.url=https://s3.amazonaws.com/careers-picpay/users.csv.gz com.picpay.csv.database.filename=users.csv.gz \ No newline at end of file diff --git a/src/main/resources/static/main.css b/src/main/resources/static/main.css new file mode 100644 index 000000000..e59d00b3f --- /dev/null +++ b/src/main/resources/static/main.css @@ -0,0 +1,9 @@ +table { + border-collapse: collapse; +} + +td, th { + border: 1px solid #999; + padding: 0.5rem; + text-align: left; +} \ No newline at end of file diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html new file mode 100644 index 000000000..208e325d9 --- /dev/null +++ b/src/main/resources/templates/index.html @@ -0,0 +1,15 @@ + + + + + PicPay User Manager + + + + +
+ + + + + \ No newline at end of file From 88767011b78a8b0e231ce5c92aca8f46477b621a Mon Sep 17 00:00:00 2001 From: "brunocarreira.silva" Date: Wed, 19 Sep 2018 17:56:33 -0300 Subject: [PATCH 04/26] changes --- pom.xml | 8 +- src/main/java/com/picpay/BatchConfig.java | 100 ++++++++++++++++++ src/main/java/com/picpay/DBLogProcessor.java | 13 +++ src/main/java/com/picpay/DatabaseLoader.java | 10 +- src/main/java/com/picpay/model/User.java | 2 + .../picpay/repositories/UserRepository.java | 1 - src/main/java/com/picpay/util/CsvUtil.java | 1 + src/main/resources/application.properties | 4 +- 8 files changed, 128 insertions(+), 11 deletions(-) create mode 100644 src/main/java/com/picpay/BatchConfig.java create mode 100644 src/main/java/com/picpay/DBLogProcessor.java diff --git a/pom.xml b/pom.xml index eb4b261c6..c70e4971d 100644 --- a/pom.xml +++ b/pom.xml @@ -60,7 +60,10 @@ com.fasterxml.jackson.dataformat jackson-dataformat-csv - + + org.springframework.boot + spring-boot-starter-batch + @@ -68,6 +71,9 @@ org.springframework.boot spring-boot-maven-plugin + + -Xmx2048m + + \ No newline at end of file diff --git a/src/main/java/com/picpay/DatabaseLoader.java b/src/main/java/com/picpay/DatabaseLoader.java index b00da84a2..53001453b 100644 --- a/src/main/java/com/picpay/DatabaseLoader.java +++ b/src/main/java/com/picpay/DatabaseLoader.java @@ -1,6 +1,9 @@ package com.picpay; import com.fasterxml.jackson.databind.MappingIterator; +import com.fasterxml.jackson.databind.ObjectReader; +import com.fasterxml.jackson.dataformat.csv.CsvMapper; +import com.fasterxml.jackson.dataformat.csv.CsvSchema; import com.picpay.model.User; import com.picpay.repositories.UserRepository; import com.picpay.util.CsvUtil; @@ -10,9 +13,15 @@ import org.springframework.core.io.ClassPathResource; import org.springframework.stereotype.Component; +import java.io.BufferedReader; import java.io.InputStream; +import java.io.InputStreamReader; import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.List; +import java.util.stream.Stream; import java.util.zip.GZIPInputStream; /** @@ -40,7 +49,19 @@ public void run(String... strings) throws Exception { InputStream zipFileInputStream = new ClassPathResource(csvDatabaseFilename).getInputStream(); //InputStream zipFileInputStream = new URL(csvDatabaseUrl).openStream(); GZIPInputStream is = new GZIPInputStream(zipFileInputStream); - //repository.bulkLoadData(); + Stream lines = new BufferedReader(new InputStreamReader(is)).lines(); +/* + final CsvMapper mapper = new CsvMapper(); + CsvSchema schema = mapper.schemaFor(User.class).withColumnReordering(true); + ObjectReader reader = mapper.readerFor(User.class).with(schema); + + for( String line : (Iterable) lines::iterator ) + { + System.out.println(line); + User user = reader.readValue(line); + repository.save(user); + } + */ } } // end::code[] \ No newline at end of file diff --git a/src/main/java/com/picpay/util/CsvUtil.java b/src/main/java/com/picpay/util/CsvUtil.java index 8dec532f7..bfe84924b 100644 --- a/src/main/java/com/picpay/util/CsvUtil.java +++ b/src/main/java/com/picpay/util/CsvUtil.java @@ -17,4 +17,11 @@ public static MappingIterator read(Class clazz, InputStream stream) th return reader.readValues(stream); } + public static T readLine(Class clazz, String line) throws IOException { + final CsvMapper mapper = new CsvMapper(); + CsvSchema schema = mapper.schemaFor(clazz).withColumnReordering(true); + ObjectReader reader = mapper.readerFor(clazz).with(schema); + return reader.readValue(line); + } + } \ No newline at end of file diff --git a/src/main/js/api/uriListConverter.js b/src/main/js/api/uriListConverter.js new file mode 100644 index 000000000..1c2124eee --- /dev/null +++ b/src/main/js/api/uriListConverter.js @@ -0,0 +1,21 @@ +define(function() { + 'use strict'; + + /* Convert a single or array of resources into "URI1\nURI2\nURI3..." */ + return { + read: function(str /*, opts */) { + return str.split('\n'); + }, + write: function(obj /*, opts */) { + // If this is an Array, extract the self URI and then join using a newline + if (obj instanceof Array) { + return obj.map(function(resource) { + return resource._links.self.href; + }).join('\n'); + } else { // otherwise, just return the self URI + return obj._links.self.href; + } + } + }; + +}); diff --git a/src/main/js/api/uriTemplateInterceptor.js b/src/main/js/api/uriTemplateInterceptor.js new file mode 100644 index 000000000..269165f9e --- /dev/null +++ b/src/main/js/api/uriTemplateInterceptor.js @@ -0,0 +1,18 @@ +define(function(require) { + 'use strict'; + + var interceptor = require('rest/interceptor'); + + return interceptor({ + request: function (request /*, config, meta */) { + /* If the URI is a URI Template per RFC 6570 (http://tools.ietf.org/html/rfc6570), trim out the template part */ + if (request.path.indexOf('{') === -1) { + return request; + } else { + request.path = request.path.split('{')[0]; + return request; + } + } + }); + +}); \ No newline at end of file diff --git a/src/main/js/app.js b/src/main/js/app.js new file mode 100644 index 000000000..9bf724fd8 --- /dev/null +++ b/src/main/js/app.js @@ -0,0 +1,73 @@ +'use strict'; + +// tag::vars[] +const React = require('react'); +const ReactDOM = require('react-dom'); +const client = require('./client'); +// end::vars[] + +// tag::app[] +class App extends React.Component { + + constructor(props) { + super(props); + this.state = {users: []}; + } + + componentDidMount() { + client({method: 'GET', path: '/api/users'}).done(response => { + this.setState({users: response.entity._embedded.users}); + }); + } + + render() { + return ( + + ) + } +} +// end::app[] + +// tag::user-list[] +class UserList extends React.Component{ + render() { + var users = this.props.users.map(user => + + ); + return ( + + + + + + + + {users} + +
IdNameUsername
+ ) + } +} +// end::user-list[] + +// tag::user[] +class User extends React.Component{ + render() { + return ( + + {this.props.user.id} + {this.props.user.name} + {this.props.user.username} + + ) + } +} +// end::user[] + +// tag::render[] +ReactDOM.render( + , + document.getElementById('react') +) +// end::render[] + diff --git a/src/main/js/client.js b/src/main/js/client.js new file mode 100644 index 000000000..8e542c9e3 --- /dev/null +++ b/src/main/js/client.js @@ -0,0 +1,19 @@ +'use strict'; + +var rest = require('rest'); +var defaultRequest = require('rest/interceptor/defaultRequest'); +var mime = require('rest/interceptor/mime'); +var uriTemplateInterceptor = require('./api/uriTemplateInterceptor'); +var errorCode = require('rest/interceptor/errorCode'); +var baseRegistry = require('rest/mime/registry'); + +var registry = baseRegistry.child(); + +registry.register('text/uri-list', require('./api/uriListConverter')); +registry.register('application/hal+json', require('rest/mime/type/application/hal')); + +module.exports = rest + .wrap(mime, { registry: registry }) + .wrap(uriTemplateInterceptor) + .wrap(errorCode) + .wrap(defaultRequest, { headers: { 'Accept': 'application/hal+json' }}); diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 000000000..42ba3575c --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,25 @@ +var path = require('path'); + +module.exports = { + entry: './src/main/js/app.js', + devtool: 'sourcemaps', + cache: true, + debug: true, + output: { + path: __dirname, + filename: './src/main/resources/static/built/bundle.js' + }, + module: { + loaders: [ + { + test: path.join(__dirname, '.'), + exclude: /(node_modules)/, + loader: 'babel', + query: { + cacheDirectory: true, + presets: ['es2015', 'react'] + } + } + ] + } +}; \ No newline at end of file From 404ddb8303c1eaae319db200467033c77dcdaf97 Mon Sep 17 00:00:00 2001 From: "brunocarreira.silva" Date: Mon, 24 Sep 2018 16:29:40 -0300 Subject: [PATCH 06/26] changes --- Dockerfile | 4 ++ package.json | 1 + pom.xml | 7 ++- src/main/js/app.js | 1 + src/main/resources/application.properties | 30 ++++++++++-- src/main/resources/import.sql | 1 + .../picpay/repositories/UserRepositoryIT.java | 40 ++++++++++++++++ .../repositories/UserRepositoryTest.java | 47 +++++++++++++++++++ .../resources/application-test.properties | 2 + src/test/resources/import.sql | 1 + 10 files changed, 130 insertions(+), 4 deletions(-) create mode 100644 Dockerfile create mode 100644 src/main/resources/import.sql create mode 100644 src/test/java/com/picpay/repositories/UserRepositoryIT.java create mode 100644 src/test/java/com/picpay/repositories/UserRepositoryTest.java create mode 100644 src/test/resources/application-test.properties create mode 100644 src/test/resources/import.sql diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..aff0668b3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,4 @@ +FROM openjdk:8 +ADD target/user-search.jar user-search.jar +EXPOSE 8086 +ENTRYPOINT ["java", "-jar", "user-search.jar"] \ No newline at end of file diff --git a/package.json b/package.json index e69db79a7..eccd2f961 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "homepage": "https://github.com/spring-guides/tut-react-and-spring-data-rest", "dependencies": { "react": "^15.3.2", + "react-data-grid": "^4.0.8", "react-dom": "^15.3.2", "rest": "^1.3.1", "webpack": "^1.12.2" diff --git a/pom.xml b/pom.xml index 10caf5a9f..d40273978 100644 --- a/pom.xml +++ b/pom.xml @@ -48,6 +48,11 @@ com.h2database h2 + test + + + mysql + mysql-connector-java runtime @@ -72,7 +77,7 @@ org.springframework.boot spring-boot-maven-plugin - -Xmx2048m + user-search diff --git a/src/main/js/app.js b/src/main/js/app.js index 9bf724fd8..6aa9b27c0 100644 --- a/src/main/js/app.js +++ b/src/main/js/app.js @@ -4,6 +4,7 @@ const React = require('react'); const ReactDOM = require('react-dom'); const client = require('./client'); +const dataGrid = require('react-data-grid'); // end::vars[] // tag::app[] diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 2032c9997..99158627f 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,5 +1,3 @@ -server.port = 8090 - spring.data.rest.base-path=/api spring.data.rest.default-page-size=15 @@ -7,4 +5,30 @@ spring.data.rest.default-page-size=15 com.picpay.csv.database.url=https://s3.amazonaws.com/careers-picpay/users.csv.gz com.picpay.csv.database.filename=users.csv.gz -spring.jpa.hibernate.ddl-auto=create-drop \ No newline at end of file +# DataSource settings: set here your own configurations for the database +# connection. In this example we have "netgloo_blog" as database name and +# "root" as username and password. +spring.datasource.url = jdbc:mysql://mysql-standalone:3306/test +spring.datasource.username = sa +spring.datasource.password = password + +# Keep the connection alive if idle for a long time (needed in production) +spring.datasource.testWhileIdle = true +spring.datasource.validationQuery = SELECT 1 + +# Show or not log for each sql query +spring.jpa.show-sql = true + +# Hibernate ddl auto (create, create-drop, update) +spring.jpa.hibernate.ddl-auto = update + +# Naming strategy +spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy + +# Use spring.jpa.properties.* for Hibernate native properties (the prefix is +# stripped before adding them to the entity manager) + +# The SQL dialect makes Hibernate generate better SQL for the chosen database +spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect + +server.port=8086 \ No newline at end of file diff --git a/src/main/resources/import.sql b/src/main/resources/import.sql new file mode 100644 index 000000000..0197aaa1d --- /dev/null +++ b/src/main/resources/import.sql @@ -0,0 +1 @@ +INSERT INTO tb_user SELECT * FROM CSVREAD('classpath:/users.csv'); \ No newline at end of file diff --git a/src/test/java/com/picpay/repositories/UserRepositoryIT.java b/src/test/java/com/picpay/repositories/UserRepositoryIT.java new file mode 100644 index 000000000..36727ab67 --- /dev/null +++ b/src/test/java/com/picpay/repositories/UserRepositoryIT.java @@ -0,0 +1,40 @@ +package com.picpay.repositories; + +import com.picpay.UserManagerApplication; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +@RunWith(SpringRunner.class) +@SpringBootTest( + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + classes = UserManagerApplication.class +) +@AutoConfigureMockMvc +@TestPropertySource(locations = "classpath:application-test.properties") +public class UserRepositoryIT { + + @Autowired + MockMvc mockMvc; + + @Test + public void contextLoads() throws Exception { + + MvcResult mvcResult = mockMvc.perform( + MockMvcRequestBuilders.get("/") + .accept(MediaType.APPLICATION_JSON) + ).andReturn(); + + System.out.println(mvcResult.getResponse()); + + } + +} \ No newline at end of file diff --git a/src/test/java/com/picpay/repositories/UserRepositoryTest.java b/src/test/java/com/picpay/repositories/UserRepositoryTest.java new file mode 100644 index 000000000..4f977b568 --- /dev/null +++ b/src/test/java/com/picpay/repositories/UserRepositoryTest.java @@ -0,0 +1,47 @@ +package com.picpay.repositories; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +import java.util.Collections; + +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(SpringRunner.class) +@WebMvcTest +public class UserRepositoryTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private UserRepository userRepository; + + @Test + public void contextLoads() throws Exception { + + when(userRepository.findAll()).thenReturn( + Collections.emptyList() + ); + + MvcResult mvcResult = mockMvc.perform( + MockMvcRequestBuilders.get("/") + .accept(MediaType.APPLICATION_JSON) + ).andReturn(); + + System.out.println(mvcResult.getResponse()); + + verify(userRepository).findAll(); + + } + +} \ No newline at end of file diff --git a/src/test/resources/application-test.properties b/src/test/resources/application-test.properties new file mode 100644 index 000000000..342316f89 --- /dev/null +++ b/src/test/resources/application-test.properties @@ -0,0 +1,2 @@ +spring.datasource.url=jdbc:h2:mem:test +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect \ No newline at end of file diff --git a/src/test/resources/import.sql b/src/test/resources/import.sql new file mode 100644 index 000000000..9827bcee2 --- /dev/null +++ b/src/test/resources/import.sql @@ -0,0 +1 @@ +INSERT INTO tb_user SELECT * FROM CSVREAD('classpath:/users2.csv'); \ No newline at end of file From bccee64e8aea8cfc97f97d54d093573f70e1373e Mon Sep 17 00:00:00 2001 From: "brunocarreira.silva" Date: Tue, 25 Sep 2018 17:23:53 -0300 Subject: [PATCH 07/26] changes --- pom.xml | 2 +- src/main/java/com/picpay/DatabaseLoader.java | 1 + .../com/picpay/repositories/UserRepository.java | 6 ++++++ src/main/resources/application.properties | 17 +++++++++-------- src/main/resources/import.sql | 6 +++++- 5 files changed, 22 insertions(+), 10 deletions(-) diff --git a/pom.xml b/pom.xml index d40273978..d231443e0 100644 --- a/pom.xml +++ b/pom.xml @@ -48,7 +48,7 @@ com.h2database h2 - test + runtime mysql diff --git a/src/main/java/com/picpay/DatabaseLoader.java b/src/main/java/com/picpay/DatabaseLoader.java index 53001453b..2ec164f0e 100644 --- a/src/main/java/com/picpay/DatabaseLoader.java +++ b/src/main/java/com/picpay/DatabaseLoader.java @@ -50,6 +50,7 @@ public void run(String... strings) throws Exception { //InputStream zipFileInputStream = new URL(csvDatabaseUrl).openStream(); GZIPInputStream is = new GZIPInputStream(zipFileInputStream); Stream lines = new BufferedReader(new InputStreamReader(is)).lines(); + //repository.bulkLoad(); /* final CsvMapper mapper = new CsvMapper(); CsvSchema schema = mapper.schemaFor(User.class).withColumnReordering(true); diff --git a/src/main/java/com/picpay/repositories/UserRepository.java b/src/main/java/com/picpay/repositories/UserRepository.java index 31258b888..51c95ae0e 100644 --- a/src/main/java/com/picpay/repositories/UserRepository.java +++ b/src/main/java/com/picpay/repositories/UserRepository.java @@ -1,10 +1,16 @@ package com.picpay.repositories; import com.picpay.model.User; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.PagingAndSortingRepository; /** * @author Bruno Carreira */ public interface UserRepository extends PagingAndSortingRepository { + @Query(value = "LOAD DATA LOCAL INFILE :filename INTO TABLE tb_user;", + nativeQuery = true) + void bulkLoad(String filename); + + } \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 99158627f..4cb5ddb57 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -6,21 +6,22 @@ com.picpay.csv.database.url=https://s3.amazonaws.com/careers-picpay/users.csv.gz com.picpay.csv.database.filename=users.csv.gz # DataSource settings: set here your own configurations for the database -# connection. In this example we have "netgloo_blog" as database name and +# connection. In this example we have "test" as database name and # "root" as username and password. -spring.datasource.url = jdbc:mysql://mysql-standalone:3306/test -spring.datasource.username = sa -spring.datasource.password = password +#spring.datasource.url = jdbc:mysql://localhost:3306/test +spring.datasource.url=jdbc:h2:file:~/test;LOG=0;CACHE_SIZE=65536;LOCK_MODE=0;UNDO_LOG=0 +#spring.datasource.username = root +#spring.datasource.password = password # Keep the connection alive if idle for a long time (needed in production) -spring.datasource.testWhileIdle = true -spring.datasource.validationQuery = SELECT 1 +#spring.datasource.testWhileIdle = true +#spring.datasource.validationQuery = SELECT 1 # Show or not log for each sql query spring.jpa.show-sql = true # Hibernate ddl auto (create, create-drop, update) -spring.jpa.hibernate.ddl-auto = update +#spring.jpa.hibernate.ddl-auto = update # Naming strategy spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy @@ -29,6 +30,6 @@ spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy # stripped before adding them to the entity manager) # The SQL dialect makes Hibernate generate better SQL for the chosen database -spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect +# spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect server.port=8086 \ No newline at end of file diff --git a/src/main/resources/import.sql b/src/main/resources/import.sql index 0197aaa1d..8fea8870a 100644 --- a/src/main/resources/import.sql +++ b/src/main/resources/import.sql @@ -1 +1,5 @@ -INSERT INTO tb_user SELECT * FROM CSVREAD('classpath:/users.csv'); \ No newline at end of file +--INSERT INTO tb_user SELECT * FROM CSVREAD('classpath:/users.csv', 'id,name,username', null) WHERE name like '%Rafael%'; +DROP TABLE IF EXISTS tb_user; +CREATE TABLE tb_user(id varchar(255), name varchar(255), username varchar(255)) AS SELECT * FROM CSVREAD('classpath:/users.csv', 'id,name,username', null); + +--LOAD DATA LOCAL INFILE 'C:\\ProgramData\\MySQL\\MySQL Server 8.0\\Uploads\\users.csv' INTO TABLE tb_user; \ No newline at end of file From b0ad08c4dc3f340a303ad47e79ea3284d8e3492e Mon Sep 17 00:00:00 2001 From: "brunocarreira.silva" Date: Thu, 27 Sep 2018 17:47:13 -0300 Subject: [PATCH 08/26] changes --- package.json | 7 +- .../java/com/picpay/ApplicationStartup.java | 53 ++++++++++ src/main/java/com/picpay/BatchConfig.java | 100 ------------------ src/main/java/com/picpay/DBLogProcessor.java | 13 --- src/main/java/com/picpay/DatabaseLoader.java | 68 ------------ .../com/picpay/UserManagerApplication.java | 27 +++++ .../picpay/repositories/UserRepository.java | 11 +- .../java/com/picpay/service/UserService.java | 31 ++++++ src/main/js/app.js | 34 +++++- src/main/resources/application.properties | 2 + src/main/resources/import.sql | 7 +- webpack.config.js | 2 +- 12 files changed, 165 insertions(+), 190 deletions(-) create mode 100644 src/main/java/com/picpay/ApplicationStartup.java delete mode 100644 src/main/java/com/picpay/BatchConfig.java delete mode 100644 src/main/java/com/picpay/DBLogProcessor.java delete mode 100644 src/main/java/com/picpay/DatabaseLoader.java create mode 100644 src/main/java/com/picpay/service/UserService.java diff --git a/package.json b/package.json index eccd2f961..23b3b6776 100644 --- a/package.json +++ b/package.json @@ -20,9 +20,13 @@ }, "homepage": "https://github.com/spring-guides/tut-react-and-spring-data-rest", "dependencies": { + "bootstrap": "^4.1.3", + "bootstrap-less": "^3.3.8", + "less": "^3.8.1", "react": "^15.3.2", "react-data-grid": "^4.0.8", "react-dom": "^15.3.2", + "react-js-pagination": "^3.0.2", "rest": "^1.3.1", "webpack": "^1.12.2" }, @@ -34,6 +38,7 @@ "babel-loader": "^6.2.7", "babel-polyfill": "^6.16.0", "babel-preset-es2015": "^6.18.0", - "babel-preset-react": "^6.16.0" + "babel-preset-react": "^6.16.0", + "less-loader": "^4.1.0" } } diff --git a/src/main/java/com/picpay/ApplicationStartup.java b/src/main/java/com/picpay/ApplicationStartup.java new file mode 100644 index 000000000..20da928a1 --- /dev/null +++ b/src/main/java/com/picpay/ApplicationStartup.java @@ -0,0 +1,53 @@ +package com.picpay; + +import org.apache.tomcat.util.http.fileupload.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Component; + +import java.io.*; +import java.net.URL; +import java.nio.file.StandardCopyOption; +import java.util.zip.GZIPInputStream; + +/** + * @author Bruno Carreira + */ +// tag::code[] + /* +@Component +public class ApplicationStartup implements CommandLineRunner { + + @Value("${com.picpay.csv.database.url}") + private final String csvDatabaseUrl = null; + + @Value("${com.picpay.csv.database.filename}") + private final String csvDatabaseFilename = null; + + private static final Logger LOG = + LoggerFactory.getLogger(ApplicationStartup.class); + + @Override + public void run(String... strings) throws Exception { + System.out.println("Creating File....."); + LOG.info("Creating File...."); + InputStream zipFileInputStream = new URL(csvDatabaseUrl).openStream(); + GZIPInputStream is = new GZIPInputStream(zipFileInputStream); + + File targetFile = new File("src/main/resources/userstest.csv"); + + java.nio.file.Files.copy( + is, + targetFile.toPath(), + StandardCopyOption.REPLACE_EXISTING); + + //IOUtils.closeQuietly(is); + System.out.println("File is created!"); + LOG.info("File is created!"); + } + +} +*/ +// end::code[] \ No newline at end of file diff --git a/src/main/java/com/picpay/BatchConfig.java b/src/main/java/com/picpay/BatchConfig.java deleted file mode 100644 index 80a5a9667..000000000 --- a/src/main/java/com/picpay/BatchConfig.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.picpay; - -import com.picpay.model.User; -import com.picpay.repositories.UserRepository; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.Step; -import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; -import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; -import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; -import org.springframework.batch.core.launch.support.RunIdIncrementer; -import org.springframework.batch.item.ItemProcessor; -import org.springframework.batch.item.data.RepositoryItemWriter; -import org.springframework.batch.item.file.FlatFileItemReader; -import org.springframework.batch.item.file.LineMapper; -import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper; -import org.springframework.batch.item.file.mapping.DefaultLineMapper; -import org.springframework.batch.item.file.transform.DelimitedLineTokenizer; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.io.Resource; -/* -@Configuration -@EnableBatchProcessing -public class BatchConfig { - - @Autowired - private JobBuilderFactory jobBuilderFactory; - - @Autowired - private StepBuilderFactory stepBuilderFactory; - - @Value("classPath:/users.csv") - private Resource inputResource; - - private final UserRepository repository; - - @Autowired - public BatchConfig(UserRepository repository) { - this.repository = repository; - } - - @Bean - public Job readCSVFileJob() { - return jobBuilderFactory - .get("readCSVFileJob") - .incrementer(new RunIdIncrementer()) - .start(step()) - .build(); - } - - @Bean - public Step step() { - return stepBuilderFactory - .get("step") - .chunk(5) - .reader(reader()) - .processor(processor()) - .writer(writer()) - .build(); - } - - @Bean - public ItemProcessor processor() { - return new DBLogProcessor(); - } - - @Bean - public FlatFileItemReader reader() { - FlatFileItemReader itemReader = new FlatFileItemReader(); - itemReader.setLineMapper(lineMapper()); - //itemReader.setLinesToSkip(1); - itemReader.setResource(inputResource); - return itemReader; - } - - @Bean - public LineMapper lineMapper() { - DefaultLineMapper lineMapper = new DefaultLineMapper(); - DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer(); - lineTokenizer.setNames(new String[] { "id", "name", "username" }); - lineTokenizer.setIncludedFields(new int[] { 0, 1, 2 }); - BeanWrapperFieldSetMapper fieldSetMapper = new BeanWrapperFieldSetMapper(); - fieldSetMapper.setTargetType(User.class); - lineMapper.setLineTokenizer(lineTokenizer); - lineMapper.setFieldSetMapper(fieldSetMapper); - return lineMapper; - } - - @Bean - public RepositoryItemWriter writer() { - RepositoryItemWriter writer = new RepositoryItemWriter<>(); - writer.setRepository(repository); - writer.setMethodName("save"); - return writer; - } - -} -*/ \ No newline at end of file diff --git a/src/main/java/com/picpay/DBLogProcessor.java b/src/main/java/com/picpay/DBLogProcessor.java deleted file mode 100644 index 75ee77145..000000000 --- a/src/main/java/com/picpay/DBLogProcessor.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.picpay; - -import com.picpay.model.User; -import org.springframework.batch.item.ItemProcessor; - -public class DBLogProcessor implements ItemProcessor -{ - public User process(User user) throws Exception - { - System.out.println("Inserting user : " + user); - return user; - } -} \ No newline at end of file diff --git a/src/main/java/com/picpay/DatabaseLoader.java b/src/main/java/com/picpay/DatabaseLoader.java deleted file mode 100644 index 2ec164f0e..000000000 --- a/src/main/java/com/picpay/DatabaseLoader.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.picpay; - -import com.fasterxml.jackson.databind.MappingIterator; -import com.fasterxml.jackson.databind.ObjectReader; -import com.fasterxml.jackson.dataformat.csv.CsvMapper; -import com.fasterxml.jackson.dataformat.csv.CsvSchema; -import com.picpay.model.User; -import com.picpay.repositories.UserRepository; -import com.picpay.util.CsvUtil; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.CommandLineRunner; -import org.springframework.core.io.ClassPathResource; -import org.springframework.stereotype.Component; - -import java.io.BufferedReader; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.List; -import java.util.stream.Stream; -import java.util.zip.GZIPInputStream; - -/** - * @author Bruno Carreira - */ -// tag::code[] -@Component -public class DatabaseLoader implements CommandLineRunner { - - @Value("${com.picpay.csv.database.url}") - private final String csvDatabaseUrl = null; - - @Value("${com.picpay.csv.database.filename}") - private final String csvDatabaseFilename = null; - - private final UserRepository repository; - - @Autowired - public DatabaseLoader(UserRepository repository) { - this.repository = repository; - } - - @Override - public void run(String... strings) throws Exception { - InputStream zipFileInputStream = new ClassPathResource(csvDatabaseFilename).getInputStream(); - //InputStream zipFileInputStream = new URL(csvDatabaseUrl).openStream(); - GZIPInputStream is = new GZIPInputStream(zipFileInputStream); - Stream lines = new BufferedReader(new InputStreamReader(is)).lines(); - //repository.bulkLoad(); -/* - final CsvMapper mapper = new CsvMapper(); - CsvSchema schema = mapper.schemaFor(User.class).withColumnReordering(true); - ObjectReader reader = mapper.readerFor(User.class).with(schema); - - for( String line : (Iterable) lines::iterator ) - { - System.out.println(line); - User user = reader.readValue(line); - repository.save(user); - } - */ - } -} -// end::code[] \ No newline at end of file diff --git a/src/main/java/com/picpay/UserManagerApplication.java b/src/main/java/com/picpay/UserManagerApplication.java index ca4f5d9d1..2247a33b1 100644 --- a/src/main/java/com/picpay/UserManagerApplication.java +++ b/src/main/java/com/picpay/UserManagerApplication.java @@ -1,7 +1,17 @@ package com.picpay; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; +import java.util.stream.Collector; +import java.util.stream.Collectors; +import java.util.stream.Stream; /** * @author Bruno Carreira @@ -10,8 +20,25 @@ @SpringBootApplication public class UserManagerApplication { + @Value("${com.picpay.relevancia1}") + private final String relevancia1_txt = null; + + @Value("${com.picpay.relevancia2}") + private final String relevancia2_txt = null; + public static void main(String[] args) { SpringApplication.run(UserManagerApplication.class, args); } + + @Bean + public List listRelevancia1() throws IOException { + return Files.lines(Paths.get(relevancia1_txt)).collect(Collectors.toList()); + } + + @Bean + public List listRelevancia2() throws IOException { + return Files.lines(Paths.get(relevancia2_txt)).collect(Collectors.toList()); + } + } // end::code[] \ No newline at end of file diff --git a/src/main/java/com/picpay/repositories/UserRepository.java b/src/main/java/com/picpay/repositories/UserRepository.java index 51c95ae0e..1c2dd2bd6 100644 --- a/src/main/java/com/picpay/repositories/UserRepository.java +++ b/src/main/java/com/picpay/repositories/UserRepository.java @@ -4,13 +4,20 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.PagingAndSortingRepository; +import java.util.List; + /** * @author Bruno Carreira */ public interface UserRepository extends PagingAndSortingRepository { - @Query(value = "LOAD DATA LOCAL INFILE :filename INTO TABLE tb_user;", + + @Query(value = "SELECT * FROM tb_user" + + " JOIN (VALUES ?2 as r1(id, ordering) ON tb_user.id = r1.id" + + " JOIN (VALUES ?3 as r2(id, ordering) ON tb_user.id = r2.id" + + " WHERE (tb_user.name LIKE \"%?1%\") OR (tb_user.username LIKE \"%?1%\")" + + " ORDER BY x.ordering;", nativeQuery = true) - void bulkLoad(String filename); + List searchByCriteria(String criteria, String relevancia1, String relevancia2); } \ No newline at end of file diff --git a/src/main/java/com/picpay/service/UserService.java b/src/main/java/com/picpay/service/UserService.java new file mode 100644 index 000000000..de804bc7d --- /dev/null +++ b/src/main/java/com/picpay/service/UserService.java @@ -0,0 +1,31 @@ +package com.picpay.service; + +import com.picpay.model.User; +import com.picpay.repositories.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; +import java.util.stream.Collectors; + +public class UserService { + + UserRepository repository; + + @Autowired + List listRelevancia1; + + @Autowired + List listRelevancia2; + + @Autowired + public UserService(UserRepository repository){ + this.repository = repository; + } + + public List searchUsers(String criteria){ + //String rel1 = listRelevancia1.stream().map(id -> "("+id+",1),").reduce("", String::concat); + String rel1 = listRelevancia1.stream().map(id -> "("+id+",1)").collect(Collectors.joining(",")); + String rel2 = listRelevancia1.stream().map(id -> "("+id+",2)").collect(Collectors.joining(",")); + return repository.searchByCriteria(criteria, rel1, rel2); + } +} diff --git a/src/main/js/app.js b/src/main/js/app.js index 6aa9b27c0..5711efe2f 100644 --- a/src/main/js/app.js +++ b/src/main/js/app.js @@ -3,8 +3,12 @@ // tag::vars[] const React = require('react'); const ReactDOM = require('react-dom'); +import Pagination from "react-js-pagination"; +//require("bootstrap/less/bootstrap.less"); + + const client = require('./client'); -const dataGrid = require('react-data-grid'); +//const dataGrid = require('react-data-grid'); // end::vars[] // tag::app[] @@ -12,18 +16,40 @@ class App extends React.Component { constructor(props) { super(props); - this.state = {users: []}; + this.state = { + users: [], + activePage: 1, + itemPerPage: 15 + }; } + handlePageChange(pageNumber) { + console.log(`active page is ${pageNumber}`); + this.setState({activePage: pageNumber}); + } + componentDidMount() { - client({method: 'GET', path: '/api/users'}).done(response => { + client({method: 'GET', path: '/api/users?page'+this.state.activePage+'&size=15'}).done(response => { this.setState({users: response.entity._embedded.users}); }); } render() { return ( - +
+
+ +
+
+ +
+
) } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 4cb5ddb57..da50aa08e 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -4,6 +4,8 @@ spring.data.rest.default-page-size=15 com.picpay.csv.database.url=https://s3.amazonaws.com/careers-picpay/users.csv.gz com.picpay.csv.database.filename=users.csv.gz +com.picpay.relevancia1=lista_relevancia_1.txt +com.picpay.relevancia2=lista_relevancia_2.txt # DataSource settings: set here your own configurations for the database # connection. In this example we have "test" as database name and diff --git a/src/main/resources/import.sql b/src/main/resources/import.sql index 8fea8870a..443712ccf 100644 --- a/src/main/resources/import.sql +++ b/src/main/resources/import.sql @@ -1,5 +1,10 @@ --INSERT INTO tb_user SELECT * FROM CSVREAD('classpath:/users.csv', 'id,name,username', null) WHERE name like '%Rafael%'; DROP TABLE IF EXISTS tb_user; -CREATE TABLE tb_user(id varchar(255), name varchar(255), username varchar(255)) AS SELECT * FROM CSVREAD('classpath:/users.csv', 'id,name,username', null); +CREATE TABLE tb_user(id varchar(255), name varchar(255), username varchar(255)) AS SELECT * FROM CSVREAD('classpath:/users.csv', 'id,name,username', null) LIMIT 1000; +CREATE INDEX idxname ON tb_user(name, username); + +-- SELECT * FROM foo +-- JOIN (VALUES (67,1), (23,2), (1362,3), (24,4)) as x(id, ordering) ON foo.id = x.id +-- ORDER BY x.ordering --LOAD DATA LOCAL INFILE 'C:\\ProgramData\\MySQL\\MySQL Server 8.0\\Uploads\\users.csv' INTO TABLE tb_user; \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index 42ba3575c..48eaf0ad8 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -14,7 +14,7 @@ module.exports = { { test: path.join(__dirname, '.'), exclude: /(node_modules)/, - loader: 'babel', + loader: 'babel-loader', query: { cacheDirectory: true, presets: ['es2015', 'react'] From f28360e3aa3d8d4e111398f80c390d92dfef3ee1 Mon Sep 17 00:00:00 2001 From: "brunocarreira.silva" Date: Mon, 1 Oct 2018 14:57:46 -0300 Subject: [PATCH 09/26] changes --- .../com/picpay/controller/UserController.java | 30 +++++++++++++++++++ .../picpay/repositories/UserRepository.java | 6 ++-- .../java/com/picpay/service/UserService.java | 6 ++-- 3 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/picpay/controller/UserController.java diff --git a/src/main/java/com/picpay/controller/UserController.java b/src/main/java/com/picpay/controller/UserController.java new file mode 100644 index 000000000..5f99eddce --- /dev/null +++ b/src/main/java/com/picpay/controller/UserController.java @@ -0,0 +1,30 @@ +package com.picpay.controller; + +import com.picpay.model.User; +import com.picpay.service.UserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.rest.webmvc.RepositoryRestController; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @author Bruno Carreira + */ +// tag::code[] +@RepositoryRestController +public class UserController { + + @Autowired + private UserService service; + + @GetMapping("/api/search") + @ResponseStatus(HttpStatus.OK) + @ResponseBody + public List search(@RequestParam(value = "nome") String nome) { + return service.searchUsers(nome); + } +} +// end::code[] \ No newline at end of file diff --git a/src/main/java/com/picpay/repositories/UserRepository.java b/src/main/java/com/picpay/repositories/UserRepository.java index 1c2dd2bd6..6ab452aaf 100644 --- a/src/main/java/com/picpay/repositories/UserRepository.java +++ b/src/main/java/com/picpay/repositories/UserRepository.java @@ -3,17 +3,19 @@ import com.picpay.model.User; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.data.rest.core.annotation.RepositoryRestResource; import java.util.List; /** * @author Bruno Carreira */ + public interface UserRepository extends PagingAndSortingRepository { @Query(value = "SELECT * FROM tb_user" + - " JOIN (VALUES ?2 as r1(id, ordering) ON tb_user.id = r1.id" + - " JOIN (VALUES ?3 as r2(id, ordering) ON tb_user.id = r2.id" + + " LEFT OUTER JOIN (VALUES ?2 as r1(id, ordering) ON tb_user.id = r1.id" + + " LEFT OUTER JOIN (VALUES ?3 as r2(id, ordering) ON tb_user.id = r2.id" + " WHERE (tb_user.name LIKE \"%?1%\") OR (tb_user.username LIKE \"%?1%\")" + " ORDER BY x.ordering;", nativeQuery = true) diff --git a/src/main/java/com/picpay/service/UserService.java b/src/main/java/com/picpay/service/UserService.java index de804bc7d..f83e853ad 100644 --- a/src/main/java/com/picpay/service/UserService.java +++ b/src/main/java/com/picpay/service/UserService.java @@ -3,19 +3,21 @@ import com.picpay.model.User; import com.picpay.repositories.UserRepository; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; import java.util.List; import java.util.stream.Collectors; +@Service public class UserService { UserRepository repository; @Autowired - List listRelevancia1; + private List listRelevancia1; @Autowired - List listRelevancia2; + private List listRelevancia2; @Autowired public UserService(UserRepository repository){ From c361c3ec0307623354679e27c6b8d32e8234674a Mon Sep 17 00:00:00 2001 From: "brunocarreira.silva" Date: Wed, 3 Oct 2018 13:32:45 -0300 Subject: [PATCH 10/26] changes --- .../com/picpay/controller/UserController.java | 3 +- .../picpay/repositories/UserRepository.java | 29 ++++++++++++++----- .../java/com/picpay/service/UserService.java | 3 +- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/picpay/controller/UserController.java b/src/main/java/com/picpay/controller/UserController.java index 5f99eddce..c3f2b06b1 100644 --- a/src/main/java/com/picpay/controller/UserController.java +++ b/src/main/java/com/picpay/controller/UserController.java @@ -19,12 +19,13 @@ public class UserController { @Autowired private UserService service; - +/* @GetMapping("/api/search") @ResponseStatus(HttpStatus.OK) @ResponseBody public List search(@RequestParam(value = "nome") String nome) { return service.searchUsers(nome); } + */ } // end::code[] \ No newline at end of file diff --git a/src/main/java/com/picpay/repositories/UserRepository.java b/src/main/java/com/picpay/repositories/UserRepository.java index 6ab452aaf..f172d2343 100644 --- a/src/main/java/com/picpay/repositories/UserRepository.java +++ b/src/main/java/com/picpay/repositories/UserRepository.java @@ -1,9 +1,13 @@ package com.picpay.repositories; import com.picpay.model.User; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.data.repository.query.Param; import org.springframework.data.rest.core.annotation.RepositoryRestResource; +import org.springframework.data.rest.core.annotation.RestResource; import java.util.List; @@ -12,14 +16,25 @@ */ public interface UserRepository extends PagingAndSortingRepository { - - @Query(value = "SELECT * FROM tb_user" + - " LEFT OUTER JOIN (VALUES ?2 as r1(id, ordering) ON tb_user.id = r1.id" + +/* + @Query(value = "Select u from User u " + + " left outer join VALUES (1232, 1), (43321, 1) as r1(id, ordering) ON u.id = r1.id" + + " where (u.name like %:nome%) or (u.username like %:nome%)") + @RestResource(path = "searchNome", rel = "searchNome") + Page findByNome(@Param("nome") String nome, Pageable p); +*/ + @Query(value = "SELECT * FROM tb_user u " + + " left outer join (VALUES (1232, 1), (43321, 1) as r1(id, ordering)) ON u.id = r1.id" + + " where (u.name like %:name%) or (u.username like %:name%) order by u.id \n-- #pageable\n", + countQuery = "SELECT count(*) FROM tb_user", + nativeQuery = true + ) +/* " LEFT OUTER JOIN (VALUES ?2 as r1(id, ordering) ON tb_user.id = r1.id" + " LEFT OUTER JOIN (VALUES ?3 as r2(id, ordering) ON tb_user.id = r2.id" + - " WHERE (tb_user.name LIKE \"%?1%\") OR (tb_user.username LIKE \"%?1%\")" + - " ORDER BY x.ordering;", - nativeQuery = true) - List searchByCriteria(String criteria, String relevancia1, String relevancia2); + " where (u.name like %:nome%) or (u.username like %:nome%)" + + " ORDER BY x.ordering \n#pageable\n")*/ + @RestResource(path = "searchName", rel = "searchName") + Page findByName(@Param("name") String name, Pageable pageable); } \ No newline at end of file diff --git a/src/main/java/com/picpay/service/UserService.java b/src/main/java/com/picpay/service/UserService.java index f83e853ad..7999b576e 100644 --- a/src/main/java/com/picpay/service/UserService.java +++ b/src/main/java/com/picpay/service/UserService.java @@ -23,11 +23,12 @@ public class UserService { public UserService(UserRepository repository){ this.repository = repository; } - +/* public List searchUsers(String criteria){ //String rel1 = listRelevancia1.stream().map(id -> "("+id+",1),").reduce("", String::concat); String rel1 = listRelevancia1.stream().map(id -> "("+id+",1)").collect(Collectors.joining(",")); String rel2 = listRelevancia1.stream().map(id -> "("+id+",2)").collect(Collectors.joining(",")); return repository.searchByCriteria(criteria, rel1, rel2); } + */ } From 2d18d2301501cf9e4ad252750d3102a0da36a01f Mon Sep 17 00:00:00 2001 From: Bruno Carreira Date: Fri, 5 Oct 2018 00:32:23 +0000 Subject: [PATCH 11/26] ui --- src/main/js/app.js | 201 +++++++++++++++++++++++++++++++----------- src/main/js/follow.js | 40 +++++++++ 2 files changed, 188 insertions(+), 53 deletions(-) create mode 100644 src/main/js/follow.js diff --git a/src/main/js/app.js b/src/main/js/app.js index 5711efe2f..b123427d2 100644 --- a/src/main/js/app.js +++ b/src/main/js/app.js @@ -1,84 +1,182 @@ 'use strict'; -// tag::vars[] const React = require('react'); const ReactDOM = require('react-dom'); -import Pagination from "react-js-pagination"; -//require("bootstrap/less/bootstrap.less"); +const client = require('./client'); +const follow = require('./follow'); // function to hop multiple links by "rel" -const client = require('./client'); -//const dataGrid = require('react-data-grid'); -// end::vars[] +const root = '/api'; -// tag::app[] class App extends React.Component { constructor(props) { super(props); - this.state = { - users: [], - activePage: 1, - itemPerPage: 15 - }; + this.state = {users: [], attributes: [], pageSize: 20, links: {}}; + this.updatePageSize = this.updatePageSize.bind(this); + //this.onCreate = this.onCreate.bind(this); + //this.onDelete = this.onDelete.bind(this); + this.onNavigate = this.onNavigate.bind(this); } - handlePageChange(pageNumber) { - console.log(`active page is ${pageNumber}`); - this.setState({activePage: pageNumber}); - } + // tag::follow-2[] + loadFromServer(pageSize) { + follow(client, root, [ + {rel: 'users', params: {size: pageSize}}] + ).then(userCollection => { + return client({ + method: 'GET', + path: userCollection.entity._links.profile.href, + headers: {'Accept': 'application/schema+json'} + }).then(schema => { + this.schema = schema.entity; + return userCollection; + }); + }).done(userCollection => { + this.setState({ + users: userCollection.entity._embedded.users, + attributes: Object.keys(this.schema.properties), + pageSize: pageSize, + links: userCollection.entity._links}); + }); + } + // end::follow-2[] - componentDidMount() { - client({method: 'GET', path: '/api/users?page'+this.state.activePage+'&size=15'}).done(response => { - this.setState({users: response.entity._embedded.users}); + // tag::navigate[] + onNavigate(navUri) { + client({method: 'GET', path: navUri}).done(userCollection => { + this.setState({ + users: userCollection.entity._embedded.users, + attributes: this.state.attributes, + pageSize: this.state.pageSize, + links: userCollection.entity._links + }); }); } + // end::navigate[] + + // tag::update-page-size[] + updatePageSize(pageSize) { + if (pageSize !== this.state.pageSize) { + this.loadFromServer(pageSize); + } + } + // end::update-page-size[] + + // tag::follow-1[] + componentDidMount() { + this.loadFromServer(this.state.pageSize); + } + // end::follow-1[] render() { return ( -
-
- -
-
- -
-
+
+ +
) } } -// end::app[] -// tag::user-list[] -class UserList extends React.Component{ +class UserList extends React.Component { + + constructor(props) { + super(props); + this.handleNavFirst = this.handleNavFirst.bind(this); + this.handleNavPrev = this.handleNavPrev.bind(this); + this.handleNavNext = this.handleNavNext.bind(this); + this.handleNavLast = this.handleNavLast.bind(this); + this.handleInput = this.handleInput.bind(this); + } + + // tag::handle-page-size-updates[] + handleInput(e) { + e.preventDefault(); + const pageSize = ReactDOM.findDOMNode(this.refs.pageSize).value; + if (/^[0-9]+$/.test(pageSize)) { + this.props.updatePageSize(pageSize); + } else { + ReactDOM.findDOMNode(this.refs.pageSize).value = + pageSize.substring(0, pageSize.length - 1); + } + } + // end::handle-page-size-updates[] + + // tag::handle-nav[] + handleNavFirst(e){ + e.preventDefault(); + this.props.onNavigate(this.props.links.first.href); + } + + handleNavPrev(e) { + e.preventDefault(); + this.props.onNavigate(this.props.links.prev.href); + } + + handleNavNext(e) { + e.preventDefault(); + this.props.onNavigate(this.props.links.next.href); + } + + handleNavLast(e) { + e.preventDefault(); + this.props.onNavigate(this.props.links.last.href); + } + // end::handle-nav[] + + // tag::user-list-render[] render() { - var users = this.props.users.map(user => - + const users = this.props.users.map(user => + ); + + const navLinks = []; + if ("first" in this.props.links) { + navLinks.push(); + } + if ("prev" in this.props.links) { + navLinks.push(); + } + if ("next" in this.props.links) { + navLinks.push(); + } + if ("last" in this.props.links) { + navLinks.push(); + } + return ( - - - - - - - - {users} - -
IdNameUsername
+
+ + + + + + + + + {users} + +
IdNameUsername
+
+ {navLinks} +
+
) } + // end::user-list-render[] } -// end::user-list[] // tag::user[] -class User extends React.Component{ +class User extends React.Component { + + constructor(props) { + super(props); + } + render() { return ( @@ -91,10 +189,7 @@ class User extends React.Component{ } // end::user[] -// tag::render[] ReactDOM.render( , document.getElementById('react') ) -// end::render[] - diff --git a/src/main/js/follow.js b/src/main/js/follow.js new file mode 100644 index 000000000..59efe7049 --- /dev/null +++ b/src/main/js/follow.js @@ -0,0 +1,40 @@ +module.exports = function follow(api, rootPath, relArray) { + const root = api({ + method: 'GET', + path: rootPath + }); + + return relArray.reduce(function(root, arrayItem) { + const rel = typeof arrayItem === 'string' ? arrayItem : arrayItem.rel; + return traverseNext(root, rel, arrayItem); + }, root); + + function traverseNext (root, rel, arrayItem) { + return root.then(function (response) { + if (hasEmbeddedRel(response.entity, rel)) { + return response.entity._embedded[rel]; + } + + if(!response.entity._links) { + return []; + } + + if (typeof arrayItem === 'string') { + return api({ + method: 'GET', + path: response.entity._links[rel].href + }); + } else { + return api({ + method: 'GET', + path: response.entity._links[rel].href, + params: arrayItem.params + }); + } + }); + } + + function hasEmbeddedRel (entity, rel) { + return entity._embedded && entity._embedded.hasOwnProperty(rel); + } +}; From 673991c80db45b7ecaaf567e95c09a45f3d91817 Mon Sep 17 00:00:00 2001 From: "brunocarreira.silva" Date: Fri, 5 Oct 2018 14:55:11 -0300 Subject: [PATCH 12/26] changes --- .../com/picpay/UserManagerApplication.java | 17 ++++++++++++++--- .../com/picpay/controller/UserController.java | 2 +- src/main/java/com/picpay/model/User.java | 6 +++--- .../picpay/repositories/UserRepository.java | 18 +++++++++--------- 4 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/picpay/UserManagerApplication.java b/src/main/java/com/picpay/UserManagerApplication.java index 2247a33b1..a92d65417 100644 --- a/src/main/java/com/picpay/UserManagerApplication.java +++ b/src/main/java/com/picpay/UserManagerApplication.java @@ -3,6 +3,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import java.io.IOException; @@ -21,13 +22,23 @@ public class UserManagerApplication { @Value("${com.picpay.relevancia1}") - private final String relevancia1_txt = null; + private String relevancia1_txt = null; @Value("${com.picpay.relevancia2}") - private final String relevancia2_txt = null; + private String relevancia2_txt = null; - public static void main(String[] args) { + public static void main(String[] args){ SpringApplication.run(UserManagerApplication.class, args); +/* + List lr1 = Files.lines(Paths.get(relevancia1_txt)).collect(Collectors.toList()); + List lr2 = Files.lines(Paths.get(relevancia2_txt)).collect(Collectors.toList()); + String rel1 = lr1.stream().map(id -> "("+id+",1)").collect(Collectors.joining(",")); + String rel2 = lr2.stream().map(id -> "("+id+",2)").collect(Collectors.joining(",")); + CUSTOM_QUERY = "SELECT * FROM tb_user u " + + " LEFT OUTER JOIN (VALUES "+rel1+") as r1(id, ordering) ON u.id = r1.id" + + " LEFT OUTER JOIN (VALUES "+rel2+") as r2(id, ordering) ON u.id = r2.id" + + " where (u.name like %:name%) or (u.username like %:name%) order by u.id \n-- #pageable\n"; + */ } @Bean diff --git a/src/main/java/com/picpay/controller/UserController.java b/src/main/java/com/picpay/controller/UserController.java index c3f2b06b1..4970364bf 100644 --- a/src/main/java/com/picpay/controller/UserController.java +++ b/src/main/java/com/picpay/controller/UserController.java @@ -14,7 +14,7 @@ * @author Bruno Carreira */ // tag::code[] -@RepositoryRestController +//@RepositoryRestController public class UserController { @Autowired diff --git a/src/main/java/com/picpay/model/User.java b/src/main/java/com/picpay/model/User.java index 2640cc16a..67b0c949d 100644 --- a/src/main/java/com/picpay/model/User.java +++ b/src/main/java/com/picpay/model/User.java @@ -14,14 +14,14 @@ @Table(name = "tb_user") public class User { @Id - private String id; + private String Id; private String name; private String username; private User() {} - public User(String id, String name, String username) { - this.id = id; + public User(String Id, String name, String username) { + this.Id = Id; this.name = name; this.username = username; } diff --git a/src/main/java/com/picpay/repositories/UserRepository.java b/src/main/java/com/picpay/repositories/UserRepository.java index f172d2343..b4310c604 100644 --- a/src/main/java/com/picpay/repositories/UserRepository.java +++ b/src/main/java/com/picpay/repositories/UserRepository.java @@ -16,23 +16,23 @@ */ public interface UserRepository extends PagingAndSortingRepository { -/* + String query = "SELECT * FROM tb_user u " + + " LEFT OUTER JOIN (VALUES rel1) as r1(id, ordering) ON u.id = r1.id " + + " LEFT OUTER JOIN (VALUES rel2) as r2(id, ordering) ON u.id = r2.id " + + " where (u.name like %:name%) or (u.username like %:name%) order by u.id \n-- #pageable\n"; + String COUNT_QUERY = "SELECT count(*) FROM tb_user"; + + /* @Query(value = "Select u from User u " + " left outer join VALUES (1232, 1), (43321, 1) as r1(id, ordering) ON u.id = r1.id" + " where (u.name like %:nome%) or (u.username like %:nome%)") @RestResource(path = "searchNome", rel = "searchNome") Page findByNome(@Param("nome") String nome, Pageable p); */ - @Query(value = "SELECT * FROM tb_user u " + - " left outer join (VALUES (1232, 1), (43321, 1) as r1(id, ordering)) ON u.id = r1.id" + - " where (u.name like %:name%) or (u.username like %:name%) order by u.id \n-- #pageable\n", - countQuery = "SELECT count(*) FROM tb_user", + @Query(value = query, + countQuery = COUNT_QUERY, nativeQuery = true ) -/* " LEFT OUTER JOIN (VALUES ?2 as r1(id, ordering) ON tb_user.id = r1.id" + - " LEFT OUTER JOIN (VALUES ?3 as r2(id, ordering) ON tb_user.id = r2.id" + - " where (u.name like %:nome%) or (u.username like %:nome%)" + - " ORDER BY x.ordering \n#pageable\n")*/ @RestResource(path = "searchName", rel = "searchName") Page findByName(@Param("name") String name, Pageable pageable); From 6568c0b8dd2498da6fc26f4580ee3d26b7a2b0fa Mon Sep 17 00:00:00 2001 From: "brunocarreira.silva" Date: Mon, 8 Oct 2018 16:04:22 -0300 Subject: [PATCH 13/26] changes --- .../com/picpay/controller/UserController.java | 31 ----------- .../controller/UserSearchController.java | 51 +++++++++++++++++++ .../picpay/repositories/UserRepository.java | 15 +++--- 3 files changed, 59 insertions(+), 38 deletions(-) delete mode 100644 src/main/java/com/picpay/controller/UserController.java create mode 100644 src/main/java/com/picpay/controller/UserSearchController.java diff --git a/src/main/java/com/picpay/controller/UserController.java b/src/main/java/com/picpay/controller/UserController.java deleted file mode 100644 index 4970364bf..000000000 --- a/src/main/java/com/picpay/controller/UserController.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.picpay.controller; - -import com.picpay.model.User; -import com.picpay.service.UserService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.rest.webmvc.RepositoryRestController; -import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * @author Bruno Carreira - */ -// tag::code[] -//@RepositoryRestController -public class UserController { - - @Autowired - private UserService service; -/* - @GetMapping("/api/search") - @ResponseStatus(HttpStatus.OK) - @ResponseBody - public List search(@RequestParam(value = "nome") String nome) { - return service.searchUsers(nome); - } - */ -} -// end::code[] \ No newline at end of file diff --git a/src/main/java/com/picpay/controller/UserSearchController.java b/src/main/java/com/picpay/controller/UserSearchController.java new file mode 100644 index 000000000..5c22b90cf --- /dev/null +++ b/src/main/java/com/picpay/controller/UserSearchController.java @@ -0,0 +1,51 @@ +package com.picpay.controller; + +import com.picpay.model.User; +import com.picpay.repositories.UserRepository; +import com.picpay.service.UserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.rest.webmvc.RepositoryRestController; +import org.springframework.data.web.PagedResourcesAssembler; +import org.springframework.hateoas.PagedResources; +import org.springframework.hateoas.Resource; +import org.springframework.hateoas.Resources; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author Bruno Carreira + */ +// tag::code[] +@RepositoryRestController +public class UserSearchController { + + @Autowired + private UserRepository repo; + + @Autowired + private List listRelevancia1; + + @Autowired + private List listRelevancia2; + + @Autowired + private PagedResourcesAssembler pagedAssembler; + + @RequestMapping(value = "/users/search/listUsers", method = RequestMethod.GET) + public @ResponseBody PagedResources> search(@RequestParam(value = "nome") String nome, Pageable pageable) { + String rel1 = listRelevancia1.stream().map(id -> "("+id+",1)").collect(Collectors.joining(",")); + String rel2 = listRelevancia2.stream().map(id -> "("+id+",2)").collect(Collectors.joining(",")); + + Page users = repo.findByName(nome, rel1,/* rel2,*/ pageable); + return pagedAssembler.toResource(users); + } + +} +// end::code[] \ No newline at end of file diff --git a/src/main/java/com/picpay/repositories/UserRepository.java b/src/main/java/com/picpay/repositories/UserRepository.java index b4310c604..55b6bc3ad 100644 --- a/src/main/java/com/picpay/repositories/UserRepository.java +++ b/src/main/java/com/picpay/repositories/UserRepository.java @@ -16,11 +16,12 @@ */ public interface UserRepository extends PagingAndSortingRepository { - String query = "SELECT * FROM tb_user u " + - " LEFT OUTER JOIN (VALUES rel1) as r1(id, ordering) ON u.id = r1.id " + - " LEFT OUTER JOIN (VALUES rel2) as r2(id, ordering) ON u.id = r2.id " + - " where (u.name like %:name%) or (u.username like %:name%) order by u.id \n-- #pageable\n"; - String COUNT_QUERY = "SELECT count(*) FROM tb_user"; + String BASE_QUERY = "FROM tb_user u " + + " LEFT OUTER JOIN (VALUES :rel1) as r1 ON u.id = r1.C1 " + + //" LEFT OUTER JOIN (VALUES :rel2) as r2(id, ordering) ON u.id = r2.id " + + " where (u.name like %:name%) or (u.username like %:name%) order by r1.C2 \n-- #pageable\n"; + String query = "SELECT * " + BASE_QUERY; + String COUNT_QUERY = "SELECT count(*) " + BASE_QUERY; /* @Query(value = "Select u from User u " + @@ -33,8 +34,8 @@ public interface UserRepository extends PagingAndSortingRepository countQuery = COUNT_QUERY, nativeQuery = true ) - @RestResource(path = "searchName", rel = "searchName") - Page findByName(@Param("name") String name, Pageable pageable); + //@RestResource(path = "searchName", rel = "searchName") + Page findByName(@Param("name") String name, @Param("rel1") String rel1,/* @Param("rel2") String rel2, */@Param("pageable") Pageable pageable); } \ No newline at end of file From 7d2ad03d94475780677a85650fe0ecfb81f9cd23 Mon Sep 17 00:00:00 2001 From: "brunocarreira.silva" Date: Tue, 9 Oct 2018 15:14:59 -0300 Subject: [PATCH 14/26] changes --- .../controller/UserSearchController.java | 12 +++++++- .../picpay/repositories/UserRepository.java | 30 ++----------------- .../com/picpay/util/UserSpecifications.java | 27 +++++++++++++++++ 3 files changed, 40 insertions(+), 29 deletions(-) create mode 100644 src/main/java/com/picpay/util/UserSpecifications.java diff --git a/src/main/java/com/picpay/controller/UserSearchController.java b/src/main/java/com/picpay/controller/UserSearchController.java index 5c22b90cf..7a8c745af 100644 --- a/src/main/java/com/picpay/controller/UserSearchController.java +++ b/src/main/java/com/picpay/controller/UserSearchController.java @@ -3,9 +3,12 @@ import com.picpay.model.User; import com.picpay.repositories.UserRepository; import com.picpay.service.UserService; +import com.picpay.util.UserSpecifications; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.data.jpa.domain.Specifications; import org.springframework.data.rest.webmvc.RepositoryRestController; import org.springframework.data.web.PagedResourcesAssembler; import org.springframework.hateoas.PagedResources; @@ -16,6 +19,9 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; +import javax.persistence.criteria.Predicate; +import java.util.Arrays; +import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; @@ -43,9 +49,13 @@ public class UserSearchController { String rel1 = listRelevancia1.stream().map(id -> "("+id+",1)").collect(Collectors.joining(",")); String rel2 = listRelevancia2.stream().map(id -> "("+id+",2)").collect(Collectors.joining(",")); - Page users = repo.findByName(nome, rel1,/* rel2,*/ pageable); + //users.sort(Comparator.comparing(u->listRelevancia1.indexOf(u.getId()))); + + Page users = repo.findAll(Specifications.where(UserSpecifications.containsTextInName(nome)), pageable); + return pagedAssembler.toResource(users); } + } // end::code[] \ No newline at end of file diff --git a/src/main/java/com/picpay/repositories/UserRepository.java b/src/main/java/com/picpay/repositories/UserRepository.java index 55b6bc3ad..3bd92cfcf 100644 --- a/src/main/java/com/picpay/repositories/UserRepository.java +++ b/src/main/java/com/picpay/repositories/UserRepository.java @@ -3,39 +3,13 @@ import com.picpay.model.User; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.repository.Query; +import org.springframework.data.jpa.domain.Specification; import org.springframework.data.repository.PagingAndSortingRepository; -import org.springframework.data.repository.query.Param; -import org.springframework.data.rest.core.annotation.RepositoryRestResource; -import org.springframework.data.rest.core.annotation.RestResource; - -import java.util.List; /** * @author Bruno Carreira */ public interface UserRepository extends PagingAndSortingRepository { - String BASE_QUERY = "FROM tb_user u " + - " LEFT OUTER JOIN (VALUES :rel1) as r1 ON u.id = r1.C1 " + - //" LEFT OUTER JOIN (VALUES :rel2) as r2(id, ordering) ON u.id = r2.id " + - " where (u.name like %:name%) or (u.username like %:name%) order by r1.C2 \n-- #pageable\n"; - String query = "SELECT * " + BASE_QUERY; - String COUNT_QUERY = "SELECT count(*) " + BASE_QUERY; - - /* - @Query(value = "Select u from User u " + - " left outer join VALUES (1232, 1), (43321, 1) as r1(id, ordering) ON u.id = r1.id" + - " where (u.name like %:nome%) or (u.username like %:nome%)") - @RestResource(path = "searchNome", rel = "searchNome") - Page findByNome(@Param("nome") String nome, Pageable p); -*/ - @Query(value = query, - countQuery = COUNT_QUERY, - nativeQuery = true - ) - //@RestResource(path = "searchName", rel = "searchName") - Page findByName(@Param("name") String name, @Param("rel1") String rel1,/* @Param("rel2") String rel2, */@Param("pageable") Pageable pageable); - - + Page findAll(Specification spec, Pageable pageable); } \ No newline at end of file diff --git a/src/main/java/com/picpay/util/UserSpecifications.java b/src/main/java/com/picpay/util/UserSpecifications.java new file mode 100644 index 000000000..089494722 --- /dev/null +++ b/src/main/java/com/picpay/util/UserSpecifications.java @@ -0,0 +1,27 @@ +package com.picpay.util; + +import com.picpay.model.User; +import org.springframework.data.jpa.domain.Specification; + +import javax.persistence.criteria.Predicate; +import java.util.Arrays; +import java.util.List; + +public class UserSpecifications { + + public static Specification containsTextInAttributes(String text, List attributes) { + if (!text.contains("%")) { + text = "%" + text + "%"; + } + String finalText = text; + return (root, query, builder) -> builder.or(root.getModel().getDeclaredSingularAttributes().stream() + .filter(a -> attributes.contains(a.getName())) + .map(a -> builder.like(root.get(a.getName()), finalText)) + .toArray(Predicate[]::new) + ); + } + + public static Specification containsTextInName(String text) { + return containsTextInAttributes(text, Arrays.asList("name", "username")); + } +} From c45e8fc49477b177f385457fa9212788dbdd8a66 Mon Sep 17 00:00:00 2001 From: Bruno Carreira Date: Tue, 9 Oct 2018 18:37:04 -0300 Subject: [PATCH 15/26] changes --- src/main/js/app.js | 47 ++++++++++++++----- .../repositories/UserRepositoryTest.java | 2 +- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/main/js/app.js b/src/main/js/app.js index b123427d2..39bb5f724 100644 --- a/src/main/js/app.js +++ b/src/main/js/app.js @@ -12,18 +12,16 @@ class App extends React.Component { constructor(props) { super(props); - this.state = {users: [], attributes: [], pageSize: 20, links: {}}; + this.state = {users: [], attributes: [], pageSize: 20, nameSearch: 'bruno',links: {}}; this.updatePageSize = this.updatePageSize.bind(this); - //this.onCreate = this.onCreate.bind(this); - //this.onDelete = this.onDelete.bind(this); - this.onNavigate = this.onNavigate.bind(this); + this.onNavigate = this.onNavigate.bind', params: {size: pageSize}}] + ).then(userCollection => {(this); } // tag::follow-2[] - loadFromServer(pageSize) { + loadFromServer(pageSize, nameSearch) { follow(client, root, [ - {rel: 'users', params: {size: pageSize}}] - ).then(userCollection => { + {rel: 'users/search/listUsers?nome='+nameSearch return client({ method: 'GET', path: userCollection.entity._links.profile.href, @@ -37,6 +35,7 @@ class App extends React.Component { users: userCollection.entity._embedded.users, attributes: Object.keys(this.schema.properties), pageSize: pageSize, + nameSearch: nameSearch, links: userCollection.entity._links}); }); } @@ -58,11 +57,19 @@ class App extends React.Component { // tag::update-page-size[] updatePageSize(pageSize) { if (pageSize !== this.state.pageSize) { - this.loadFromServer(pageSize); + this.loadFromServer(pageSize, this.state.nameSearch); } } // end::update-page-size[] + // tag::update-search-name[] + updateNameSearch(nameSearch) { + if (nameSearch !== this.state.nameSearch) { + this.loadFromServer(this.state.pageSize, nameSearch); + } + } + // end::update-search-name[] + // tag::follow-1[] componentDidMount() { this.loadFromServer(this.state.pageSize); @@ -90,11 +97,11 @@ class UserList extends React.Component { this.handleNavPrev = this.handleNavPrev.bind(this); this.handleNavNext = this.handleNavNext.bind(this); this.handleNavLast = this.handleNavLast.bind(this); - this.handleInput = this.handleInput.bind(this); + this.handlePageSize = this.handlePageSize.bind(this); } // tag::handle-page-size-updates[] - handleInput(e) { + handlePageSize(e) { e.preventDefault(); const pageSize = ReactDOM.findDOMNode(this.refs.pageSize).value; if (/^[0-9]+$/.test(pageSize)) { @@ -106,6 +113,19 @@ class UserList extends React.Component { } // end::handle-page-size-updates[] + // tag::handle-name-search-updates[] + handleNameSearch(e) { + e.preventDefault(); + const nameSearch = ReactDOM.findDOMNode(this.refs.nameSearch).value; + if (/^[a-zA-Z ]+$/.test(nameSearch)) { + this.props.updatePageSize(pageSize); + } else { + ReactDOM.findDOMNode(this.refs.pageSize).value = + pageSize.substring(0, pageSize.length - 1); + } + } + // end::handle-name-search-updates[] + // tag::handle-nav[] handleNavFirst(e){ e.preventDefault(); @@ -150,7 +170,12 @@ class UserList extends React.Component { return (
- +

+ +

+

+ +

diff --git a/src/test/java/com/picpay/repositories/UserRepositoryTest.java b/src/test/java/com/picpay/repositories/UserRepositoryTest.java index 4f977b568..374ce2bba 100644 --- a/src/test/java/com/picpay/repositories/UserRepositoryTest.java +++ b/src/test/java/com/picpay/repositories/UserRepositoryTest.java @@ -34,7 +34,7 @@ public void contextLoads() throws Exception { ); MvcResult mvcResult = mockMvc.perform( - MockMvcRequestBuilders.get("/") + MockMvcRequestBuilders.get("/api/users") .accept(MediaType.APPLICATION_JSON) ).andReturn(); From d01c4d315c4fa669c2d6c0a0a09af55e19e5eefb Mon Sep 17 00:00:00 2001 From: "brunocarreira.silva" Date: Thu, 11 Oct 2018 14:48:01 -0300 Subject: [PATCH 16/26] changes --- .../java/com/picpay/ApplicationStartup.java | 19 ++++++++++++++++--- .../com/picpay/UserManagerApplication.java | 10 ---------- src/main/java/com/picpay/model/User.java | 4 ++++ .../picpay/repositories/UserRepository.java | 13 +++++++++++++ src/main/js/app.js | 15 ++++++++++----- src/main/js/follow.js | 2 ++ src/main/resources/application.properties | 2 ++ src/main/resources/import.sql | 11 +++-------- 8 files changed, 50 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/picpay/ApplicationStartup.java b/src/main/java/com/picpay/ApplicationStartup.java index 20da928a1..b3427cea4 100644 --- a/src/main/java/com/picpay/ApplicationStartup.java +++ b/src/main/java/com/picpay/ApplicationStartup.java @@ -1,8 +1,10 @@ package com.picpay; +import com.picpay.repositories.UserRepository; import org.apache.tomcat.util.http.fileupload.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; @@ -10,13 +12,13 @@ import java.io.*; import java.net.URL; import java.nio.file.StandardCopyOption; +import java.util.List; import java.util.zip.GZIPInputStream; /** * @author Bruno Carreira */ // tag::code[] - /* @Component public class ApplicationStartup implements CommandLineRunner { @@ -26,6 +28,15 @@ public class ApplicationStartup implements CommandLineRunner { @Value("${com.picpay.csv.database.filename}") private final String csvDatabaseFilename = null; + @Autowired + private List listRelevancia1; + + @Autowired + private List listRelevancia2; + + @Autowired + private UserRepository repo; + private static final Logger LOG = LoggerFactory.getLogger(ApplicationStartup.class); @@ -33,6 +44,7 @@ public class ApplicationStartup implements CommandLineRunner { public void run(String... strings) throws Exception { System.out.println("Creating File....."); LOG.info("Creating File...."); + /* InputStream zipFileInputStream = new URL(csvDatabaseUrl).openStream(); GZIPInputStream is = new GZIPInputStream(zipFileInputStream); @@ -42,12 +54,13 @@ public void run(String... strings) throws Exception { is, targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - +*/ //IOUtils.closeQuietly(is); + repo.updatePriorityByIds(listRelevancia1, 1); + repo.updatePriorityByIds(listRelevancia2, 2); System.out.println("File is created!"); LOG.info("File is created!"); } } -*/ // end::code[] \ No newline at end of file diff --git a/src/main/java/com/picpay/UserManagerApplication.java b/src/main/java/com/picpay/UserManagerApplication.java index a92d65417..2311916fa 100644 --- a/src/main/java/com/picpay/UserManagerApplication.java +++ b/src/main/java/com/picpay/UserManagerApplication.java @@ -29,16 +29,6 @@ public class UserManagerApplication { public static void main(String[] args){ SpringApplication.run(UserManagerApplication.class, args); -/* - List lr1 = Files.lines(Paths.get(relevancia1_txt)).collect(Collectors.toList()); - List lr2 = Files.lines(Paths.get(relevancia2_txt)).collect(Collectors.toList()); - String rel1 = lr1.stream().map(id -> "("+id+",1)").collect(Collectors.joining(",")); - String rel2 = lr2.stream().map(id -> "("+id+",2)").collect(Collectors.joining(",")); - CUSTOM_QUERY = "SELECT * FROM tb_user u " + - " LEFT OUTER JOIN (VALUES "+rel1+") as r1(id, ordering) ON u.id = r1.id" + - " LEFT OUTER JOIN (VALUES "+rel2+") as r2(id, ordering) ON u.id = r2.id" + - " where (u.name like %:name%) or (u.username like %:name%) order by u.id \n-- #pageable\n"; - */ } @Bean diff --git a/src/main/java/com/picpay/model/User.java b/src/main/java/com/picpay/model/User.java index 67b0c949d..a30bcedc3 100644 --- a/src/main/java/com/picpay/model/User.java +++ b/src/main/java/com/picpay/model/User.java @@ -1,6 +1,8 @@ package com.picpay.model; import lombok.Data; +import org.springframework.data.rest.core.annotation.RestResource; + import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @@ -17,6 +19,8 @@ public class User { private String Id; private String name; private String username; + @RestResource(exported = false) + private Integer priority; private User() {} diff --git a/src/main/java/com/picpay/repositories/UserRepository.java b/src/main/java/com/picpay/repositories/UserRepository.java index 3bd92cfcf..96491989b 100644 --- a/src/main/java/com/picpay/repositories/UserRepository.java +++ b/src/main/java/com/picpay/repositories/UserRepository.java @@ -4,12 +4,25 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.data.repository.query.Param; + +import javax.transaction.Transactional; +import java.util.List; /** * @author Bruno Carreira */ +@Transactional public interface UserRepository extends PagingAndSortingRepository { Page findAll(Specification spec, Pageable pageable); + + Page findByNameContainingOrUsernameContaining(@Param("name") String nameText, @Param("username") String usernameText, Pageable pageable); + + @Modifying + @Query(value = "update User u set u.priority=:priority where u.id in (:ids)") + int updatePriorityByIds(@Param("ids") List id, @Param("priority") int priority); } \ No newline at end of file diff --git a/src/main/js/app.js b/src/main/js/app.js index 39bb5f724..13a1f50ea 100644 --- a/src/main/js/app.js +++ b/src/main/js/app.js @@ -7,21 +7,24 @@ const client = require('./client'); const follow = require('./follow'); // function to hop multiple links by "rel" const root = '/api'; +//const loadURL = 'users/search/findByNameContainingOrUsernameContaining'; +const loadURL = 'users'; class App extends React.Component { constructor(props) { super(props); - this.state = {users: [], attributes: [], pageSize: 20, nameSearch: 'bruno',links: {}}; + this.state = {users: [], attributes: [], pageSize: 20, nameSearch: 'bruno', links: {}}; this.updatePageSize = this.updatePageSize.bind(this); - this.onNavigate = this.onNavigate.bind', params: {size: pageSize}}] - ).then(userCollection => {(this); + this.onNavigate = this.onNavigate.bind(this); } // tag::follow-2[] loadFromServer(pageSize, nameSearch) { + console.log("loadFromServer pageSize "+pageSize+" nameSearch "+nameSearch); follow(client, root, [ - {rel: 'users/search/listUsers?nome='+nameSearch + {rel: loadURL, params: {size: pageSize/*, name: nameSearch, username: nameSearch*/}}] + ).then(userCollection => { return client({ method: 'GET', path: userCollection.entity._links.profile.href, @@ -64,6 +67,7 @@ class App extends React.Component { // tag::update-search-name[] updateNameSearch(nameSearch) { + console.log("updateNameSearch"+nameSearch); if (nameSearch !== this.state.nameSearch) { this.loadFromServer(this.state.pageSize, nameSearch); } @@ -72,7 +76,8 @@ class App extends React.Component { // tag::follow-1[] componentDidMount() { - this.loadFromServer(this.state.pageSize); + console.log("componentDidMount pageSize "+this.state.pageSize+" nameSearch "+this.state.nameSearch); + this.loadFromServer(this.state.pageSize, this.state.nameSearch); } // end::follow-1[] diff --git a/src/main/js/follow.js b/src/main/js/follow.js index 59efe7049..e722a0432 100644 --- a/src/main/js/follow.js +++ b/src/main/js/follow.js @@ -10,7 +10,9 @@ module.exports = function follow(api, rootPath, relArray) { }, root); function traverseNext (root, rel, arrayItem) { + console.log("traverseNext root "+JSON.stringify(root)+" rel "+rel+" arrayItem "+JSON.stringify(arrayItem)); return root.then(function (response) { + console.log("response "+JSON.stringify(response)); if (hasEmbeddedRel(response.entity, rel)) { return response.entity._embedded[rel]; } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index da50aa08e..42e95f6ed 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -12,6 +12,8 @@ com.picpay.relevancia2=lista_relevancia_2.txt # "root" as username and password. #spring.datasource.url = jdbc:mysql://localhost:3306/test spring.datasource.url=jdbc:h2:file:~/test;LOG=0;CACHE_SIZE=65536;LOCK_MODE=0;UNDO_LOG=0 +spring.h2.console.enabled=true +spring.h2.console.path=/h2-console #spring.datasource.username = root #spring.datasource.password = password diff --git a/src/main/resources/import.sql b/src/main/resources/import.sql index 443712ccf..811aee79b 100644 --- a/src/main/resources/import.sql +++ b/src/main/resources/import.sql @@ -1,10 +1,5 @@ ---INSERT INTO tb_user SELECT * FROM CSVREAD('classpath:/users.csv', 'id,name,username', null) WHERE name like '%Rafael%'; DROP TABLE IF EXISTS tb_user; -CREATE TABLE tb_user(id varchar(255), name varchar(255), username varchar(255)) AS SELECT * FROM CSVREAD('classpath:/users.csv', 'id,name,username', null) LIMIT 1000; +CREATE TABLE tb_user(id varchar(255), name varchar(255), username varchar(255)) AS SELECT * FROM CSVREAD('classpath:/users.csv', 'id,name,username', null) LIMIT 10000; CREATE INDEX idxname ON tb_user(name, username); - --- SELECT * FROM foo --- JOIN (VALUES (67,1), (23,2), (1362,3), (24,4)) as x(id, ordering) ON foo.id = x.id --- ORDER BY x.ordering - ---LOAD DATA LOCAL INFILE 'C:\\ProgramData\\MySQL\\MySQL Server 8.0\\Uploads\\users.csv' INTO TABLE tb_user; \ No newline at end of file +ALTER TABLE tb_user ADD priority int; +CREATE INDEX idxpriority ON tb_user(priority); From d083f2e2ffe16d00e3dd939dd5e9314c99593b05 Mon Sep 17 00:00:00 2001 From: "brunocarreira.silva" Date: Mon, 15 Oct 2018 13:04:51 -0300 Subject: [PATCH 17/26] changes --- .../controller/UserSearchController.java | 2 ++ .../picpay/repositories/UserRepository.java | 4 ++- src/main/js/app.js | 27 +++++++++++-------- src/main/js/follow.js | 8 ++++-- src/main/resources/import.sql | 2 +- 5 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/picpay/controller/UserSearchController.java b/src/main/java/com/picpay/controller/UserSearchController.java index 7a8c745af..e2e07c65b 100644 --- a/src/main/java/com/picpay/controller/UserSearchController.java +++ b/src/main/java/com/picpay/controller/UserSearchController.java @@ -29,6 +29,7 @@ * @author Bruno Carreira */ // tag::code[] + /* @RepositoryRestController public class UserSearchController { @@ -58,4 +59,5 @@ public class UserSearchController { } +*/ // end::code[] \ No newline at end of file diff --git a/src/main/java/com/picpay/repositories/UserRepository.java b/src/main/java/com/picpay/repositories/UserRepository.java index 96491989b..c5fb02a22 100644 --- a/src/main/java/com/picpay/repositories/UserRepository.java +++ b/src/main/java/com/picpay/repositories/UserRepository.java @@ -8,6 +8,7 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.query.Param; +import org.springframework.data.rest.core.annotation.RestResource; import javax.transaction.Transactional; import java.util.List; @@ -18,8 +19,9 @@ @Transactional public interface UserRepository extends PagingAndSortingRepository { - Page findAll(Specification spec, Pageable pageable); +// Page findAll(Specification spec, Pageable pageable); + @RestResource(path = "usersbyname", rel = "usersbyname") Page findByNameContainingOrUsernameContaining(@Param("name") String nameText, @Param("username") String usernameText, Pageable pageable); @Modifying diff --git a/src/main/js/app.js b/src/main/js/app.js index 13a1f50ea..4efc2864a 100644 --- a/src/main/js/app.js +++ b/src/main/js/app.js @@ -6,9 +6,9 @@ const client = require('./client'); const follow = require('./follow'); // function to hop multiple links by "rel" -const root = '/api'; -//const loadURL = 'users/search/findByNameContainingOrUsernameContaining'; -const loadURL = 'users'; +const profileURL = 'http://localhost:8086/api/profile/users'; +const root = '/api/users/search'; +const loadURL = 'usersbyname'; class App extends React.Component { @@ -16,6 +16,7 @@ class App extends React.Component { super(props); this.state = {users: [], attributes: [], pageSize: 20, nameSearch: 'bruno', links: {}}; this.updatePageSize = this.updatePageSize.bind(this); + this.updateNameSearch = this.updateNameSearch.bind(this); this.onNavigate = this.onNavigate.bind(this); } @@ -23,11 +24,11 @@ class App extends React.Component { loadFromServer(pageSize, nameSearch) { console.log("loadFromServer pageSize "+pageSize+" nameSearch "+nameSearch); follow(client, root, [ - {rel: loadURL, params: {size: pageSize/*, name: nameSearch, username: nameSearch*/}}] + {rel: loadURL, params: {size: pageSize, name: nameSearch, username: nameSearch}}] ).then(userCollection => { return client({ method: 'GET', - path: userCollection.entity._links.profile.href, + path: profileURL, headers: {'Accept': 'application/schema+json'} }).then(schema => { this.schema = schema.entity; @@ -51,6 +52,7 @@ class App extends React.Component { users: userCollection.entity._embedded.users, attributes: this.state.attributes, pageSize: this.state.pageSize, + nameSearch: this.state.nameSearch, links: userCollection.entity._links }); }); @@ -87,8 +89,10 @@ class App extends React.Component { + updatePageSize={this.updatePageSize} + updateNameSearch={this.updateNameSearch}/> ) } @@ -103,6 +107,7 @@ class UserList extends React.Component { this.handleNavNext = this.handleNavNext.bind(this); this.handleNavLast = this.handleNavLast.bind(this); this.handlePageSize = this.handlePageSize.bind(this); + this.handleNameSearch = this.handleNameSearch.bind(this); } // tag::handle-page-size-updates[] @@ -123,10 +128,10 @@ class UserList extends React.Component { e.preventDefault(); const nameSearch = ReactDOM.findDOMNode(this.refs.nameSearch).value; if (/^[a-zA-Z ]+$/.test(nameSearch)) { - this.props.updatePageSize(pageSize); + this.props.updateNameSearch(nameSearch); } else { - ReactDOM.findDOMNode(this.refs.pageSize).value = - pageSize.substring(0, pageSize.length - 1); + ReactDOM.findDOMNode(this.refs.nameSearch).value = + nameSearch.substring(0, nameSearch.length - 1); } } // end::handle-name-search-updates[] @@ -176,10 +181,10 @@ class UserList extends React.Component { return (

- + Nome:

- + Tamanho página:

diff --git a/src/main/js/follow.js b/src/main/js/follow.js index e722a0432..fbadb8e2f 100644 --- a/src/main/js/follow.js +++ b/src/main/js/follow.js @@ -10,10 +10,11 @@ module.exports = function follow(api, rootPath, relArray) { }, root); function traverseNext (root, rel, arrayItem) { - console.log("traverseNext root "+JSON.stringify(root)+" rel "+rel+" arrayItem "+JSON.stringify(arrayItem)); + //console.log("traverseNext root "+JSON.stringify(root)+" rel "+rel+" arrayItem "+JSON.stringify(arrayItem)); return root.then(function (response) { - console.log("response "+JSON.stringify(response)); + //console.log("response "+JSON.stringify(response)); if (hasEmbeddedRel(response.entity, rel)) { + //console.log("hasEmbeddedRel response.entity "+JSON.stringify(response.entity)); return response.entity._embedded[rel]; } @@ -22,11 +23,14 @@ module.exports = function follow(api, rootPath, relArray) { } if (typeof arrayItem === 'string') { + //console.log("arrayItem = string -> response.entity "+JSON.stringify(response.entity)); return api({ method: 'GET', path: response.entity._links[rel].href }); } else { + //console.log("arrayItem != string -> response.entity "+JSON.stringify(response.entity)); + //console.log("arrayItem != string -> arrayItem.params "+JSON.stringify(arrayItem.params)); return api({ method: 'GET', path: response.entity._links[rel].href, diff --git a/src/main/resources/import.sql b/src/main/resources/import.sql index 811aee79b..7dbbc4769 100644 --- a/src/main/resources/import.sql +++ b/src/main/resources/import.sql @@ -1,5 +1,5 @@ DROP TABLE IF EXISTS tb_user; CREATE TABLE tb_user(id varchar(255), name varchar(255), username varchar(255)) AS SELECT * FROM CSVREAD('classpath:/users.csv', 'id,name,username', null) LIMIT 10000; CREATE INDEX idxname ON tb_user(name, username); -ALTER TABLE tb_user ADD priority int; +ALTER TABLE tb_user ADD priority int DEFAULT 10; CREATE INDEX idxpriority ON tb_user(priority); From 5d44e4b7e836863ef25d09cca3ffcafb7b55d6ad Mon Sep 17 00:00:00 2001 From: Bruno Carreira Date: Mon, 15 Oct 2018 22:16:34 -0300 Subject: [PATCH 18/26] changes --- src/main/resources/import.sql | 2 +- .../picpay/repositories/UserRepositoryIT.java | 2 +- .../repositories/UserRepositoryTest.java | 40 +++--- .../resources/application-test.properties | 2 +- src/test/resources/import.sql | 2 +- src/test/resources/users.csv | 117 ++++++++++++++++++ 6 files changed, 143 insertions(+), 22 deletions(-) create mode 100644 src/test/resources/users.csv diff --git a/src/main/resources/import.sql b/src/main/resources/import.sql index 7dbbc4769..a2bd4ded6 100644 --- a/src/main/resources/import.sql +++ b/src/main/resources/import.sql @@ -1,5 +1,5 @@ DROP TABLE IF EXISTS tb_user; -CREATE TABLE tb_user(id varchar(255), name varchar(255), username varchar(255)) AS SELECT * FROM CSVREAD('classpath:/users.csv', 'id,name,username', null) LIMIT 10000; +CREATE TABLE tb_user(id varchar(255), name varchar(255), username varchar(255)) AS SELECT * FROM CSVREAD('classpath:/users.csv', 'id,name,username', null) ; CREATE INDEX idxname ON tb_user(name, username); ALTER TABLE tb_user ADD priority int DEFAULT 10; CREATE INDEX idxpriority ON tb_user(priority); diff --git a/src/test/java/com/picpay/repositories/UserRepositoryIT.java b/src/test/java/com/picpay/repositories/UserRepositoryIT.java index 36727ab67..667de6b57 100644 --- a/src/test/java/com/picpay/repositories/UserRepositoryIT.java +++ b/src/test/java/com/picpay/repositories/UserRepositoryIT.java @@ -29,7 +29,7 @@ public class UserRepositoryIT { public void contextLoads() throws Exception { MvcResult mvcResult = mockMvc.perform( - MockMvcRequestBuilders.get("/") + MockMvcRequestBuilders.get("/api/users") .accept(MediaType.APPLICATION_JSON) ).andReturn(); diff --git a/src/test/java/com/picpay/repositories/UserRepositoryTest.java b/src/test/java/com/picpay/repositories/UserRepositoryTest.java index 374ce2bba..3d64468f1 100644 --- a/src/test/java/com/picpay/repositories/UserRepositoryTest.java +++ b/src/test/java/com/picpay/repositories/UserRepositoryTest.java @@ -1,47 +1,51 @@ package com.picpay.repositories; +import com.picpay.model.User; +import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.data.domain.Page; import org.springframework.http.MediaType; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import java.util.Arrays; import java.util.Collections; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @RunWith(SpringRunner.class) -@WebMvcTest +@DataJpaTest public class UserRepositoryTest { @Autowired - private MockMvc mockMvc; - - @MockBean private UserRepository userRepository; - @Test - public void contextLoads() throws Exception { - - when(userRepository.findAll()).thenReturn( - Collections.emptyList() - ); - - MvcResult mvcResult = mockMvc.perform( - MockMvcRequestBuilders.get("/api/users") - .accept(MediaType.APPLICATION_JSON) - ).andReturn(); - - System.out.println(mvcResult.getResponse()); + @Before + public void setUp(){ + userRepository.save(new User("id", "name", "username")); + userRepository.save(new User("id2", "name2", "username2")); + userRepository.save(new User("id3", "trash", "trash")); + } - verify(userRepository).findAll(); + @Test + public void shouldReturnUserWithName() throws Exception { + Page page = userRepository.findByNameContainingOrUsernameContaining("name", "name", null); + Assert.assertTrue(page.getTotalElements() == 2); + } + @Test + public void shouldUpdatePriority() throws Exception { + int updated = userRepository.updatePriorityByIds(Arrays.asList("id", "id3"), 4); + Assert.assertTrue(updated == 2); } } \ No newline at end of file diff --git a/src/test/resources/application-test.properties b/src/test/resources/application-test.properties index 342316f89..1309731f4 100644 --- a/src/test/resources/application-test.properties +++ b/src/test/resources/application-test.properties @@ -1,2 +1,2 @@ -spring.datasource.url=jdbc:h2:mem:test +spring.datasource.url=jdbc:h2:mem:test;DB_CLOSE_ON_EXIT=FALSE spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect \ No newline at end of file diff --git a/src/test/resources/import.sql b/src/test/resources/import.sql index 9827bcee2..0197aaa1d 100644 --- a/src/test/resources/import.sql +++ b/src/test/resources/import.sql @@ -1 +1 @@ -INSERT INTO tb_user SELECT * FROM CSVREAD('classpath:/users2.csv'); \ No newline at end of file +INSERT INTO tb_user SELECT * FROM CSVREAD('classpath:/users.csv'); \ No newline at end of file diff --git a/src/test/resources/users.csv b/src/test/resources/users.csv new file mode 100644 index 000000000..1ac0a8380 --- /dev/null +++ b/src/test/resources/users.csv @@ -0,0 +1,117 @@ +6e172695-c76c-4364-8dd9-44e6d2d3aed9,Heitor Rovaron,heitor.rovaron +4e8660b0-7350-4211-9b9b-9ba50792ccd9,Melony Terci,melony.terci +7e3d4092-6664-4162-9866-c4256507a35e,Tatiana Arrieiro Filgueira,tatianaarrieirofilgueira +d41d1b73-e28a-4464-a640-abfe1d913cfd,Nadja Elias,nadjaelias +657eb911-3fd1-4317-9430-f5f53199754c,Rafael Furtado,rafael.furtado +c5dcda1f-6d9c-4fe4-824b-ee9a0b138a9c,Luzanira Sardenberg,luzanira.sardenberg +6dec2c10-1522-4cc7-8e45-89d78a6274c2,Donizete Kohler,donizete.kohler +61423001-c484-4fbf-9ee7-9475fb93cf3c,Alinice Araujp,alinicearaujp +c720558d-652d-48d3-b952-40b16124b989,Alax Kaiser Raquel,alax.kaiser.raquel +bea7457f-3d0a-48f8-9ee9-c3ff79bf756b,Candisse Mattis,candisse.mattis +fd7ec052-7e2a-4425-a109-a4a37f105512,Ivanice Callado,ivanicecallado +18c369fe-2b6c-4638-9693-425b13b22948,Vixpark Valariano Federici,vixpark.valariano.federici +850778f4-0bc9-45d0-a732-d023a8f25196, Falfan Brant,falfanbrant +e7e46a01-9618-4f48-978c-9a712949389d,Gustav Angione,gustav.angione +64b7f8c1-6264-4edf-b47a-90f8692056e0,Emannuelly Reginaldo Fofonka,emannuelly.reginaldo.fofonka +cfe9ca52-4b8b-4a15-86f1-4b0adb0f9227,Flaviane Salgado Dudar,flaviane.salgado.dudar +93a30bf5-7c91-45a2-8624-80c79b35b422,Francisca Brunelli Mafetone,francisca.brunelli.mafetone +d2173551-7d7b-47d5-8425-133cdcb69724,Leonaia Farias,leonaiafarias +81bb7a02-c574-4114-85f9-368514aaba29,Rejane fernandes Marinonio,rejane.fernandes.marinonio +f687f04d-5f24-4327-bd74-b07c5660f364,Marcia Louredo,marcialouredo +48da4ef1-9cdf-4a18-aa93-92cdef0d6482,Joeliton RODRIGUES,joelitonrodrigues +a8461f62-d18f-4190-bf97-1684a13b5531,Everaldo Birkman L,everaldo.birkman.l +02b6ce38-b23d-446a-b78b-823f360a4f35,Sarah Auxiliadora,sarah.auxiliadora +708943ab-7987-4632-ae23-1248922b87d6,Jusandra Pessini,jusandrapessini +15d3f155-6a02-4849-9af7-d2cc4148f5a2,Alysson Missagia Mazoco,alyssonmissagiamazoco +b3259f66-1309-42b0-b27e-abb916da67c0,Valdinei Juvencio,valdinei.juvencio +fd3d9ebc-ed89-4a5c-ad0d-c34ecbcae2ac,Joicy Quidicomo,joicyquidicomo +7bd3cf31-e9c5-4b28-b4d2-161b633a99b4,laize Nobrega,laizenobrega +efa7c6a5-7ed7-438a-875b-1fc4184b6bf0,JOSE Cynara Katyuce,jose.cynara.katyuce +fe822c21-d963-4886-ab29-612738cbc47e,Edmarine Castegnara Dattein,edmarine.castegnara.dattein +902a5975-a4a4-4ba8-9a0e-ba3b2812a57d,Franciellen Collopy Marcelina,franciellencollopymarcelina +e04042a2-6ee5-432e-85be-142197dc59c7,Domitila Xx Vavassori,domitila.xx.vavassori +104cf1c0-70d8-4a4e-ac01-29440b10d5ef,Alessandra Ely Isaac,alessandra.ely.isaac +4a873af2-fe3c-4b81-abc3-91ec7299f6b2,Nicolle Ricardo,nicollericardo +529655d9-38c4-4f0c-88d7-62eb8a7adf76,Jacob Swartele,jacobswartele +709b6d12-a526-42d9-9980-25ff71d7c0d9,Morris Franco,morris.franco +5261adc3-8249-4ce0-9ce0-230e65164a8d,Eloisa Lund,eloisa.lund +36fbfe3b-91ba-4bc9-8918-ed94a10aee3f,Cleiziene Bertagnoni,cleiziene.bertagnoni +0cad4728-8f1e-48d4-8e3e-63594ca33b17,Joil Valle,joil.valle +f4fb9402-a929-4d97-b2ed-d424e81bbf51,Kamila Riper,kamilariper +7a917d5a-cb31-4bd5-b6a5-10c90de4b6f2,Vitor Steinmann,vitor.steinmann +b1d011ac-47c7-453c-9558-22027a759f91,Valdirlene William,valdirlenewilliam +cd322a11-d1ac-431a-99a8-25f126a2d389,Aleandra Cassia Abdon,aleandra.cassia.abdon +30abd294-6b09-428b-b761-dc28f6961f43,Sandro Valerii Restum,sandro.valerii.restum +37c5d202-641c-49a6-848b-4fc64bf790ef,Alan Gasco Balbo,alangascobalbo +14f015ba-4cdf-439e-8948-518c5cb5ddce,Jany Carpinteiro,jany.carpinteiro +5e0ccb3e-7f28-47d0-9cf7-9426f364805e,Wesley Souzs,wesley.souzs +6f0bf406-6eb6-4c5c-ab8c-50a2398da5e4,Frank Sabrina Pauperio,frank.sabrina.pauperio +0bc1a237-0995-4bae-9961-ad7c992d1bba,Benedito Calheiros Dionei,benedito.calheiros.dionei +be581d60-9825-441a-92fb-bb2eda2229e3,Vixpark Lessa,vixpark.lessa +6df83561-1386-45e8-b0b5-9e4bfc15d1d7,Stefani Prara Brunhara,stefani.prara.brunhara +56f5e56d-b443-4538-9b47-484a1d7643aa,Elizandra Luziane Sossella,elizandra.luziane.sossella +a64be1f1-f87a-4228-a19a-babb9c394d97,Marilda Regiani,marildaregiani +2858715a-cf1e-473f-94cb-e9a4ac682bb0,Rosemary Goyanna,rosemary.goyanna +bdfc56a9-5ac2-4070-a291-e3f10a785d8d,Keliani Ketten Makuch,kelianikettenmakuch +363a6422-dcc4-4896-ad75-03af2cf8b9da,Zeiny Brandes,zeiny.brandes +d27c46cb-8e5e-4401-8aac-1947c675b297,Greziele Amanti Preira,greziele.amanti.preira +1786166c-3a2f-45bb-8639-d5738d11ff06,Waldeia Melone,waldeia.melone +1398be63-9b24-4d45-8809-bc3ab8b5a75f,Vivyane Cypriano,vivyanecypriano +e17cae43-8f14-4403-8432-d85cc8939727,Elizabete Pompeu,elizabete.pompeu +ab0a5e06-202a-43b2-8705-31022e31c04b,Jose Pivetta P,jose.pivetta.p +32caa8a3-6085-48d5-9eb5-39953de07b82,Christine Eustaquio,christine.eustaquio +092b7c45-cafd-4242-96e1-373c453961d8,Daliana Weigert,daliana.weigert +00afd0b4-63fe-4644-ba88-acdc16502630,Leudileia Valerii,leudileia.valerii +09f51559-17fe-4228-9a45-2c0e2eb6cbbc,Cariza H,cariza.h +18a53b29-997a-470b-8562-10620474b5ab,Kendy FLAVIO Roizen,kendyflavioroizen +8355725e-3953-441f-921f-960ad9e8e93d,Ariana Wilhelm Carvalhp,arianawilhelmcarvalhp +259dfd7e-77b0-4f63-b288-9cad31ba3112,Yane Goncalo,yane.goncalo +df098d5e-23cf-4374-b31c-5034fe7dc1ed,Jhonattan Jacinto,jhonattan.jacinto +595b663a-b091-40f8-8a76-b3ca57534bcd,Quelen Acelino von,quelen.acelino.von +bc541175-304f-49d6-a98f-07b387ee5dbb,Elry Maiolini Rejiane,elry.maiolini.rejiane +3d6f947d-b311-4e61-bf9f-1172dff257dc,Thereza Lessi Bressani,thereza.lessi.bressani +54fb2ece-8c81-4cbc-b8b3-b5cae6b24d33,Lucianeda amatuzzi,lucianeda.amatuzzi +187aa3dc-dc54-4b48-891f-5c199a04c531,Luanda Verner,luanda.verner +275a87a2-6185-4ad7-82d8-0f12864fec43,Nailton Airton,nailton.airton +81241945-b0bd-4b6a-ace5-67336015aef7,Suzelen Martimiano,suzelen.martimiano +bce450dd-1e19-4a00-a95c-2814ece1de59,Luca Emanuele,lucaemanuele +b62b6525-f480-4d38-b100-64b0cfb843f6,Jaime Rodrigues,jaimerodrigues +c3bec5ba-bb5a-4f8c-bc31-8cb41359e174,Ademir Girelli,ademir.girelli +c91ee16c-7497-4634-aa17-65106681d396,Tauane Lucaa,tauane.lucaa +7ad381e7-c54d-47a5-8e83-d010cc979a27,Augustho Leopici barreto,augustho.leopici.barreto +51269a99-684a-4976-b518-da346219f28c,Samir Cynthia Paim,samir.cynthia.paim +83477481-6b3d-4433-a75f-17bc631f3812,Ivanires Drudi,ivaniresdrudi +89414639-ec14-415f-ae7b-9850e04d81c2,Amauri Lother,amauri.lother +aedb0fec-3ce2-4017-92f4-5b8a0a244805,Cefas Silva,cefas.silva +792db824-2d78-4091-a0bf-03863f0eb8d6,Yara Zago,yara.zago +927197cc-28f5-4807-a649-f9cd9d172760,Enaide Williany,enaidewilliany +e24ba427-5302-456a-aefd-7cc907ff8604,MARIO Toscano,mario.toscano +d59cc9d9-3a45-4c5a-944e-25cd681edcda,Suellen Scaletti Reginaldo,suellenscalettireginaldo +f5b79043-83cd-4ba1-9427-848fa61c7146,Roger Sabotto,roger.sabotto +245cf7fe-9744-477c-a58a-90038ce5d531,Adriene PAULO,adriene.paulo +1f63e134-50a1-4c7c-86f7-3c892894e42a,Gabrielle Ribeiri Pianna,gabrielle.ribeiri.pianna +223fe7f8-fa44-4360-8c91-837e04346ba0,Juciara Cestari,juciara.cestari +dfe8a80e-19b6-4530-a635-b69b2066e193,Naiani Em,naiani.em +f39dd988-31fe-4c54-9fd4-497cc7d076d9,Jerry Erlaches,jerryerlaches +aa842796-9b06-4fce-8256-e16af7aa3311,Karyna Agostinho,karyna.agostinho +68e9215b-9d8d-4b2d-b0dd-f4a6d8fe15dc,Maiky Iara Buarque,maiky.iara.buarque +27bf3036-ccac-4d49-9eb8-26b16adadc34,Lucide O,lucide.o +56987a61-88ef-4ba7-a97c-f29c8e7f69ef,Caique Brigatto,caique.brigatto +7443be6a-16fc-4c36-ba63-be34290e6f0a,Jannayna Lozer Deleon,jannayna.lozer.deleon +543144ac-ae86-48c5-ab65-6591a45db040,Francielly Paranhos,francielly.paranhos +470dfa6a-a2a9-4d73-841b-1e96b4d524eb,Endrezy Scalfoni,endrezyscalfoni +58923126-03fa-4772-bac9-87f5d317e598,Licia Roriz,liciaroriz +d508278a-12be-42aa-b3ac-80c30720120d,Alice Loureiro,aliceloureiro +1785c1b5-e9f5-4a65-8742-066f55e1d8e1,Wilton Negrelli,wiltonnegrelli +780c732f-f36f-480b-9548-7a28ccdc2657,Evelly Varella Vianna,evelly.varella.vianna +b50051b3-4f60-4ba3-b649-63a6b99c104e,Cinara Bomtempo Maira,cinara.bomtempo.maira +e5cc712f-a688-4389-974b-757aa7438af5,Tamiris Ivan,tamiris.ivan +927ed97a-64d2-4d38-b065-81d244685915,Eryka Marilac,eryka.marilac +ae152332-1b3a-4efc-968a-32539b7ae98e,Wekesley Vanete Schiavon,wekesleyvaneteschiavon +3d8f916b-7e8d-4e0c-b421-8ed8b1119283,Ludiely Zaineli Morale,ludiely.zaineli.morale +aef241cf-0678-4106-ad3f-00f956cac1c0,Talicia Loblein,talicialoblein +e3d2ba76-8241-4d60-8f2e-6e30381886b5,Isabele vil,isabele.vil +07261474-de87-45f4-9a5e-6849e672aaea,Jacy Evelyn,jacy.evelyn +6e25ab33-1500-42b7-88e4-15b02853b67f,Caliane Redig,calianeredig +d2b5b90f-c857-4c85-afbd-e5544b886c51,Gilmar Feola,gilmar.feola +01326111-4c38-479c-a057-ab92c955fd76,Wellyngton Ressurreicao,wellyngton.ressurreicao From 0b25d42efeaef1ee098e8985694f6d3092c59d45 Mon Sep 17 00:00:00 2001 From: Bruno Carreira Date: Mon, 15 Oct 2018 22:45:31 -0300 Subject: [PATCH 19/26] changes --- src/main/js/app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/js/app.js b/src/main/js/app.js index 4efc2864a..f18e64025 100644 --- a/src/main/js/app.js +++ b/src/main/js/app.js @@ -14,7 +14,7 @@ class App extends React.Component { constructor(props) { super(props); - this.state = {users: [], attributes: [], pageSize: 20, nameSearch: 'bruno', links: {}}; + this.state = {users: [], attributes: [], pageSize: 15, nameSearch: 'bruno', links: {}}; this.updatePageSize = this.updatePageSize.bind(this); this.updateNameSearch = this.updateNameSearch.bind(this); this.onNavigate = this.onNavigate.bind(this); @@ -24,7 +24,7 @@ class App extends React.Component { loadFromServer(pageSize, nameSearch) { console.log("loadFromServer pageSize "+pageSize+" nameSearch "+nameSearch); follow(client, root, [ - {rel: loadURL, params: {size: pageSize, name: nameSearch, username: nameSearch}}] + {rel: loadURL, params: {size: pageSize, name: nameSearch, username: nameSearch, sort: "priority"}}] ).then(userCollection => { return client({ method: 'GET', From 43dc671d20f598abe2bd815f02dde2d503acfd03 Mon Sep 17 00:00:00 2001 From: "brunocarreira.silva" Date: Tue, 16 Oct 2018 15:27:46 -0300 Subject: [PATCH 20/26] changes --- .../picpay/repositories/UserRepository.java | 2 +- .../repositories/UserRepositoryTest.java | 31 +++++++++++-------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/picpay/repositories/UserRepository.java b/src/main/java/com/picpay/repositories/UserRepository.java index c5fb02a22..8ba61af31 100644 --- a/src/main/java/com/picpay/repositories/UserRepository.java +++ b/src/main/java/com/picpay/repositories/UserRepository.java @@ -22,7 +22,7 @@ public interface UserRepository extends PagingAndSortingRepository // Page findAll(Specification spec, Pageable pageable); @RestResource(path = "usersbyname", rel = "usersbyname") - Page findByNameContainingOrUsernameContaining(@Param("name") String nameText, @Param("username") String usernameText, Pageable pageable); + Page findByNameContainingOrUsernameContainingOrderByPriority(@Param("name") String nameText, @Param("username") String usernameText, Pageable pageable); @Modifying @Query(value = "update User u set u.priority=:priority where u.id in (:ids)") diff --git a/src/test/java/com/picpay/repositories/UserRepositoryTest.java b/src/test/java/com/picpay/repositories/UserRepositoryTest.java index 3d64468f1..fdfc79bcc 100644 --- a/src/test/java/com/picpay/repositories/UserRepositoryTest.java +++ b/src/test/java/com/picpay/repositories/UserRepositoryTest.java @@ -7,20 +7,11 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.data.domain.Page; -import org.springframework.http.MediaType; import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.MvcResult; -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import java.util.Arrays; -import java.util.Collections; - -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import java.util.List; @RunWith(SpringRunner.class) @DataJpaTest @@ -37,15 +28,29 @@ public void setUp(){ } @Test - public void shouldReturnUserWithName() throws Exception { - Page page = userRepository.findByNameContainingOrUsernameContaining("name", "name", null); + public void shouldReturnUserWithName() { + Page page = userRepository.findByNameContainingOrUsernameContainingOrderByPriority("name", "name", null); Assert.assertTrue(page.getTotalElements() == 2); } @Test - public void shouldUpdatePriority() throws Exception { + public void shouldUpdatePriority() { int updated = userRepository.updatePriorityByIds(Arrays.asList("id", "id3"), 4); Assert.assertTrue(updated == 2); + int updated2 = userRepository.updatePriorityByIds(Arrays.asList("id2"), 2); + Assert.assertTrue(updated2 == 1); + } + + @Test + public void shouldReturnUserWithNameOrdered() { + userRepository.updatePriorityByIds(Arrays.asList("id", "id3"), 10); + userRepository.updatePriorityByIds(Arrays.asList("id2"), 8); + + Page page = userRepository.findByNameContainingOrUsernameContainingOrderByPriority("a", "a", null); + Assert.assertTrue(page.getTotalElements() == 3); + List list = page.getContent(); + User user = list.get(0); + Assert.assertTrue(user.getId().equals("id2")); } } \ No newline at end of file From 0c0111a1f48aa36c3f9e202f1881c4dcb87c5200 Mon Sep 17 00:00:00 2001 From: Bruno Carreira Date: Tue, 16 Oct 2018 22:35:36 -0300 Subject: [PATCH 21/26] changes --- pom.xml | 4 ++ .../java/com/picpay/WebSecurityConfig.java | 44 +++++++++++++++++++ src/main/resources/application.properties | 9 +++- src/main/resources/import.sql | 2 +- 4 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/picpay/WebSecurityConfig.java diff --git a/pom.xml b/pom.xml index d231443e0..c3fe5ba8e 100644 --- a/pom.xml +++ b/pom.xml @@ -29,6 +29,10 @@ org.springframework.boot spring-boot-starter-thymeleaf + + org.springframework.boot + spring-boot-starter-security + org.springframework.boot spring-boot-starter-data-jpa diff --git a/src/main/java/com/picpay/WebSecurityConfig.java b/src/main/java/com/picpay/WebSecurityConfig.java new file mode 100644 index 000000000..781e77004 --- /dev/null +++ b/src/main/java/com/picpay/WebSecurityConfig.java @@ -0,0 +1,44 @@ +package com.picpay; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +@Configuration +@EnableWebSecurity +public class WebSecurityConfig extends WebSecurityConfigurerAdapter { + +// @Autowired +// private MyBasicAuthenticationEntryPoint authenticationEntryPoint; + + @Autowired + public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication() + .withUser("bruno").password(passwordEncoder().encode("$2a$04$DhQ9bTTaGgoNAryoR9a3W.Z/2VWNHcPQDxJ6MJde1UY5PNWSZ3XoC")) + .authorities("ROLE_USER"); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.authorizeRequests() + .antMatchers("/api/**").authenticated() + //.anyRequest().authenticated() + .and() + .httpBasic(); +// .authenticationEntryPoint(authenticationEntryPoint); + +// http.addFilterAfter(new CustomFilter(), +// BasicAuthenticationFilter.class); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 42e95f6ed..ac3fe7483 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -11,7 +11,13 @@ com.picpay.relevancia2=lista_relevancia_2.txt # connection. In this example we have "test" as database name and # "root" as username and password. #spring.datasource.url = jdbc:mysql://localhost:3306/test -spring.datasource.url=jdbc:h2:file:~/test;LOG=0;CACHE_SIZE=65536;LOCK_MODE=0;UNDO_LOG=0 +spring.datasource.url=jdbc:h2:mem:testdb +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password= + +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect +#spring.datasource.url=jdbc:h2:file:~/test;LOG=0;CACHE_SIZE=65536;LOCK_MODE=0;UNDO_LOG=0 spring.h2.console.enabled=true spring.h2.console.path=/h2-console #spring.datasource.username = root @@ -35,5 +41,6 @@ spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy # The SQL dialect makes Hibernate generate better SQL for the chosen database # spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect +logging.level.org.springframework.security=DEBUG server.port=8086 \ No newline at end of file diff --git a/src/main/resources/import.sql b/src/main/resources/import.sql index a2bd4ded6..12aeaa906 100644 --- a/src/main/resources/import.sql +++ b/src/main/resources/import.sql @@ -1,5 +1,5 @@ DROP TABLE IF EXISTS tb_user; -CREATE TABLE tb_user(id varchar(255), name varchar(255), username varchar(255)) AS SELECT * FROM CSVREAD('classpath:/users.csv', 'id,name,username', null) ; +CREATE TABLE tb_user(id varchar(255), name varchar(255), username varchar(255)) AS SELECT * FROM CSVREAD('classpath:/users.csv', 'id,name,username', null) limit 10000; CREATE INDEX idxname ON tb_user(name, username); ALTER TABLE tb_user ADD priority int DEFAULT 10; CREATE INDEX idxpriority ON tb_user(priority); From f52abe4f0ecefc1991cce6aadf4d0dd27ce60a7e Mon Sep 17 00:00:00 2001 From: "brunocarreira.silva" Date: Wed, 17 Oct 2018 15:42:01 -0300 Subject: [PATCH 22/26] changes --- .../java/com/picpay/WebSecurityConfig.java | 2 +- src/main/js/app.js | 18 ++++++++++-------- src/main/resources/application.properties | 4 ++-- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/picpay/WebSecurityConfig.java b/src/main/java/com/picpay/WebSecurityConfig.java index 781e77004..ce9030a9a 100644 --- a/src/main/java/com/picpay/WebSecurityConfig.java +++ b/src/main/java/com/picpay/WebSecurityConfig.java @@ -20,7 +20,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() - .withUser("bruno").password(passwordEncoder().encode("$2a$04$DhQ9bTTaGgoNAryoR9a3W.Z/2VWNHcPQDxJ6MJde1UY5PNWSZ3XoC")) + .withUser("bruno").password("bruno") .authorities("ROLE_USER"); } diff --git a/src/main/js/app.js b/src/main/js/app.js index f18e64025..bc8c809ba 100644 --- a/src/main/js/app.js +++ b/src/main/js/app.js @@ -125,13 +125,15 @@ class UserList extends React.Component { // tag::handle-name-search-updates[] handleNameSearch(e) { - e.preventDefault(); - const nameSearch = ReactDOM.findDOMNode(this.refs.nameSearch).value; - if (/^[a-zA-Z ]+$/.test(nameSearch)) { - this.props.updateNameSearch(nameSearch); - } else { - ReactDOM.findDOMNode(this.refs.nameSearch).value = - nameSearch.substring(0, nameSearch.length - 1); + if (e.key == 'Enter'){ + e.preventDefault(); + const nameSearch = ReactDOM.findDOMNode(this.refs.nameSearch).value; + if (/^[a-zA-Z ]+$/.test(nameSearch)) { + this.props.updateNameSearch(nameSearch); + } else { + ReactDOM.findDOMNode(this.refs.nameSearch).value = + nameSearch.substring(0, nameSearch.length - 1); + } } } // end::handle-name-search-updates[] @@ -181,7 +183,7 @@ class UserList extends React.Component { return (

- Nome: + Nome:

Tamanho página: diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index ac3fe7483..67e2621f7 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -11,13 +11,13 @@ com.picpay.relevancia2=lista_relevancia_2.txt # connection. In this example we have "test" as database name and # "root" as username and password. #spring.datasource.url = jdbc:mysql://localhost:3306/test -spring.datasource.url=jdbc:h2:mem:testdb +# spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password= spring.jpa.database-platform=org.hibernate.dialect.H2Dialect -#spring.datasource.url=jdbc:h2:file:~/test;LOG=0;CACHE_SIZE=65536;LOCK_MODE=0;UNDO_LOG=0 +spring.datasource.url=jdbc:h2:file:~/test;LOG=0;CACHE_SIZE=65536;LOCK_MODE=0;UNDO_LOG=0 spring.h2.console.enabled=true spring.h2.console.path=/h2-console #spring.datasource.username = root From 4405f09d03380eb32cb6120afb1ae86063700932 Mon Sep 17 00:00:00 2001 From: Bruno Carreira Date: Wed, 17 Oct 2018 23:19:28 -0300 Subject: [PATCH 23/26] changes --- .../java/com/picpay/ApplicationStartup.java | 6 +- src/main/resources/application.properties | 28 +++-- src/main/resources/import.sql | 4 +- src/test/resources/import.sql | 2 +- src/test/resources/users.csv | 117 ------------------ 5 files changed, 22 insertions(+), 135 deletions(-) delete mode 100644 src/test/resources/users.csv diff --git a/src/main/java/com/picpay/ApplicationStartup.java b/src/main/java/com/picpay/ApplicationStartup.java index b3427cea4..22a7f699f 100644 --- a/src/main/java/com/picpay/ApplicationStartup.java +++ b/src/main/java/com/picpay/ApplicationStartup.java @@ -42,8 +42,7 @@ public class ApplicationStartup implements CommandLineRunner { @Override public void run(String... strings) throws Exception { - System.out.println("Creating File....."); - LOG.info("Creating File...."); + LOG.info("Updating priority...."); /* InputStream zipFileInputStream = new URL(csvDatabaseUrl).openStream(); GZIPInputStream is = new GZIPInputStream(zipFileInputStream); @@ -58,8 +57,7 @@ public void run(String... strings) throws Exception { //IOUtils.closeQuietly(is); repo.updatePriorityByIds(listRelevancia1, 1); repo.updatePriorityByIds(listRelevancia2, 2); - System.out.println("File is created!"); - LOG.info("File is created!"); + LOG.info("Priority updated!"); } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 67e2621f7..ed4e9df5a 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -7,22 +7,26 @@ com.picpay.csv.database.filename=users.csv.gz com.picpay.relevancia1=lista_relevancia_1.txt com.picpay.relevancia2=lista_relevancia_2.txt -# DataSource settings: set here your own configurations for the database -# connection. In this example we have "test" as database name and -# "root" as username and password. -#spring.datasource.url = jdbc:mysql://localhost:3306/test +# H2 CONFIG # spring.datasource.url=jdbc:h2:mem:testdb +spring.datasource.url=jdbc:h2:file:~/testdb;LOG=0;CACHE_SIZE=65536;LOCK_MODE=0;UNDO_LOG=0 spring.datasource.driverClassName=org.h2.Driver -spring.datasource.username=sa -spring.datasource.password= - +# spring.datasource.username=sa +# spring.datasource.password= spring.jpa.database-platform=org.hibernate.dialect.H2Dialect -spring.datasource.url=jdbc:h2:file:~/test;LOG=0;CACHE_SIZE=65536;LOCK_MODE=0;UNDO_LOG=0 spring.h2.console.enabled=true -spring.h2.console.path=/h2-console +# spring.h2.console.path=/h2-console + +# MYSQL CONFIG +# DataSource settings: set here your own configurations for the database +# connection. In this example we have "test" as database name and +# "root" as username and password. +#spring.datasource.url = jdbc:mysql://localhost:3306/test +# spring.datasource.url = jdbc:mysql://mysql-standalone:3306/test +#spring.datasource.username = sa +#spring.datasource.password = password #spring.datasource.username = root #spring.datasource.password = password - # Keep the connection alive if idle for a long time (needed in production) #spring.datasource.testWhileIdle = true #spring.datasource.validationQuery = SELECT 1 @@ -31,7 +35,7 @@ spring.h2.console.path=/h2-console spring.jpa.show-sql = true # Hibernate ddl auto (create, create-drop, update) -#spring.jpa.hibernate.ddl-auto = update +spring.jpa.hibernate.ddl-auto = create # Naming strategy spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy @@ -41,6 +45,6 @@ spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy # The SQL dialect makes Hibernate generate better SQL for the chosen database # spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect -logging.level.org.springframework.security=DEBUG +#logging.level.org.springframework.security=DEBUG server.port=8086 \ No newline at end of file diff --git a/src/main/resources/import.sql b/src/main/resources/import.sql index 12aeaa906..217d0027d 100644 --- a/src/main/resources/import.sql +++ b/src/main/resources/import.sql @@ -1,5 +1,7 @@ DROP TABLE IF EXISTS tb_user; -CREATE TABLE tb_user(id varchar(255), name varchar(255), username varchar(255)) AS SELECT * FROM CSVREAD('classpath:/users.csv', 'id,name,username', null) limit 10000; +--CREATE TABLE tb_user(id varchar(255), name varchar(255), username varchar(255)); +--LOAD DATA LOCAL INFILE '/home/bruno/IdeaProjects/trabalhe-conosco-backend-dev/src/main/resources/users.csv' INTO TABLE tb_user FIELDS TERMINATED BY ','; +CREATE TABLE tb_user(id varchar(255), name varchar(255), username varchar(255)) AS SELECT * FROM CSVREAD('classpath:/users.csv', 'id,name,username', null); CREATE INDEX idxname ON tb_user(name, username); ALTER TABLE tb_user ADD priority int DEFAULT 10; CREATE INDEX idxpriority ON tb_user(priority); diff --git a/src/test/resources/import.sql b/src/test/resources/import.sql index 0197aaa1d..55ade54a1 100644 --- a/src/test/resources/import.sql +++ b/src/test/resources/import.sql @@ -1 +1 @@ -INSERT INTO tb_user SELECT * FROM CSVREAD('classpath:/users.csv'); \ No newline at end of file +INSERT INTO tb_user SELECT * FROM CSVREAD('classpath:/users-test.csv'); \ No newline at end of file diff --git a/src/test/resources/users.csv b/src/test/resources/users.csv deleted file mode 100644 index 1ac0a8380..000000000 --- a/src/test/resources/users.csv +++ /dev/null @@ -1,117 +0,0 @@ -6e172695-c76c-4364-8dd9-44e6d2d3aed9,Heitor Rovaron,heitor.rovaron -4e8660b0-7350-4211-9b9b-9ba50792ccd9,Melony Terci,melony.terci -7e3d4092-6664-4162-9866-c4256507a35e,Tatiana Arrieiro Filgueira,tatianaarrieirofilgueira -d41d1b73-e28a-4464-a640-abfe1d913cfd,Nadja Elias,nadjaelias -657eb911-3fd1-4317-9430-f5f53199754c,Rafael Furtado,rafael.furtado -c5dcda1f-6d9c-4fe4-824b-ee9a0b138a9c,Luzanira Sardenberg,luzanira.sardenberg -6dec2c10-1522-4cc7-8e45-89d78a6274c2,Donizete Kohler,donizete.kohler -61423001-c484-4fbf-9ee7-9475fb93cf3c,Alinice Araujp,alinicearaujp -c720558d-652d-48d3-b952-40b16124b989,Alax Kaiser Raquel,alax.kaiser.raquel -bea7457f-3d0a-48f8-9ee9-c3ff79bf756b,Candisse Mattis,candisse.mattis -fd7ec052-7e2a-4425-a109-a4a37f105512,Ivanice Callado,ivanicecallado -18c369fe-2b6c-4638-9693-425b13b22948,Vixpark Valariano Federici,vixpark.valariano.federici -850778f4-0bc9-45d0-a732-d023a8f25196, Falfan Brant,falfanbrant -e7e46a01-9618-4f48-978c-9a712949389d,Gustav Angione,gustav.angione -64b7f8c1-6264-4edf-b47a-90f8692056e0,Emannuelly Reginaldo Fofonka,emannuelly.reginaldo.fofonka -cfe9ca52-4b8b-4a15-86f1-4b0adb0f9227,Flaviane Salgado Dudar,flaviane.salgado.dudar -93a30bf5-7c91-45a2-8624-80c79b35b422,Francisca Brunelli Mafetone,francisca.brunelli.mafetone -d2173551-7d7b-47d5-8425-133cdcb69724,Leonaia Farias,leonaiafarias -81bb7a02-c574-4114-85f9-368514aaba29,Rejane fernandes Marinonio,rejane.fernandes.marinonio -f687f04d-5f24-4327-bd74-b07c5660f364,Marcia Louredo,marcialouredo -48da4ef1-9cdf-4a18-aa93-92cdef0d6482,Joeliton RODRIGUES,joelitonrodrigues -a8461f62-d18f-4190-bf97-1684a13b5531,Everaldo Birkman L,everaldo.birkman.l -02b6ce38-b23d-446a-b78b-823f360a4f35,Sarah Auxiliadora,sarah.auxiliadora -708943ab-7987-4632-ae23-1248922b87d6,Jusandra Pessini,jusandrapessini -15d3f155-6a02-4849-9af7-d2cc4148f5a2,Alysson Missagia Mazoco,alyssonmissagiamazoco -b3259f66-1309-42b0-b27e-abb916da67c0,Valdinei Juvencio,valdinei.juvencio -fd3d9ebc-ed89-4a5c-ad0d-c34ecbcae2ac,Joicy Quidicomo,joicyquidicomo -7bd3cf31-e9c5-4b28-b4d2-161b633a99b4,laize Nobrega,laizenobrega -efa7c6a5-7ed7-438a-875b-1fc4184b6bf0,JOSE Cynara Katyuce,jose.cynara.katyuce -fe822c21-d963-4886-ab29-612738cbc47e,Edmarine Castegnara Dattein,edmarine.castegnara.dattein -902a5975-a4a4-4ba8-9a0e-ba3b2812a57d,Franciellen Collopy Marcelina,franciellencollopymarcelina -e04042a2-6ee5-432e-85be-142197dc59c7,Domitila Xx Vavassori,domitila.xx.vavassori -104cf1c0-70d8-4a4e-ac01-29440b10d5ef,Alessandra Ely Isaac,alessandra.ely.isaac -4a873af2-fe3c-4b81-abc3-91ec7299f6b2,Nicolle Ricardo,nicollericardo -529655d9-38c4-4f0c-88d7-62eb8a7adf76,Jacob Swartele,jacobswartele -709b6d12-a526-42d9-9980-25ff71d7c0d9,Morris Franco,morris.franco -5261adc3-8249-4ce0-9ce0-230e65164a8d,Eloisa Lund,eloisa.lund -36fbfe3b-91ba-4bc9-8918-ed94a10aee3f,Cleiziene Bertagnoni,cleiziene.bertagnoni -0cad4728-8f1e-48d4-8e3e-63594ca33b17,Joil Valle,joil.valle -f4fb9402-a929-4d97-b2ed-d424e81bbf51,Kamila Riper,kamilariper -7a917d5a-cb31-4bd5-b6a5-10c90de4b6f2,Vitor Steinmann,vitor.steinmann -b1d011ac-47c7-453c-9558-22027a759f91,Valdirlene William,valdirlenewilliam -cd322a11-d1ac-431a-99a8-25f126a2d389,Aleandra Cassia Abdon,aleandra.cassia.abdon -30abd294-6b09-428b-b761-dc28f6961f43,Sandro Valerii Restum,sandro.valerii.restum -37c5d202-641c-49a6-848b-4fc64bf790ef,Alan Gasco Balbo,alangascobalbo -14f015ba-4cdf-439e-8948-518c5cb5ddce,Jany Carpinteiro,jany.carpinteiro -5e0ccb3e-7f28-47d0-9cf7-9426f364805e,Wesley Souzs,wesley.souzs -6f0bf406-6eb6-4c5c-ab8c-50a2398da5e4,Frank Sabrina Pauperio,frank.sabrina.pauperio -0bc1a237-0995-4bae-9961-ad7c992d1bba,Benedito Calheiros Dionei,benedito.calheiros.dionei -be581d60-9825-441a-92fb-bb2eda2229e3,Vixpark Lessa,vixpark.lessa -6df83561-1386-45e8-b0b5-9e4bfc15d1d7,Stefani Prara Brunhara,stefani.prara.brunhara -56f5e56d-b443-4538-9b47-484a1d7643aa,Elizandra Luziane Sossella,elizandra.luziane.sossella -a64be1f1-f87a-4228-a19a-babb9c394d97,Marilda Regiani,marildaregiani -2858715a-cf1e-473f-94cb-e9a4ac682bb0,Rosemary Goyanna,rosemary.goyanna -bdfc56a9-5ac2-4070-a291-e3f10a785d8d,Keliani Ketten Makuch,kelianikettenmakuch -363a6422-dcc4-4896-ad75-03af2cf8b9da,Zeiny Brandes,zeiny.brandes -d27c46cb-8e5e-4401-8aac-1947c675b297,Greziele Amanti Preira,greziele.amanti.preira -1786166c-3a2f-45bb-8639-d5738d11ff06,Waldeia Melone,waldeia.melone -1398be63-9b24-4d45-8809-bc3ab8b5a75f,Vivyane Cypriano,vivyanecypriano -e17cae43-8f14-4403-8432-d85cc8939727,Elizabete Pompeu,elizabete.pompeu -ab0a5e06-202a-43b2-8705-31022e31c04b,Jose Pivetta P,jose.pivetta.p -32caa8a3-6085-48d5-9eb5-39953de07b82,Christine Eustaquio,christine.eustaquio -092b7c45-cafd-4242-96e1-373c453961d8,Daliana Weigert,daliana.weigert -00afd0b4-63fe-4644-ba88-acdc16502630,Leudileia Valerii,leudileia.valerii -09f51559-17fe-4228-9a45-2c0e2eb6cbbc,Cariza H,cariza.h -18a53b29-997a-470b-8562-10620474b5ab,Kendy FLAVIO Roizen,kendyflavioroizen -8355725e-3953-441f-921f-960ad9e8e93d,Ariana Wilhelm Carvalhp,arianawilhelmcarvalhp -259dfd7e-77b0-4f63-b288-9cad31ba3112,Yane Goncalo,yane.goncalo -df098d5e-23cf-4374-b31c-5034fe7dc1ed,Jhonattan Jacinto,jhonattan.jacinto -595b663a-b091-40f8-8a76-b3ca57534bcd,Quelen Acelino von,quelen.acelino.von -bc541175-304f-49d6-a98f-07b387ee5dbb,Elry Maiolini Rejiane,elry.maiolini.rejiane -3d6f947d-b311-4e61-bf9f-1172dff257dc,Thereza Lessi Bressani,thereza.lessi.bressani -54fb2ece-8c81-4cbc-b8b3-b5cae6b24d33,Lucianeda amatuzzi,lucianeda.amatuzzi -187aa3dc-dc54-4b48-891f-5c199a04c531,Luanda Verner,luanda.verner -275a87a2-6185-4ad7-82d8-0f12864fec43,Nailton Airton,nailton.airton -81241945-b0bd-4b6a-ace5-67336015aef7,Suzelen Martimiano,suzelen.martimiano -bce450dd-1e19-4a00-a95c-2814ece1de59,Luca Emanuele,lucaemanuele -b62b6525-f480-4d38-b100-64b0cfb843f6,Jaime Rodrigues,jaimerodrigues -c3bec5ba-bb5a-4f8c-bc31-8cb41359e174,Ademir Girelli,ademir.girelli -c91ee16c-7497-4634-aa17-65106681d396,Tauane Lucaa,tauane.lucaa -7ad381e7-c54d-47a5-8e83-d010cc979a27,Augustho Leopici barreto,augustho.leopici.barreto -51269a99-684a-4976-b518-da346219f28c,Samir Cynthia Paim,samir.cynthia.paim -83477481-6b3d-4433-a75f-17bc631f3812,Ivanires Drudi,ivaniresdrudi -89414639-ec14-415f-ae7b-9850e04d81c2,Amauri Lother,amauri.lother -aedb0fec-3ce2-4017-92f4-5b8a0a244805,Cefas Silva,cefas.silva -792db824-2d78-4091-a0bf-03863f0eb8d6,Yara Zago,yara.zago -927197cc-28f5-4807-a649-f9cd9d172760,Enaide Williany,enaidewilliany -e24ba427-5302-456a-aefd-7cc907ff8604,MARIO Toscano,mario.toscano -d59cc9d9-3a45-4c5a-944e-25cd681edcda,Suellen Scaletti Reginaldo,suellenscalettireginaldo -f5b79043-83cd-4ba1-9427-848fa61c7146,Roger Sabotto,roger.sabotto -245cf7fe-9744-477c-a58a-90038ce5d531,Adriene PAULO,adriene.paulo -1f63e134-50a1-4c7c-86f7-3c892894e42a,Gabrielle Ribeiri Pianna,gabrielle.ribeiri.pianna -223fe7f8-fa44-4360-8c91-837e04346ba0,Juciara Cestari,juciara.cestari -dfe8a80e-19b6-4530-a635-b69b2066e193,Naiani Em,naiani.em -f39dd988-31fe-4c54-9fd4-497cc7d076d9,Jerry Erlaches,jerryerlaches -aa842796-9b06-4fce-8256-e16af7aa3311,Karyna Agostinho,karyna.agostinho -68e9215b-9d8d-4b2d-b0dd-f4a6d8fe15dc,Maiky Iara Buarque,maiky.iara.buarque -27bf3036-ccac-4d49-9eb8-26b16adadc34,Lucide O,lucide.o -56987a61-88ef-4ba7-a97c-f29c8e7f69ef,Caique Brigatto,caique.brigatto -7443be6a-16fc-4c36-ba63-be34290e6f0a,Jannayna Lozer Deleon,jannayna.lozer.deleon -543144ac-ae86-48c5-ab65-6591a45db040,Francielly Paranhos,francielly.paranhos -470dfa6a-a2a9-4d73-841b-1e96b4d524eb,Endrezy Scalfoni,endrezyscalfoni -58923126-03fa-4772-bac9-87f5d317e598,Licia Roriz,liciaroriz -d508278a-12be-42aa-b3ac-80c30720120d,Alice Loureiro,aliceloureiro -1785c1b5-e9f5-4a65-8742-066f55e1d8e1,Wilton Negrelli,wiltonnegrelli -780c732f-f36f-480b-9548-7a28ccdc2657,Evelly Varella Vianna,evelly.varella.vianna -b50051b3-4f60-4ba3-b649-63a6b99c104e,Cinara Bomtempo Maira,cinara.bomtempo.maira -e5cc712f-a688-4389-974b-757aa7438af5,Tamiris Ivan,tamiris.ivan -927ed97a-64d2-4d38-b065-81d244685915,Eryka Marilac,eryka.marilac -ae152332-1b3a-4efc-968a-32539b7ae98e,Wekesley Vanete Schiavon,wekesleyvaneteschiavon -3d8f916b-7e8d-4e0c-b421-8ed8b1119283,Ludiely Zaineli Morale,ludiely.zaineli.morale -aef241cf-0678-4106-ad3f-00f956cac1c0,Talicia Loblein,talicialoblein -e3d2ba76-8241-4d60-8f2e-6e30381886b5,Isabele vil,isabele.vil -07261474-de87-45f4-9a5e-6849e672aaea,Jacy Evelyn,jacy.evelyn -6e25ab33-1500-42b7-88e4-15b02853b67f,Caliane Redig,calianeredig -d2b5b90f-c857-4c85-afbd-e5544b886c51,Gilmar Feola,gilmar.feola -01326111-4c38-479c-a057-ab92c955fd76,Wellyngton Ressurreicao,wellyngton.ressurreicao From 980123d545b392a36a2e2a45748b5ee84cb5cc7d Mon Sep 17 00:00:00 2001 From: Bruno Carreira Date: Thu, 18 Oct 2018 22:02:23 -0300 Subject: [PATCH 24/26] changes --- pom.xml | 2 +- .../java/com/picpay/ApplicationStartup.java | 15 ------ .../java/com/picpay/DatasourceConfig.java | 51 +++++++++++++++++++ src/main/resources/application.properties | 2 +- 4 files changed, 53 insertions(+), 17 deletions(-) create mode 100644 src/main/java/com/picpay/DatasourceConfig.java diff --git a/pom.xml b/pom.xml index c3fe5ba8e..4f10ec527 100644 --- a/pom.xml +++ b/pom.xml @@ -52,7 +52,7 @@ com.h2database h2 - runtime + mysql diff --git a/src/main/java/com/picpay/ApplicationStartup.java b/src/main/java/com/picpay/ApplicationStartup.java index 22a7f699f..92c6d5661 100644 --- a/src/main/java/com/picpay/ApplicationStartup.java +++ b/src/main/java/com/picpay/ApplicationStartup.java @@ -22,9 +22,6 @@ @Component public class ApplicationStartup implements CommandLineRunner { - @Value("${com.picpay.csv.database.url}") - private final String csvDatabaseUrl = null; - @Value("${com.picpay.csv.database.filename}") private final String csvDatabaseFilename = null; @@ -43,18 +40,6 @@ public class ApplicationStartup implements CommandLineRunner { @Override public void run(String... strings) throws Exception { LOG.info("Updating priority...."); - /* - InputStream zipFileInputStream = new URL(csvDatabaseUrl).openStream(); - GZIPInputStream is = new GZIPInputStream(zipFileInputStream); - - File targetFile = new File("src/main/resources/userstest.csv"); - - java.nio.file.Files.copy( - is, - targetFile.toPath(), - StandardCopyOption.REPLACE_EXISTING); -*/ - //IOUtils.closeQuietly(is); repo.updatePriorityByIds(listRelevancia1, 1); repo.updatePriorityByIds(listRelevancia2, 2); LOG.info("Priority updated!"); diff --git a/src/main/java/com/picpay/DatasourceConfig.java b/src/main/java/com/picpay/DatasourceConfig.java new file mode 100644 index 000000000..93842a4f8 --- /dev/null +++ b/src/main/java/com/picpay/DatasourceConfig.java @@ -0,0 +1,51 @@ +package com.picpay; + + +import org.apache.tomcat.util.http.fileupload.IOUtils; +import org.h2.jdbcx.JdbcDataSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.sql.DataSource; +import java.io.File; +import java.io.InputStream; +import java.net.URL; +import java.nio.file.StandardCopyOption; +import java.util.zip.GZIPInputStream; + + +@Configuration +public class DatasourceConfig { + + @Value("${com.picpay.csv.database.url}") + private final String csvDatabaseUrl = null; + + private static final Logger LOG = + LoggerFactory.getLogger(DatasourceConfig.class); + + //private static final String TEMP_DIRECTORY = System.getProperty("java.io.tmpdir"); + @Bean(name = "mainDataSource") + public DataSource createMainDataSource() throws Exception { + LOG.info("createMainDataSource..."); + + InputStream zipFileInputStream = new URL(csvDatabaseUrl).openStream(); + GZIPInputStream is = new GZIPInputStream(zipFileInputStream); + + File targetFile = new File("src/main/resources/users.csv"); + + java.nio.file.Files.copy( + is, + targetFile.toPath(), + StandardCopyOption.REPLACE_EXISTING); + + IOUtils.closeQuietly(is); + LOG.info("createMainDataSource end..."); + + JdbcDataSource ds = new JdbcDataSource(); + ds.setURL("jdbc:h2:file:~/testdb;LOG=0;CACHE_SIZE=65536;LOCK_MODE=0;UNDO_LOG=0"); + return ds; + } +} \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index ed4e9df5a..b55838601 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -9,7 +9,7 @@ com.picpay.relevancia2=lista_relevancia_2.txt # H2 CONFIG # spring.datasource.url=jdbc:h2:mem:testdb -spring.datasource.url=jdbc:h2:file:~/testdb;LOG=0;CACHE_SIZE=65536;LOCK_MODE=0;UNDO_LOG=0 +#spring.datasource.url=jdbc:h2:file:~/testdb;LOG=0;CACHE_SIZE=65536;LOCK_MODE=0;UNDO_LOG=0 spring.datasource.driverClassName=org.h2.Driver # spring.datasource.username=sa # spring.datasource.password= From ff0d892f11ad5f6b829f6a8e8249a57783cfcc97 Mon Sep 17 00:00:00 2001 From: "brunocarreira.silva" Date: Fri, 19 Oct 2018 13:09:49 -0300 Subject: [PATCH 25/26] final changes --- README.md | 40 ++++++++++++ .../java/com/picpay/ApplicationStartup.java | 11 +--- .../java/com/picpay/DatasourceConfig.java | 29 +++++---- .../com/picpay/UserManagerApplication.java | 3 - .../java/com/picpay/WebSecurityConfig.java | 16 ----- .../controller/UserSearchController.java | 63 ------------------- .../picpay/repositories/UserRepository.java | 3 - .../java/com/picpay/service/UserService.java | 34 ---------- src/main/java/com/picpay/util/CsvUtil.java | 27 -------- .../com/picpay/util/UserSpecifications.java | 27 -------- src/main/resources/import.sql | 2 +- 11 files changed, 60 insertions(+), 195 deletions(-) delete mode 100644 src/main/java/com/picpay/controller/UserSearchController.java delete mode 100644 src/main/java/com/picpay/service/UserService.java delete mode 100644 src/main/java/com/picpay/util/CsvUtil.java delete mode 100644 src/main/java/com/picpay/util/UserSpecifications.java diff --git a/README.md b/README.md index 6fcb5a302..520880c4f 100644 --- a/README.md +++ b/README.md @@ -33,3 +33,43 @@ Faça um ***Fork*** deste repositório e abra um ***Pull Request***, **com seu n - Ter um desempenho elevado num conjunto de dados muito grande - Utilizar o Docker +----- + +# Solução + +O backend foi desenvolvido com a utilização do framework Spring Data REST, com banco H2 embedded. +Uma UI simples foi construída em ReactJS para listar o resultado da busca com paginação. + +### UI + +A aplicação ReactJS utiliza webpack para compilar todos os arquivos num bundle. Usa rest.js para comunicação com a API REST. E usa babel para compilar ES6 para ES5. + +### Segurança + +A API está protegida por BASIC AUTHENTICATION, via Spring Security (usuário e senha: bruno). + +### Docker + +Um arquivo Dockerfile foi adicionado ao projeto permitindo a criação de uma imagem baseada no JDK8. +Para gerar a imagem, basta executar do diretório do projeto: + +`docker build . -t user-search` + +Depois de baixar a imagem, basta executá-la: + +`docker run image user-search` + +### Executando na máquina local + +Não é necessário ter npm e nodeJS na máquina local para executar a UI. +Basta executar: + +`mvn spring-boot:run` + +Esta operação demandará um bom tempo porque, além de instalar npm e nodeJS embedded, vai fazer o download do arquivo users.csv.gz, descompactá-lo e carregar o banco de dados H2. + +## Melhorias + +- Otimizar o banco de dados H2 para melhor performance de LOAD e SEARCH +- Utilizar um banco de dados noSQL +- Criar mais unit tests e integration tests diff --git a/src/main/java/com/picpay/ApplicationStartup.java b/src/main/java/com/picpay/ApplicationStartup.java index 92c6d5661..53b9d901e 100644 --- a/src/main/java/com/picpay/ApplicationStartup.java +++ b/src/main/java/com/picpay/ApplicationStartup.java @@ -1,19 +1,14 @@ package com.picpay; import com.picpay.repositories.UserRepository; -import org.apache.tomcat.util.http.fileupload.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; -import java.io.*; -import java.net.URL; -import java.nio.file.StandardCopyOption; import java.util.List; -import java.util.zip.GZIPInputStream; + /** * @author Bruno Carreira @@ -21,10 +16,6 @@ // tag::code[] @Component public class ApplicationStartup implements CommandLineRunner { - - @Value("${com.picpay.csv.database.filename}") - private final String csvDatabaseFilename = null; - @Autowired private List listRelevancia1; diff --git a/src/main/java/com/picpay/DatasourceConfig.java b/src/main/java/com/picpay/DatasourceConfig.java index 93842a4f8..46de77cf5 100644 --- a/src/main/java/com/picpay/DatasourceConfig.java +++ b/src/main/java/com/picpay/DatasourceConfig.java @@ -13,6 +13,7 @@ import java.io.File; import java.io.InputStream; import java.net.URL; +import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.zip.GZIPInputStream; @@ -26,26 +27,32 @@ public class DatasourceConfig { private static final Logger LOG = LoggerFactory.getLogger(DatasourceConfig.class); - //private static final String TEMP_DIRECTORY = System.getProperty("java.io.tmpdir"); + private static final String CSV_PATH = "src/main/resources/users.csv"; + @Bean(name = "mainDataSource") public DataSource createMainDataSource() throws Exception { - LOG.info("createMainDataSource..."); + LOG.info("Importing and extracting CSV file..."); + + if (!java.nio.file.Files.exists(Paths.get(CSV_PATH))) { - InputStream zipFileInputStream = new URL(csvDatabaseUrl).openStream(); - GZIPInputStream is = new GZIPInputStream(zipFileInputStream); + InputStream zipFileInputStream = new URL(csvDatabaseUrl).openStream(); + GZIPInputStream is = new GZIPInputStream(zipFileInputStream); - File targetFile = new File("src/main/resources/users.csv"); + File targetFile = new File(CSV_PATH); - java.nio.file.Files.copy( - is, - targetFile.toPath(), - StandardCopyOption.REPLACE_EXISTING); + java.nio.file.Files.copy( + is, + targetFile.toPath(), + StandardCopyOption.REPLACE_EXISTING); - IOUtils.closeQuietly(is); - LOG.info("createMainDataSource end..."); + IOUtils.closeQuietly(is); + LOG.info("CSV imported and extracted..."); + } JdbcDataSource ds = new JdbcDataSource(); ds.setURL("jdbc:h2:file:~/testdb;LOG=0;CACHE_SIZE=65536;LOCK_MODE=0;UNDO_LOG=0"); + ds.setUser("sa"); + ds.setPassword(""); return ds; } } \ No newline at end of file diff --git a/src/main/java/com/picpay/UserManagerApplication.java b/src/main/java/com/picpay/UserManagerApplication.java index 2311916fa..9166781ac 100644 --- a/src/main/java/com/picpay/UserManagerApplication.java +++ b/src/main/java/com/picpay/UserManagerApplication.java @@ -3,16 +3,13 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.List; -import java.util.stream.Collector; import java.util.stream.Collectors; -import java.util.stream.Stream; /** * @author Bruno Carreira diff --git a/src/main/java/com/picpay/WebSecurityConfig.java b/src/main/java/com/picpay/WebSecurityConfig.java index ce9030a9a..014d6a84e 100644 --- a/src/main/java/com/picpay/WebSecurityConfig.java +++ b/src/main/java/com/picpay/WebSecurityConfig.java @@ -1,22 +1,16 @@ package com.picpay; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.crypto.password.PasswordEncoder; @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { -// @Autowired -// private MyBasicAuthenticationEntryPoint authenticationEntryPoint; - @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() @@ -28,17 +22,7 @@ public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/api/**").authenticated() - //.anyRequest().authenticated() .and() .httpBasic(); -// .authenticationEntryPoint(authenticationEntryPoint); - -// http.addFilterAfter(new CustomFilter(), -// BasicAuthenticationFilter.class); - } - - @Bean - public PasswordEncoder passwordEncoder() { - return new BCryptPasswordEncoder(); } } diff --git a/src/main/java/com/picpay/controller/UserSearchController.java b/src/main/java/com/picpay/controller/UserSearchController.java deleted file mode 100644 index e2e07c65b..000000000 --- a/src/main/java/com/picpay/controller/UserSearchController.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.picpay.controller; - -import com.picpay.model.User; -import com.picpay.repositories.UserRepository; -import com.picpay.service.UserService; -import com.picpay.util.UserSpecifications; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.domain.Specification; -import org.springframework.data.jpa.domain.Specifications; -import org.springframework.data.rest.webmvc.RepositoryRestController; -import org.springframework.data.web.PagedResourcesAssembler; -import org.springframework.hateoas.PagedResources; -import org.springframework.hateoas.Resource; -import org.springframework.hateoas.Resources; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.*; - -import javax.persistence.criteria.Predicate; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; -import java.util.stream.Collectors; - -/** - * @author Bruno Carreira - */ -// tag::code[] - /* -@RepositoryRestController -public class UserSearchController { - - @Autowired - private UserRepository repo; - - @Autowired - private List listRelevancia1; - - @Autowired - private List listRelevancia2; - - @Autowired - private PagedResourcesAssembler pagedAssembler; - - @RequestMapping(value = "/users/search/listUsers", method = RequestMethod.GET) - public @ResponseBody PagedResources> search(@RequestParam(value = "nome") String nome, Pageable pageable) { - String rel1 = listRelevancia1.stream().map(id -> "("+id+",1)").collect(Collectors.joining(",")); - String rel2 = listRelevancia2.stream().map(id -> "("+id+",2)").collect(Collectors.joining(",")); - - //users.sort(Comparator.comparing(u->listRelevancia1.indexOf(u.getId()))); - - Page users = repo.findAll(Specifications.where(UserSpecifications.containsTextInName(nome)), pageable); - - return pagedAssembler.toResource(users); - } - - -} -*/ -// end::code[] \ No newline at end of file diff --git a/src/main/java/com/picpay/repositories/UserRepository.java b/src/main/java/com/picpay/repositories/UserRepository.java index 8ba61af31..eb5081952 100644 --- a/src/main/java/com/picpay/repositories/UserRepository.java +++ b/src/main/java/com/picpay/repositories/UserRepository.java @@ -3,7 +3,6 @@ import com.picpay.model.User; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.PagingAndSortingRepository; @@ -19,8 +18,6 @@ @Transactional public interface UserRepository extends PagingAndSortingRepository { -// Page findAll(Specification spec, Pageable pageable); - @RestResource(path = "usersbyname", rel = "usersbyname") Page findByNameContainingOrUsernameContainingOrderByPriority(@Param("name") String nameText, @Param("username") String usernameText, Pageable pageable); diff --git a/src/main/java/com/picpay/service/UserService.java b/src/main/java/com/picpay/service/UserService.java deleted file mode 100644 index 7999b576e..000000000 --- a/src/main/java/com/picpay/service/UserService.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.picpay.service; - -import com.picpay.model.User; -import com.picpay.repositories.UserRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.stream.Collectors; - -@Service -public class UserService { - - UserRepository repository; - - @Autowired - private List listRelevancia1; - - @Autowired - private List listRelevancia2; - - @Autowired - public UserService(UserRepository repository){ - this.repository = repository; - } -/* - public List searchUsers(String criteria){ - //String rel1 = listRelevancia1.stream().map(id -> "("+id+",1),").reduce("", String::concat); - String rel1 = listRelevancia1.stream().map(id -> "("+id+",1)").collect(Collectors.joining(",")); - String rel2 = listRelevancia1.stream().map(id -> "("+id+",2)").collect(Collectors.joining(",")); - return repository.searchByCriteria(criteria, rel1, rel2); - } - */ -} diff --git a/src/main/java/com/picpay/util/CsvUtil.java b/src/main/java/com/picpay/util/CsvUtil.java deleted file mode 100644 index bfe84924b..000000000 --- a/src/main/java/com/picpay/util/CsvUtil.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.picpay.util; - -import com.fasterxml.jackson.databind.MappingIterator; -import com.fasterxml.jackson.databind.ObjectReader; -import com.fasterxml.jackson.dataformat.csv.CsvMapper; -import com.fasterxml.jackson.dataformat.csv.CsvSchema; - -import java.io.IOException; -import java.io.InputStream; - -public class CsvUtil { - - public static MappingIterator read(Class clazz, InputStream stream) throws IOException { - final CsvMapper mapper = new CsvMapper(); - CsvSchema schema = mapper.schemaFor(clazz).withColumnReordering(true); - ObjectReader reader = mapper.readerFor(clazz).with(schema); - return reader.readValues(stream); - } - - public static T readLine(Class clazz, String line) throws IOException { - final CsvMapper mapper = new CsvMapper(); - CsvSchema schema = mapper.schemaFor(clazz).withColumnReordering(true); - ObjectReader reader = mapper.readerFor(clazz).with(schema); - return reader.readValue(line); - } - -} \ No newline at end of file diff --git a/src/main/java/com/picpay/util/UserSpecifications.java b/src/main/java/com/picpay/util/UserSpecifications.java deleted file mode 100644 index 089494722..000000000 --- a/src/main/java/com/picpay/util/UserSpecifications.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.picpay.util; - -import com.picpay.model.User; -import org.springframework.data.jpa.domain.Specification; - -import javax.persistence.criteria.Predicate; -import java.util.Arrays; -import java.util.List; - -public class UserSpecifications { - - public static Specification containsTextInAttributes(String text, List attributes) { - if (!text.contains("%")) { - text = "%" + text + "%"; - } - String finalText = text; - return (root, query, builder) -> builder.or(root.getModel().getDeclaredSingularAttributes().stream() - .filter(a -> attributes.contains(a.getName())) - .map(a -> builder.like(root.get(a.getName()), finalText)) - .toArray(Predicate[]::new) - ); - } - - public static Specification containsTextInName(String text) { - return containsTextInAttributes(text, Arrays.asList("name", "username")); - } -} diff --git a/src/main/resources/import.sql b/src/main/resources/import.sql index 217d0027d..56904b139 100644 --- a/src/main/resources/import.sql +++ b/src/main/resources/import.sql @@ -1,6 +1,6 @@ -DROP TABLE IF EXISTS tb_user; --CREATE TABLE tb_user(id varchar(255), name varchar(255), username varchar(255)); --LOAD DATA LOCAL INFILE '/home/bruno/IdeaProjects/trabalhe-conosco-backend-dev/src/main/resources/users.csv' INTO TABLE tb_user FIELDS TERMINATED BY ','; +DROP TABLE IF EXISTS tb_user; CREATE TABLE tb_user(id varchar(255), name varchar(255), username varchar(255)) AS SELECT * FROM CSVREAD('classpath:/users.csv', 'id,name,username', null); CREATE INDEX idxname ON tb_user(name, username); ALTER TABLE tb_user ADD priority int DEFAULT 10; From 4fdf4657ee6b086c0d966725ba6cf4bdbcd65e44 Mon Sep 17 00:00:00 2001 From: "brunocarreira.silva" Date: Fri, 19 Oct 2018 13:14:46 -0300 Subject: [PATCH 26/26] final changes --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 520880c4f..2ad302c99 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,8 @@ Basta executar: `mvn spring-boot:run` Esta operação demandará um bom tempo porque, além de instalar npm e nodeJS embedded, vai fazer o download do arquivo users.csv.gz, descompactá-lo e carregar o banco de dados H2. +Após a execução correta do comando acima, basta acessar a URL (`http://localhost:8086/`) no browser. +Caso queira acessar diretamente a API, basta acessar `http://localhost:8086/api/users` ou `http://localhost:8086/api/users/search/listUsers?nome=nome` ## Melhorias