diff --git a/.csslintrc b/.csslintrc
new file mode 100644
index 0000000..aacba95
--- /dev/null
+++ b/.csslintrc
@@ -0,0 +1,2 @@
+--exclude-exts=.min.css
+--ignore=adjoining-classes,box-model,ids,order-alphabetical,unqualified-attributes
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..96212a3
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1 @@
+**/*{.,-}min.js
diff --git a/.eslintrc b/.eslintrc
new file mode 100644
index 0000000..9faa375
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,213 @@
+ecmaFeatures:
+ modules: true
+ jsx: true
+
+env:
+ amd: true
+ browser: true
+ es6: true
+ jquery: true
+ node: true
+
+# http://eslint.org/docs/rules/
+rules:
+ # Possible Errors
+ comma-dangle: [2, never]
+ no-cond-assign: 2
+ no-console: 0
+ no-constant-condition: 2
+ no-control-regex: 2
+ no-debugger: 2
+ no-dupe-args: 2
+ no-dupe-keys: 2
+ no-duplicate-case: 2
+ no-empty: 2
+ no-empty-character-class: 2
+ no-ex-assign: 2
+ no-extra-boolean-cast: 2
+ no-extra-parens: 0
+ no-extra-semi: 2
+ no-func-assign: 2
+ no-inner-declarations: [2, functions]
+ no-invalid-regexp: 2
+ no-irregular-whitespace: 2
+ no-negated-in-lhs: 2
+ no-obj-calls: 2
+ no-regex-spaces: 2
+ no-sparse-arrays: 2
+ no-unexpected-multiline: 2
+ no-unreachable: 2
+ use-isnan: 2
+ valid-jsdoc: 0
+ valid-typeof: 2
+
+ # Best Practices
+ accessor-pairs: 2
+ block-scoped-var: 0
+ complexity: [2, 6]
+ consistent-return: 0
+ curly: 0
+ default-case: 0
+ dot-location: 0
+ dot-notation: 0
+ eqeqeq: 2
+ guard-for-in: 2
+ no-alert: 2
+ no-caller: 2
+ no-case-declarations: 2
+ no-div-regex: 2
+ no-else-return: 0
+ no-empty-label: 2
+ no-empty-pattern: 2
+ no-eq-null: 2
+ no-eval: 2
+ no-extend-native: 2
+ no-extra-bind: 2
+ no-fallthrough: 2
+ no-floating-decimal: 0
+ no-implicit-coercion: 0
+ no-implied-eval: 2
+ no-invalid-this: 0
+ no-iterator: 2
+ no-labels: 0
+ no-lone-blocks: 2
+ no-loop-func: 2
+ no-magic-number: 0
+ no-multi-spaces: 0
+ no-multi-str: 0
+ no-native-reassign: 2
+ no-new-func: 2
+ no-new-wrappers: 2
+ no-new: 2
+ no-octal-escape: 2
+ no-octal: 2
+ no-proto: 2
+ no-redeclare: 2
+ no-return-assign: 2
+ no-script-url: 2
+ no-self-compare: 2
+ no-sequences: 0
+ no-throw-literal: 0
+ no-unused-expressions: 2
+ no-useless-call: 2
+ no-useless-concat: 2
+ no-void: 2
+ no-warning-comments: 0
+ no-with: 2
+ radix: 2
+ vars-on-top: 0
+ wrap-iife: 2
+ yoda: 0
+
+ # Strict
+ strict: 0
+
+ # Variables
+ init-declarations: 0
+ no-catch-shadow: 2
+ no-delete-var: 2
+ no-label-var: 2
+ no-shadow-restricted-names: 2
+ no-shadow: 0
+ no-undef-init: 2
+ no-undef: 0
+ no-undefined: 0
+ no-unused-vars: 0
+ no-use-before-define: 0
+
+ # Node.js and CommonJS
+ callback-return: 2
+ global-require: 2
+ handle-callback-err: 2
+ no-mixed-requires: 0
+ no-new-require: 0
+ no-path-concat: 2
+ no-process-exit: 2
+ no-restricted-modules: 0
+ no-sync: 0
+
+ # Stylistic Issues
+ array-bracket-spacing: 0
+ block-spacing: 0
+ brace-style: 0
+ camelcase: 0
+ comma-spacing: 0
+ comma-style: 0
+ computed-property-spacing: 0
+ consistent-this: 0
+ eol-last: 0
+ func-names: 0
+ func-style: 0
+ id-length: 0
+ id-match: 0
+ indent: 0
+ jsx-quotes: 0
+ key-spacing: 0
+ linebreak-style: 0
+ lines-around-comment: 0
+ max-depth: 0
+ max-len: 0
+ max-nested-callbacks: 0
+ max-params: 0
+ max-statements: [2, 30]
+ new-cap: 0
+ new-parens: 0
+ newline-after-var: 0
+ no-array-constructor: 0
+ no-bitwise: 0
+ no-continue: 0
+ no-inline-comments: 0
+ no-lonely-if: 0
+ no-mixed-spaces-and-tabs: 0
+ no-multiple-empty-lines: 0
+ no-negated-condition: 0
+ no-nested-ternary: 0
+ no-new-object: 0
+ no-plusplus: 0
+ no-restricted-syntax: 0
+ no-spaced-func: 0
+ no-ternary: 0
+ no-trailing-spaces: 0
+ no-underscore-dangle: 0
+ no-unneeded-ternary: 0
+ object-curly-spacing: 0
+ one-var: 0
+ operator-assignment: 0
+ operator-linebreak: 0
+ padded-blocks: 0
+ quote-props: 0
+ quotes: 0
+ require-jsdoc: 0
+ semi-spacing: 0
+ semi: 0
+ sort-vars: 0
+ space-after-keywords: 0
+ space-before-blocks: 0
+ space-before-function-paren: 0
+ space-before-keywords: 0
+ space-in-parens: 0
+ space-infix-ops: 0
+ space-return-throw-case: 0
+ space-unary-ops: 0
+ spaced-comment: 0
+ wrap-regex: 0
+
+ # ECMAScript 6
+ arrow-body-style: 0
+ arrow-parens: 0
+ arrow-spacing: 0
+ constructor-super: 0
+ generator-star-spacing: 0
+ no-arrow-condition: 0
+ no-class-assign: 0
+ no-const-assign: 0
+ no-dupe-class-members: 0
+ no-this-before-super: 0
+ no-var: 0
+ object-shorthand: 0
+ prefer-arrow-callback: 0
+ prefer-const: 0
+ prefer-reflect: 0
+ prefer-spread: 0
+ prefer-template: 0
+ require-yield: 0
diff --git a/.gitignore b/.gitignore
index b4a861d..ce44bc4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,8 +3,4 @@ out
target
*.iml
logs
-db
-
-
-
-
+db
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..6f1b2a9
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,2 @@
+language: java
+jdk: oraclejdk8
\ No newline at end of file
diff --git a/config/nginx.conf.conf b/config/nginx.conf.conf
index 1be06c8..56cb03f 100644
--- a/config/nginx.conf.conf
+++ b/config/nginx.conf.conf
@@ -13,7 +13,7 @@ http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
- keepalive_timeout 65;
+ keepalive_timeout 180;
error_log /home/ec2-user/javaops/logs/nginx.error.log;
access_log /home/ec2-user/javaops/logs/nginx.access.log;
@@ -32,14 +32,28 @@ http {
}
location /css/ {
- expires 1d;
+ expires 3h;
access_log off;
}
+# location /interview/test.html {
+# proxy_pass http://localhost:8080/view/test;
+# }
+# location /payment.html {
+# proxy_pass http://localhost:8080/view/payment;
+# }
+# location /story.html {
+# proxy_pass http://localhost:8080/view/story;
+# }
+# location ~ ^.*\.html$ {
+# expires 3h;
+# access_log off;
+# }
+
location / {
expires 0m;
proxy_pass http://localhost:8080;
- proxy_connect_timeout 10s;
+ proxy_connect_timeout 30s;
}
}
}
\ No newline at end of file
diff --git a/db_migration/2016-03-01.sql b/db_migration/2016-03-01.sql
new file mode 100644
index 0000000..8db2a80
--- /dev/null
+++ b/db_migration/2016-03-01.sql
@@ -0,0 +1,2 @@
+ALTER TABLE PUBLIC.USER_GROUP ALTER COLUMN TYPE RENAME TO REGISTER_TYPE;
+ALTER TABLE PUBLIC.USER_GROUP ADD PARTICIPATION_TYPE VARCHAR(255) NULL;
diff --git a/db_migration/2016-06-01.sql b/db_migration/2016-06-01.sql
new file mode 100644
index 0000000..47badbd
--- /dev/null
+++ b/db_migration/2016-06-01.sql
@@ -0,0 +1,2 @@
+ALTER TABLE USERS ADD STATS_AGREE BOOL DEFAULT FALSE;
+UPDATE USERS SET STATS_AGREE=FALSE;
\ No newline at end of file
diff --git a/db_migration/2016-08-09.sql b/db_migration/2016-08-09.sql
new file mode 100644
index 0000000..02a15f4
--- /dev/null
+++ b/db_migration/2016-08-09.sql
@@ -0,0 +1 @@
+ALTER TABLE MAIL_CASE ALTER COLUMN RESULT TEXT;
\ No newline at end of file
diff --git a/db_migration/2017-02-23.sql b/db_migration/2017-02-23.sql
new file mode 100644
index 0000000..891b140
--- /dev/null
+++ b/db_migration/2017-02-23.sql
@@ -0,0 +1 @@
+ALTER TABLE USERS ALTER COLUMN JOB_THRU_TOPJAVA RENAME TO JOB_THROUGH_TOPJAVA;
\ No newline at end of file
diff --git a/db_migration/2017-02-24.sql b/db_migration/2017-02-24.sql
new file mode 100644
index 0000000..370f60f
--- /dev/null
+++ b/db_migration/2017-02-24.sql
@@ -0,0 +1 @@
+ALTER TABLE USER_GROUP ADD registered_date TIMESTAMP DEFAULT NOW();
\ No newline at end of file
diff --git a/db_migration/2017-02-25.sql b/db_migration/2017-02-25.sql
new file mode 100644
index 0000000..51ad827
--- /dev/null
+++ b/db_migration/2017-02-25.sql
@@ -0,0 +1 @@
+CREATE UNIQUE INDEX USER_ROLES_USER_ID_ROLE_uindex ON USER_ROLES (USER_ID, ROLE);
\ No newline at end of file
diff --git a/db_migration/2017-04-23.sql b/db_migration/2017-04-23.sql
new file mode 100644
index 0000000..dbeb314
--- /dev/null
+++ b/db_migration/2017-04-23.sql
@@ -0,0 +1,11 @@
+ALTER TABLE PAYMENT ADD USER_GROUP_ID INT NULL;
+ALTER TABLE PAYMENT ADD CONSTRAINT payment_user_group_idx FOREIGN KEY (USER_GROUP_ID) REFERENCES USER_GROUP (ID) ON DELETE CASCADE;
+
+SELECT * FROM PAYMENT p WHERE USER_GROUP_ID IS NULL;
+
+-- SELECT * FROM USER_GROUP WHERE GROUP_ID=1;
+-- UPDATE PAYMENT p SET USER_GROUP_ID=210 WHERE USER_GROUP_ID IS NULL;
+
+ALTER TABLE PAYMENT ALTER COLUMN USER_GROUP_ID INTEGER NOT NULL;
+ALTER TABLE USER_GROUP DROP COLUMN PAYMENT_ID;
+
diff --git a/db_migration/2017-06-09.sql b/db_migration/2017-06-09.sql
new file mode 100644
index 0000000..dbeb314
--- /dev/null
+++ b/db_migration/2017-06-09.sql
@@ -0,0 +1,11 @@
+ALTER TABLE PAYMENT ADD USER_GROUP_ID INT NULL;
+ALTER TABLE PAYMENT ADD CONSTRAINT payment_user_group_idx FOREIGN KEY (USER_GROUP_ID) REFERENCES USER_GROUP (ID) ON DELETE CASCADE;
+
+SELECT * FROM PAYMENT p WHERE USER_GROUP_ID IS NULL;
+
+-- SELECT * FROM USER_GROUP WHERE GROUP_ID=1;
+-- UPDATE PAYMENT p SET USER_GROUP_ID=210 WHERE USER_GROUP_ID IS NULL;
+
+ALTER TABLE PAYMENT ALTER COLUMN USER_GROUP_ID INTEGER NOT NULL;
+ALTER TABLE USER_GROUP DROP COLUMN PAYMENT_ID;
+
diff --git a/db_migration/2017-06-19.sql b/db_migration/2017-06-19.sql
new file mode 100644
index 0000000..57116a7
--- /dev/null
+++ b/db_migration/2017-06-19.sql
@@ -0,0 +1,2 @@
+UPDATE USERS SET BONUS=0;
+ALTER TABLE USERS ALTER COLUMN BONUS INTEGER DEFAULT 0;
diff --git a/topjava2.md b/info.md
similarity index 60%
rename from topjava2.md
rename to info.md
index 4ed18f0..b94ef08 100644
--- a/topjava2.md
+++ b/info.md
@@ -1,23 +1,21 @@
-Запуск: mvn spring-boot:run
-
-Коннект к базе (только 1 коннект возможен):
-
-- профиль prod
-
- - приложение не работает jdbc:h2:file:~/db/javaops
- - приложение работает: jdbc:h2:tcp://localhost:9092/~/db/javaops
-
-- профиль dev
- - jdbc:h2:tcp://localhost:9092/mem:javaops
-
------------------------------------------------------
## Spring Boot generate/run
+[mvnw / mvnw.cmd](http://stackoverflow.com/questions/38723833/spring-boot-what-is-the-purpose-of-mvnw-and-mvnw-cmd-files)
+
- Spring Boot and Intellij IDEA 14
- https://github.com/snicoll-demos/spring-boot-intellij-idea-webinar
- Spring Boot Reference Guide
- spring-projects/spring-boot
- Building REST services with Spring
+- https://springframework.guru/spring-boot-web-application-part-1-spring-initializr/
+- https://springframework.guru/spring-boot-web-application-part-2-using-thymeleaf/
+- https://springframework.guru/using-logback-spring-boot/
+- https://www.youtube.com/watch?v=KmxoQRnMLfE
+
+spring-boot-starter-actuator: https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html
+
+CharacterEncodingFilter : http://stackoverflow.com/a/23051264/548473
+
2. Profiles.
3. Add H2. WebServer/TcpServer
4. Model User/Role. Repository UserRepository.
@@ -64,6 +62,18 @@ http://mtdevuk.com/2015/02/10/how-to-deploy-a-spring-boot-application-to-amazon-
- Deploy spring boot application to amazon elastic beanstalk
- Spring Cloud AWS
+http://eax.me/amazon-one-year/
+
+SES: https://aws.amazon.com/ru/ses/faqs/
+
+Remote git via SSH:
+git via ssh: http://stackoverflow.com/a/17307628/548473
+git ssh url syntax: http://stackoverflow.com/a/39841058/548473
+http://stackoverflow.com/questions/11117823/git-push-error-refusing-to-update-checked-out-branch
+git push non-bare repository: http://stackoverflow.com/a/28262104/548473
+
+[Change Timezone](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/set-time.html#change_time_zone)
+
## Static resources
http://www.baeldung.com/spring-mvc-static-resources
@@ -79,8 +89,8 @@ Run at 80 port: http://stackoverflow.com/questions/33703965/spring-boot-running-
cat /etc/init.d/nginx
`Ctrl+D (exit)`
-# config: /etc/nginx/nginx.conf
-# config: /etc/sysconfig/nginx
+config: /etc/nginx/nginx.conf
+config: /etc/sysconfig/nginx
cat /etc/sysconfig/nginx
cat /etc/nginx/nginx.conf
@@ -103,6 +113,7 @@ namei -om /home/ec2-user/javaops/static/index.html
How do I run a Unix process in the background?
+- Startup scripts
## External properties
http://www.javabeat.net/spring-boot-external-configurations/
@@ -130,6 +141,14 @@ additional-spring-configuration-metadata.json
## OAuth2
https://github.com/spring-cloud-samples/authserver
+http://oauthbible.com/
+
+1. Create app
+- [Registering OAuth Apps]https://developer.github.com/apps/building-integrations/setting-up-and-registering-oauth-apps/
+ - [OAuth applications](https://github.com/settings/developers)
+
+
+
## Execution and Scheduling
CompletionService over an ExecutorService
@@ -192,6 +211,9 @@ http://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf.html#unescaped-text
Inlining
http://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf.html#inlining
+Href
+http://www.thymeleaf.org/doc/articles/standardurlsyntax.html
+
### Using multiple template resolvers
http://blog.kaczmarzyk.net/2015/01/04/loading-view-templates-from-database-with-thymeleaf/
http://stackoverflow.com/questions/26609226/using-multiple-template-resolvers-with-spring-3-2-and-thymeleaf-2-1-3-for-emails
@@ -236,10 +258,119 @@ https://dzone.com/articles/spring-caching-abstraction-and
## Logging
https://docs.spring.io/spring-boot/docs/current/reference/html/howto-logging.html
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-logging.html#boot-features-logging-file-output
+http://blog.codeleak.pl/2017/03/spring-boot-configure-log-level-in.html
## Error handling
http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-error-handling
-org.springframework.web.servlet.DispatcherServlet.getHandler #1115
\ No newline at end of file
+org.springframework.web.servlet.DispatcherServlet.getHandler #1115
+
+## stormpath
+https://devcenter.heroku.com/articles/stormpath
+
+## encoding
+http://stackoverflow.com/questions/24054648/how-to-config-characterencodingfilter-in-springboot
+
+## UI:
+GWT Toolkit
+
+
+https://ru.wikipedia.org/wiki/Веб-компоненты
+
+https://github.com/vaadin/gwt-polymer-elements
+
+Веб-компоненты
+http://frontender.info/shadowdom/
+
+Building a modern GWT app using Polymer Elements
+http://www.gwtproject.org/doc/latest/polymer-tutorial/introduction.html
+
+http://stackoverflow.com/questions/28564438/spring-boot-gwt-embedded-configuraiton
+https://github.com/Ekito/spring-boot-gwt
+https://github.com/feedm3/spring-boot-gwt
+
+Создаем приложение с помощью Spring и GWT.
+http://alextretyakov.blogspot.ru/2011/10/4.html
+
+http://www.springbyexample.org/static/1.1/html/simple-gwt-spring-webapp.html
+
+## Slack
+https://api.slack.com/web
+https://api.slack.com/docs/oauth-test-tokens
+http://stackoverflow.com/questions/30955818/slack-api-team-invitation
+https://spring.io/blog/2009/03/27/rest-in-spring-3-resttemplate
+
+Spring-jdbc: https://www.javacodegeeks.com/2016/03/springboot-working-jdbctemplate.html
+
+## Google Apps Admin SDK Directory API
+[Explorer](https://developers.google.com/admin-sdk/directory/v1/reference/members/list)
+[QuickStart](https://developers.google.com/admin-sdk/directory/v1/quickstart/java)
+[Service Accounts](https://console.developers.google.com/iam-admin/serviceaccounts/project)
+[Group mail](https://groups.google.com/a/javaops.ru/forum/#!groupsettings/masterjava/information)
+[Delegating domain-wide authority to the service account](https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority)
+[Управление доступом клиента API](https://admin.google.com/AdminHome?chromeless=1#OGX:ManageOauthClients)
+
+
+## Hot Swapping
+http://docs.spring.io/spring-boot/docs/current/reference/html/howto-hotswapping.html
+https://patrickgrimard.io/2016/01/18/spring-boot-devtools-first-look/
+https://www.youtube.com/watch?v=VWF7vCJSqrA : spring-boot-devtools
+https://www.leveluplunch.com/java/tutorials/004-hot-deploy-java-applications-with-spring-loaded/
+
+-----------
+## H2
+- H2 TCP connection
+
+## Spring Boot
+- https://habrahabr.ru/post/257223/
+- Spring Boot and Intellij IDEA 14
+- https://github.com/snicoll-demos/spring-boot-intellij-idea-webinar
+- Spring Boot Reference Guide
+- spring-projects/spring-boot
+- Building REST services with Spring
+- Common application properties
+- Multiple external configuration
+http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-logging.html
+
+## REST
+- http://curl.haxx.se/docs/manpage.html
+- http://spring.io/guides/gs/accessing-data-rest/
+- https://github.com/spring-guides/gs-accessing-data-rest
+
+org\springframework\web\servlet\DispatcherServlet.java
+ mappedHandler = getHandler(processedRequest)
+
+org.springframework.data.rest.core.mapping.ResourceMetadata
+ for (ResourceMetadata metadata : cache.values()) {
+- Spring Data REST now comes with ALPS metadata
+- HAL: https://tools.ietf.org/html/draft-kelly-json-hal-07
+
+## ETag
+- https://objectpartners.com/2015/06/02/etags-and-spring-data-rest/
+- http://stackoverflow.com/questions/31882180/why-is-the-version-property-not-set-with-spring-data-jpa
+
+
+## ID
+- https://github.com/spring-projects/spring-hateoas/issues/66
+- https://github.com/spring-projects/spring-hateoas/issues/67
+- https://github.com/gregturn/task-manager-app
+- http://stackoverflow.com/questions/24936636/while-using-spring-data-rest-after-migrating-an-app-to-spring-boot-i-have-obser
+- http://stackoverflow.com/questions/24839760/spring-boot-responsebody-doesnt-serialize-entity-id
+
+## JSON
+https://github.com/spring-projects/spring-hateoas/issues/333
+
+## Projects
+https://github.com/spring-projects/spring-data-rest
+https://github.com/spring-projects/spring-hateoas
+https://en.wikipedia.org/wiki/HATEOAS
+http://translate.academic.ru/hypermedia/en/ru/
+http://stackoverflow.com/questions/19514131/spring-hateoas-versus-spring-data-rest/19516776
+https://ru.wikipedia.org/wiki/Список_кодов_состояния_HTTP
+https://github.com/spring-projects/spring-data-examples/tree/master/rest/
+
+## Bugs
+http://stackoverflow.com/questions/17277078/spring-mvc-exception-when-using-responsebody-and-entity-with-circular-referenc
+http://stackoverflow.com/questions/8966030/hibernate-jpa-import-sql-utf8-characters-corrupted
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 06a7378..02edfbb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,7 +14,7 @@
org.springframework.boot
spring-boot-starter-parent
- 1.3.2.RELEASE
+ 1.5.3.RELEASE
@@ -41,7 +41,25 @@
org.springframework.boot
spring-boot-starter-thymeleaf
+
+
+ nz.net.ultraq.thymeleaf
+ thymeleaf-layout-dialect
+
+
+
org.springframework.boot
spring-boot-starter-web
@@ -65,12 +83,17 @@
spring-boot-configuration-processor
true
+
+
+ com.google.apis
+ google-api-services-admin-directory
+ directory_v1-rev76-1.22.0
+
-
- org.pegdown
- pegdown
- 1.6.0
+ org.jsoup
+ jsoup
+ 1.10.1
@@ -88,7 +111,7 @@
com.google.guava
guava
- 19.0
+ 21.0
@@ -101,6 +124,20 @@
com.fasterxml.jackson.datatype
jackson-datatype-jsr310
+
+
+ org.projectlombok
+ lombok
+ 1.16.14
+
+
+
@@ -109,6 +146,14 @@
org.springframework.boot
spring-boot-maven-plugin
+
diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..07ae2fa
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,49 @@
+https://api.travis-ci.org/gkislin/javaops.svg?branch=master
+
+## Разработка сайта для Java проектов http://javaops.ru
+
+[](https://www.codacy.com/app/gkislin/javaops)
+[](https://travis-ci.org/gkislin/javaops)
+[](https://dependencyci.com/github/gkislin/javaops)
+[](https://codebeat.co/projects/github-com-gkislin-javaops)
+
+### Стек:
+- Spring Boot
+- H2
+- Thymeleaf
+- Рассмаривается на кандидаты в UI:
+ - https://vaadin.com/elements
+ - https://www.sencha.com/products/gxt
+
+### Задачи:
+- Рассылка сообщений в slack: https://api.slack.com/interactive-messages
+SSL: https://www.emaro-ssl.ru/shop/Comodo/positive-ssl/ - 690р в год.
+Есть бесплатные с пробным периодом 1-3 месяца. Но вижу бесплатные и на 2 года, что странно https://www.startcomca.com/
+Ограничения самого дешевого сертификата: 1 домен example.com и 1 поддомен www.example.com, но у каждого разные правила
+Сертификат заказывается для доменного имени, поэтому при заказе сразу понадобиться либо почта admin@example.com, либо на свой хостинг положить файл, чтобы доказать, что доменное имя принадлежат тебе. См. другие способы валидации https://thehost.ua/wiki/SSL
+Далее Comodo или другой сертификационный центр присылает сертификат на домен и пачку ssl-рутовых - всё это добро я скармливал nginx, а под ним tomcat.
+Потом там начинаются проблемы с редиректами для логина на google.com/fb.com/vk.com
+С этим всем можно 2 недели провозиться. Первый раз я пробовал всё настраивать на тестовом домене и хостинге.
+emaro-ssl.ru
+
+https://thehost.ua/wiki/SSL
+https://www.emaro-ssl.ru/shop/Comodo/positive-ssl/
+
+
+### Работа:
+ Создать пустой ./config/sql.properties
+ Закомментировать GoogleAdminSDKDirectoryService.init()
+
+ Запуск: `mvn spring-boot:run`
+
+ Коннект к базе (только 1 коннект возможен):
+
+ - профиль **prod** (`\config\application-prod.yaml`, не чекинится в репозиторий)
+ - приложение не работает `jdbc:h2:file:~/db/javaops`
+ - приложение работает: `jdbc:h2:tcp://localhost:9092/~/db/javaops`
+
+ - профиль **dev**
+ - `jdbc:h2:tcp://localhost:9092/mem:javaops`
+
+ - Общение в https://javaops.slack.com/messages/javaops_ru/
+
diff --git a/resources/activation.html b/resources/activation.html
deleted file mode 100644
index 0ceb034..0000000
--- a/resources/activation.html
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
- Изменение подписки
-
-
-
-
-
-
-
-
-
-
- Ваша подписка выключена.
-
-
-
-
-
-
diff --git a/resources/css/style.css b/resources/css/style.css
index eda44b9..3c92aab 100644
--- a/resources/css/style.css
+++ b/resources/css/style.css
@@ -1,5 +1,113 @@
.box {
- padding: 50px;
text-align: center;
vertical-align: middle;
+ align-content: center;
+}
+
+.pad, .box {
+ padding-top: 70px;
+}
+
+.container {
+ width: 1170px !important;
+}
+
+.bs-callout {
+ padding: 5px 20px;
+}
+
+.align_left, .dataTables_filter {
+ text-align: left !important;
+}
+
+.align_center {
+ text-align: center;
+}
+
+footer {
+ border-top: 1px solid #eee;
+ width: 1170px;
+ max-width: 100%;
+ margin-left: auto;
+ margin-right: auto;
+ padding: 15px;
+ font-size: 75%;
+ color: #CCC;
+}
+
+.nav-bgr {
+ background-color: #293a48;
+}
+
+a[href^="mailto:"] {
+ padding-left: 20px !important;
+ background: url(../static/img/email.png) no-repeat center left;
+ }
+
+a[href^="https://vk.com"]:not(.waves-effect), .vk {
+ padding-left: 20px !important;
+ background: url(../static/img/vk.gif) no-repeat center left;
+}
+
+a[href^="https://tproger.ru"] {
+ padding-left: 20px !important;
+ background: url(../static/img/tprg.ico) no-repeat center left;
+}
+
+a[href^="https://www.youtube.com"]:not(.waves-effect), .video {
+ padding-left: 20px !important;
+ background: url(../static/img/youtube.ico) no-repeat center left;
+}
+
+a[href^="https://habrahabr.ru"] {
+ padding-left: 20px !important;
+ background: url(../static/img/habrahabr.png) no-repeat center left;
+}
+
+a[href^="https://stackoverflow.com"] {
+ padding-left: 20px !important;
+ background: url(../static/img/so.ico) no-repeat center left;
+}
+
+a[href^="https://www.linkedin.com"] {
+ padding-left: 20px !important;
+ background: url(../static/img/lin.png) no-repeat center left;
+}
+
+a[href*="github.com"] {
+ padding-left: 20px !important;
+ background: url(../static/img/gh.png) no-repeat center left;
+}
+
+a[href*="drive.google.com"] {
+ padding-left: 20px !important;
+ background: url(../static/img/gdrv.ico) no-repeat center left;
+}
+
+a[href*="docs.google.com"] {
+ padding-left: 20px !important;
+ background: url(../static/img/gdoc.ico) no-repeat center left;
+}
+
+a[href*="yadi.sk"] {
+ padding-left: 20px !important;
+ background: url(../static/img/yadi.png) no-repeat center left;
+}
+
+a[href*="hh.ru"], a[href*="hh.ua"] {
+ padding-left: 20px !important;
+ background: url(../static/img/hh.png) no-repeat center left;
+}
+
+.nav-link a{
+ padding-left: 0 !important;
+ background: none !important;
+}
+
+.anchor:target {
+ padding-top: 70px;
+}
+
+.navbar-nav .nav-link {
+ padding-right: 1em;
}
\ No newline at end of file
diff --git a/resources/exception.html b/resources/exception.html
deleted file mode 100644
index d4fbbe8..0000000
--- a/resources/exception.html
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
-
-
-
-
-
- Ошибка
-
-
-
-
-
-
-
-
-
-
-
Ошибка приложения:
-
-
403
-
message
-
-
-
-
\ No newline at end of file
diff --git a/resources/fragments.html b/resources/fragments.html
deleted file mode 100644
index 1cdd5f6..0000000
--- a/resources/fragments.html
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/resources/habr/fistJob.html b/resources/habr/fistJob.html
new file mode 100644
index 0000000..98ceabe
--- /dev/null
+++ b/resources/habr/fistJob.html
@@ -0,0 +1,110 @@
+https://dou.ua/add-post/
+
+
+
+ Из юниоров в разработчики: получаем первую работу.
+
+
+
+Здравствуйте! Коротко о себе: программирую с 1989 г., с 2005 года в Java, с 2013 года работаю Java-тренером (до января этого года совмещал с основной работой Java-разработчика). Достаточно много моих выпускников трудоустроились, и я хочу поделится своими соображениями, как получить работу Java-разработчика (и не только Java).
+
+От изучения Java до получения оффера работы - большое расстояние
+Требования к кандидатам на вакансию Java разработчика достаточно высоки, см. пример тестового задания на джуниора от одного из аутсорсеров РБ . Конечно есть позиции и с меньшими требованиям, но их не так много и, по статистике на Украине (dou работает через прокси, в Росии не нашел), соотношение Отклики/Вакансии на такие позиции: от 20 до 50.
+
+Для вакансий с опытом работы (которых значительно больше) получается замкнутый круг: без опыта не получить работы, а без работы не получить опыта. На вопрос "Кто виноват?" ответ очевиден - компании, которые не хотят вкладывать время и деньги в обучение, а хотят получить уже готового специалиста. Остается главный вопрос:
+
+Что делать?
+
+Крупные компании в основном закрывают позиции юниоров своими стажерами . Один из вариантов трудоустройства - пойти на стажировку, но
+
+
+ здесь также большой конкурс
+ далеко не все, успешно окнончившие стажировку, получают работу
+ иногда условия обучения достаточно тяжелые и подойдут не всем. Из отзыва про стажировку в EPAMе РБ:Там все настолько жутко строго, что я до сих пор в шоке. У них там сильный отбор... все оценивается, дз, тесты, устные опросы, ну и в конце защита своего проекта. Нам назначают таски и ставят дедлайны. Не успел залить таск - все, до свиданья... Чувствую себя как в школе... Вплоть до того что у нас есть список из 200-230 вопросов примерно по всем темам, которые мы должны знать без запинки. Конспекты ведем(!), на каждый вопрос письменный ответ и это проверяется... Епам себе дрессирует программистов) по другому и не скажешь...
+Шаги другого варианта хорошо знакомы (отличное видео Якова Фейна "Как стать профессиональным Java разработчиком "):
+
+
+ Хорошее резюме
+ Приглашения на собеседования и тренировка в их прохождении
+ Получение оффера
+
+Хорошее (выделяющееся) резюме означает, что его замечает HR и отправляет вам приглашение на собеседование.
+
+В интернете есть большое количество рекомендаций, как этого добиться:
+
+
+Но, на мой взгляд, главное:
+
+Позиционируйте себя НЕ как юниора.
+Для этого необходимо:
+
+
+ Хорошее понимание основ: как устроена память , что
+ такое JMM , опыт работы с сервлетами, JUnit, SQL
+
+ Уровень выше Java Core: основы Maven, Spring (MVC, Security, Test), JPA(Hibernate), REST. Также желательно основы
+ JavaScript и HTML/CSS
+
+
+Материалов по Java фреймворкам и технологиям в интернете много. Но если вы хотите их освоить, а не прочитать/посмотреть и забыть, необходимо написать на них собственный пэт-проект . Это может быть проект домашней библиотеки или бухгалтерии, или кормления кота или... Хорошо, если в нем будет реальная потребность - тогда при его эксплуатации вы постепенно будете приходить к оптимальным решениям.
+
+Лучше всего делать его на основе небольшого проекта на популярном стеке, например референсной имплементации Spring Pet clinic . С первого раза сделать код красивым и правильным не подсилу даже синьору. Проект должен жить и нести его владельцу радость приобщения к красоте кода через рефакторинг. И, кроме понимания технолигий и развития чувства перкрасного, из работы над собственным проектом Вы получаете навыки нахождения красивых и практических решений для конкретных задач и решения конкретных проблем , из которых состоит ежедневная работа программиста. Для этого нужно:
+
+
+ понимание, как работают фреймворки, на чем они основаны, какие паттерны используются
+ кругозор, навыки решения подобных задач
+ умение находить правильные решения в интернете (70-80% это умение выбрать из найденного в Stackoverflow )
+
+Эта задача непростая и, если знаний, опыта, времени недостаточно, рекомендую пройти какой-нибудь тренинг Java Enterprise на этом стеке, обязательно с написанием проекта на основе пройденных технологий на выходе. Мои критерии тренинга:
+
+
+ Ведет преподаватель с опытом в Java разработке, лучше как синьор или архитектор
+ Максимальный охват: самые важные и необходимые Java разработчику темы, API, фреймворки, инструменты в одном курсе.
+
+ В течении тренинга разрабатывается законченный Enterprise проект. Темы идут не по отдельности (в воздухе) на отстраненных примерах, а последовательно, в связке, как дополнения к созданию единого работающего приложения.
+ Последовательное возрастание сложности: от нуля до деплоя готового приложения в облако
+ Практика! Участники на протяжении всего курса должны работать с кодом проекта. Объязательны домашние задания. Если дают только теорию (всего понемногу), то это, на мой взгляд, выброшенные деньги и время. Без практики любое обучение (Java, английский, езда на велосипеде) ничего не стоит.
+ Поддержка группы и преподавателя: возможность задать любой вопрос и получить на него квалифицированный ответ.
+ Доступность и структурированность материалов
+ Ревью Вашего кода.
+ Помощь в составлении резюме и с трудоустройством. Если вам гарантируют по окончанию 100% трудоустройство - не верьте. Хорошо сказано в статье про работу разработчика :
+ Работа программиста – не столько профессия, сколько образ жизни. Обучение в университете, самообразование, хобби и, что немаловажно, страсть – ключевые составляющие успеха в этой сфере.
+
+После того, как у Вас будет опыт в собственном Java Enterprise проекте,
+
+Сделайте новое резюме:
+Типичное резюме Java юниора начинается так:
+Начать карьеру как junior Java developer в современной, перспективной компании, чтобы через 3 года стать специалистом...
+ Хорошо обучаем...
+ Оптыт работы: отсутствует
+ Прошел курсы...
+Нужно:
+
+
+ уберать слова "начать карьеру", "юниор" и "готов к обучению"
+ вставить в квалификацию все изученные вами технологии
+ в опыте работы написать об участие в проекте с его кратким описанием
+
+Например, ОПЫТ РАБОТЫ:
+Участие в разработке Spring/JPA Enterprise приложения c авторизацией и правами доступа на основе ролей на стеке Maven/ Spring MVC/ Security/ REST(Jackson)/ Java 8 Stream API:
+
+
+ реализация сохранения в базы Postgres и HSQLDB на основе Spring JBDC, JPA(Hibernate) и Spring-Data-JPA
+ реализация и тестирование REST и AJAX контроллеров
+ реализация клиента на Bootstrap (css/js), datatables, jQuery + plugins.
+
+С таким резюме вы можете не бояться обращаться на вакансии с требованием 1-2 года опыта и, возможно, пройдете на следующий уровень: "Приглашения на собеседования и тренировка в их прохождении", что уже требует отдельной статьи.
+
+Спасибо за внимание и желаю отличной карьеры в IT .
+