├── .gitignore ├── .metadata ├── .lock ├── .log ├── .mylyn │ └── repositories.xml.zip ├── .plugins │ ├── org.eclipse.core.resources │ │ ├── .root │ │ │ ├── .indexes │ │ │ │ ├── history.version │ │ │ │ ├── properties.index │ │ │ │ └── properties.version │ │ │ └── 1.tree │ │ └── .safetable │ │ │ └── org.eclipse.core.resources │ ├── org.eclipse.e4.workbench │ │ └── workbench.xmi │ ├── org.eclipse.epp.logging.aeri.ide │ │ └── com.genuitec.eclipse.aeri.server1 │ │ │ ├── http-cache.lucene60 │ │ │ ├── segments_1 │ │ │ └── write.lock │ │ │ ├── local-history.lucene60 │ │ │ ├── _0.cfe │ │ │ ├── _0.cfs │ │ │ ├── _0.si │ │ │ ├── segments_1 │ │ │ └── write.lock │ │ │ └── server-config.json │ ├── org.eclipse.jdt.core │ │ ├── assumedExternalFilesCache │ │ ├── externalFilesCache │ │ ├── index.db │ │ ├── javaLikeNames.txt │ │ ├── nonChainingJarsCache │ │ └── variablesAndContainers.dat │ ├── org.eclipse.jdt.ui │ │ ├── OpenTypeHistory.xml │ │ ├── QualifiedTypeNameHistory.xml │ │ └── dialog_settings.xml │ ├── org.eclipse.m2e.core │ │ ├── nexus │ │ │ ├── 05b0fe8524860bd73cbb07ef30fb34cc │ │ │ │ ├── _0.cfs │ │ │ │ ├── segments.gen │ │ │ │ ├── segments_2 │ │ │ │ └── write.lock │ │ │ ├── 524abec12001e0d138ee468a3c5739cf │ │ │ │ ├── _0.cfs │ │ │ │ ├── segments.gen │ │ │ │ ├── segments_2 │ │ │ │ └── write.lock │ │ │ └── 830bc118332e77292949ed1e6d2fabe0 │ │ │ │ ├── _0.cfs │ │ │ │ ├── segments.gen │ │ │ │ ├── segments_2 │ │ │ │ └── write.lock │ │ └── workspaceState.ser │ ├── org.eclipse.m2e.logback.configuration │ │ └── logback.1.8.2.20171007-0217.xml │ ├── org.eclipse.mylyn.github.ui │ │ └── avatars.ser │ ├── org.eclipse.oomph.setup │ │ └── workspace.setup │ ├── org.eclipse.pde.core │ │ └── .cache │ │ │ └── clean-cache.properties │ ├── org.eclipse.rse.core │ │ ├── .log │ │ ├── initializerMarks │ │ │ └── org.eclipse.rse.internal.core.RSELocalConnectionInitializer.mark │ │ └── profiles │ │ │ └── PRF.vacsal52848_2016 │ │ │ ├── FP.local.files_0 │ │ │ └── node.properties │ │ │ ├── H.local_16 │ │ │ └── node.properties │ │ │ └── node.properties │ ├── org.eclipse.rse.ui │ │ └── .log │ ├── org.eclipse.ui.ide │ │ └── dialog_settings.xml │ ├── org.eclipse.ui.workbench │ │ └── dialog_settings.xml │ ├── org.eclipse.ui │ │ └── dialog_settings.xml │ ├── org.springframework.ide.eclipse.aop.core │ │ └── .state │ ├── org.springframework.ide.eclipse.beans.core.metadata │ │ ├── metadata │ │ │ └── .state │ │ └── properties │ │ │ └── .state │ ├── org.springsource.ide.eclipse.commons.gettingstarted │ │ └── dashboard │ │ │ └── 1522593921848 │ │ │ ├── common │ │ │ ├── bootstrap-datetimepicker │ │ │ │ └── js │ │ │ │ │ └── bootstrap-datetimepicker.min.js │ │ │ ├── bootstrap │ │ │ │ ├── css │ │ │ │ │ ├── bootstrap.css │ │ │ │ │ └── bootstrap.min.js │ │ │ │ └── js │ │ │ │ │ ├── bootstrap-datetimepicker │ │ │ │ │ └── js │ │ │ │ │ │ └── bootstrap-datetimepicker.min.js │ │ │ │ │ └── bootstrap.min.js │ │ │ ├── css │ │ │ │ ├── application.css │ │ │ │ ├── blog.css │ │ │ │ ├── buttons.css │ │ │ │ ├── dashboard.css │ │ │ │ ├── docs.css │ │ │ │ ├── flexbox.css │ │ │ │ ├── font-awesome.css │ │ │ │ ├── fontcustom.css │ │ │ │ ├── highlight.css │ │ │ │ ├── homepage.css │ │ │ │ ├── icons.css │ │ │ │ ├── main.css │ │ │ │ ├── markdown-content.css │ │ │ │ ├── panes.css │ │ │ │ ├── projects.css │ │ │ │ ├── responsive.css │ │ │ │ ├── tools.css │ │ │ │ └── typography.css │ │ │ ├── font-awesome │ │ │ │ └── css │ │ │ │ │ └── font-awesome.css │ │ │ ├── font-custom │ │ │ │ └── fontcustom.woff │ │ │ ├── img │ │ │ │ ├── blog.png │ │ │ │ ├── blog_32.png │ │ │ │ ├── bug_32.png │ │ │ │ ├── comparison_32.png │ │ │ │ ├── compass.png │ │ │ │ ├── compass_32.png │ │ │ │ ├── extension.png │ │ │ │ ├── extension_32.png │ │ │ │ ├── favicon.png │ │ │ │ ├── forum.png │ │ │ │ ├── forum_32.png │ │ │ │ ├── guides.png │ │ │ │ ├── guides_32.png │ │ │ │ ├── loading.gif │ │ │ │ ├── logo_bigleaf.png │ │ │ │ ├── logo_spring.png │ │ │ │ ├── logo_sts.png │ │ │ │ ├── new_32.png │ │ │ │ ├── overlay-incoming.png │ │ │ │ ├── question.png │ │ │ │ ├── spring-logo.png │ │ │ │ ├── springdocs.png │ │ │ │ └── springdocs_32.png │ │ │ └── js │ │ │ │ ├── application.js │ │ │ │ ├── filter.js │ │ │ │ ├── guide.js │ │ │ │ ├── jquery.js │ │ │ │ └── modernizer.flexbox.js │ │ │ └── index.html │ └── org.springsource.ide.eclipse.dashboard.ui │ │ └── feeds │ │ ├── dashboard.feeds.blogs │ │ └── -549550714.xml │ │ └── dashboard.feeds.update │ │ └── 623127801.xml └── version.ini ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── README.md ├── mvnw ├── mvnw.cmd ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── appsdeveloperblog │ │ └── app │ │ └── ws │ │ ├── MobileAppWsApplication.java │ │ ├── SpringApplicationContext.java │ │ ├── SwaggerConfig.java │ │ ├── WebConfig.java │ │ ├── exceptions │ │ ├── AppExceptionsHandler.java │ │ └── UserServiceException.java │ │ ├── io │ │ ├── entity │ │ │ ├── AddressEntity.java │ │ │ ├── PasswordResetTokenEntity.java │ │ │ └── UserEntity.java │ │ └── repository │ │ │ ├── AddressRepository.java │ │ │ ├── PasswordResetTokenRepository.java │ │ │ └── UserRepository.java │ │ ├── security │ │ ├── AppProperties.java │ │ ├── AuthenticationFilter.java │ │ ├── AuthorizationFilter.java │ │ ├── SecurityConstants.java │ │ └── WebSecurity.java │ │ ├── service │ │ ├── AddressService.java │ │ ├── UserService.java │ │ └── impl │ │ │ ├── AddressServiceImpl.java │ │ │ └── UserServiceImpl.java │ │ ├── shared │ │ ├── AmazonSES.java │ │ ├── Utils.java │ │ └── dto │ │ │ ├── AddressDTO.java │ │ │ └── UserDto.java │ │ └── ui │ │ ├── contoller │ │ ├── AuthenticationController.java │ │ ├── RequestOperationName.java │ │ └── UserController.java │ │ └── model │ │ ├── request │ │ ├── AddressRequestModel.java │ │ ├── LoginRequestModel.java │ │ ├── PasswordResetModel.java │ │ ├── PasswordResetRequestModel.java │ │ ├── UserDetailsRequestModel.java │ │ └── UserLoginRequestModel.java │ │ └── response │ │ ├── AddressesRest.java │ │ ├── ErrorMessage.java │ │ ├── ErrorMessages.java │ │ ├── OperationStatusModel.java │ │ ├── RequestOperationStatus.java │ │ └── UserRest.java ├── resources │ └── application.properties └── webapp │ └── META-INF │ └── context.xml └── test └── java └── com └── appsdeveloperblog └── app └── ws ├── MobileAppWsApplicationTests.java ├── io └── repository │ └── UserRepositoryTest.java ├── service └── impl │ └── UserServiceImplTest.java ├── shared └── UtilsTest.java └── ui └── controller └── UserControllerTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | nbproject/private/ 21 | build/ 22 | nbbuild/ 23 | dist/ 24 | nbdist/ 25 | .nb-gradle/ -------------------------------------------------------------------------------- /.metadata/.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.lock -------------------------------------------------------------------------------- /.metadata/.log: -------------------------------------------------------------------------------- 1 | !SESSION 2018-04-01 07:44:57.229 ----------------------------------------------- 2 | eclipse.buildId=3.9.2.201712210947-RELEASE-e47 3 | java.version=1.8.0_162 4 | java.vendor=Oracle Corporation 5 | BootLoader constants: OS=macosx, ARCH=x86_64, WS=cocoa, NL=en_CA 6 | Framework arguments: -product org.springsource.sts.ide -keyring /Users/skargopolov/.eclipse_keyring 7 | Command-line arguments: -os macosx -ws cocoa -arch x86_64 -product org.springsource.sts.ide -keyring /Users/skargopolov/.eclipse_keyring 8 | 9 | !ENTRY org.eclipse.ui 2 0 2018-04-01 07:45:16.032 10 | !MESSAGE Warnings while parsing the images from the 'org.eclipse.ui.commandImages' extension point. 11 | !SUBENTRY 1 org.eclipse.ui 2 0 2018-04-01 07:45:16.032 12 | !MESSAGE Cannot bind to an undefined command: plug-in='org.eclipse.lsp4e', id='org.eclipse.lsp4e.togglehighlight' 13 | 14 | !ENTRY org.eclipse.jface 2 0 2018-04-01 07:45:17.835 15 | !MESSAGE Keybinding conflicts occurred. They may interfere with normal accelerator operation. 16 | !SUBENTRY 1 org.eclipse.jface 2 0 2018-04-01 07:45:17.835 17 | !MESSAGE A conflict occurred for COMMAND+SHIFT+T: 18 | Binding(COMMAND+SHIFT+T, 19 | ParameterizedCommand(Command(org.eclipse.jdt.ui.navigate.open.type,Open Type, 20 | Open a type in a Java editor, 21 | Category(org.eclipse.ui.category.navigate,Navigate,null,true), 22 | org.eclipse.ui.internal.WorkbenchHandlerServiceHandler@8961e55, 23 | ,,true),null), 24 | org.eclipse.ui.defaultAcceleratorConfiguration, 25 | org.eclipse.ui.contexts.window,,,system) 26 | Binding(COMMAND+SHIFT+T, 27 | ParameterizedCommand(Command(org.eclipse.lsp4e.symbolinworkspace,Go to Symbol in Workspace, 28 | , 29 | Category(org.eclipse.lsp4e.category,Language Servers,null,true), 30 | org.eclipse.ui.internal.WorkbenchHandlerServiceHandler@67eabe02, 31 | ,,true),null), 32 | org.eclipse.ui.defaultAcceleratorConfiguration, 33 | org.eclipse.ui.contexts.window,,,system) 34 | 35 | !ENTRY org.eclipse.ui 2 2 2018-04-01 07:45:18.977 36 | !MESSAGE org.eclipse.jdt.junit.ResultView: Deprecated relationship "fast" should be converted to "stack". 37 | 38 | !ENTRY org.eclipse.ui 2 2 2018-04-01 07:45:18.986 39 | !MESSAGE org.springframework.ide.eclipse.aop.ui.navigator.aopReferenceModelNavigator: Deprecated relationship "fast" should be converted to "stack". 40 | 41 | !ENTRY org.eclipse.ui 2 2 2018-04-01 07:45:18.986 42 | !MESSAGE org.eclipse.contribution.xref.ui.views.XReferenceView: Deprecated relationship "fast" should be converted to "stack". 43 | 44 | !ENTRY org.eclipse.jface.text 2 0 2018-04-01 07:45:19.840 45 | !MESSAGE Duplicate template id: 'org.eclipse.wst.xslt.templates.xpath.number' 46 | 47 | !ENTRY org.eclipse.jface.text 2 0 2018-04-01 07:45:19.846 48 | !MESSAGE Duplicate template id: 'org.eclipse.wst.xslt.templates.xpath.round' 49 | 50 | !ENTRY org.springsource.ide.eclipse.commons.browser 4 0 2018-04-01 07:45:23.169 51 | !MESSAGE Could not call browser function extension: addHtml 52 | !STACK 0 53 | org.eclipse.core.commands.ExecutionException: Problems executing script: 'window.addHtml("gettingStarted", "Import Getting Started Guide\nImport Reference App\n")' 54 | at org.springsource.ide.eclipse.commons.browser.swt.StsBrowserManager.lambda$0(StsBrowserManager.java:147) 55 | at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:37) 56 | at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:182) 57 | at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:4034) 58 | at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3701) 59 | at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1150) 60 | at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:336) 61 | at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1039) 62 | at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:153) 63 | at org.eclipse.ui.internal.Workbench.lambda$3(Workbench.java:680) 64 | at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:336) 65 | at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:594) 66 | at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:148) 67 | at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:151) 68 | at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196) 69 | at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:134) 70 | at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:104) 71 | at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:388) 72 | at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:243) 73 | at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 74 | at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 75 | at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 76 | at java.lang.reflect.Method.invoke(Method.java:498) 77 | at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:653) 78 | at org.eclipse.equinox.launcher.Main.basicRun(Main.java:590) 79 | at org.eclipse.equinox.launcher.Main.run(Main.java:1499) 80 | 81 | !ENTRY org.eclipse.epp.logging.aeri.ide 2 17 2018-04-01 07:45:31.687 82 | !MESSAGE Server ‘org.eclipse.epp.logging.aeri.ide.server’ failed with exception: Read timed out. ; version: 2.0.6.v20170906-1226 83 | !STACK 0 84 | java.net.SocketTimeoutException: Read timed out 85 | at java.net.SocketInputStream.socketRead0(Native Method) 86 | at java.net.SocketInputStream.socketRead(SocketInputStream.java:116) 87 | at java.net.SocketInputStream.read(SocketInputStream.java:171) 88 | at java.net.SocketInputStream.read(SocketInputStream.java:141) 89 | at sun.security.ssl.InputRecord.readFully(InputRecord.java:465) 90 | at sun.security.ssl.InputRecord.read(InputRecord.java:503) 91 | at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:983) 92 | at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:940) 93 | at sun.security.ssl.AppInputStream.read(AppInputStream.java:105) 94 | at org.apache.http.impl.io.SessionInputBufferImpl.streamRead(SessionInputBufferImpl.java:137) 95 | at org.apache.http.impl.io.SessionInputBufferImpl.fillBuffer(SessionInputBufferImpl.java:153) 96 | at org.apache.http.impl.io.SessionInputBufferImpl.readLine(SessionInputBufferImpl.java:282) 97 | at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:140) 98 | at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:57) 99 | at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:259) 100 | at org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:163) 101 | at org.apache.http.impl.conn.CPoolProxy.receiveResponseHeader(CPoolProxy.java:167) 102 | at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:273) 103 | at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:125) 104 | at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:271) 105 | at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184) 106 | at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88) 107 | at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) 108 | at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184) 109 | at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82) 110 | at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:55) 111 | at org.apache.http.client.fluent.Request.internalExecute(Request.java:173) 112 | at org.apache.http.client.fluent.Executor.execute(Executor.java:262) 113 | at org.eclipse.epp.internal.logging.aeri.ide.server.mars.IO.request(IO.java:170) 114 | at org.eclipse.epp.internal.logging.aeri.ide.server.mars.IO.refreshConfiguration(IO.java:64) 115 | at org.eclipse.epp.internal.logging.aeri.ide.server.mars.ServerConnection.startUp(ServerConnection.java:124) 116 | at com.google.common.util.concurrent.AbstractIdleService$DelegateService$1.run(AbstractIdleService.java:62) 117 | at com.google.common.util.concurrent.Callables$4.run(Callables.java:122) 118 | at java.lang.Thread.run(Thread.java:748) 119 | -------------------------------------------------------------------------------- /.metadata/.mylyn/repositories.xml.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.mylyn/repositories.xml.zip -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/history.version: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.index: -------------------------------------------------------------------------------- 1 | /org.eclipse.core.resourcescontentCacheState1contentCacheTimestamp 1512696465438org.eclipse.jdt.corestateVersionNumber30 -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.version: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.core.resources/.root/1.tree: -------------------------------------------------------------------------------- 1 | org.eclipse.jdt.core -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/com.genuitec.eclipse.aeri.server1/http-cache.lucene60/segments_1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/com.genuitec.eclipse.aeri.server1/http-cache.lucene60/segments_1 -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/com.genuitec.eclipse.aeri.server1/http-cache.lucene60/write.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/com.genuitec.eclipse.aeri.server1/http-cache.lucene60/write.lock -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/com.genuitec.eclipse.aeri.server1/local-history.lucene60/_0.cfe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/com.genuitec.eclipse.aeri.server1/local-history.lucene60/_0.cfe -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/com.genuitec.eclipse.aeri.server1/local-history.lucene60/_0.cfs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/com.genuitec.eclipse.aeri.server1/local-history.lucene60/_0.cfs -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/com.genuitec.eclipse.aeri.server1/local-history.lucene60/_0.si: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/com.genuitec.eclipse.aeri.server1/local-history.lucene60/_0.si -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/com.genuitec.eclipse.aeri.server1/local-history.lucene60/segments_1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/com.genuitec.eclipse.aeri.server1/local-history.lucene60/segments_1 -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/com.genuitec.eclipse.aeri.server1/local-history.lucene60/write.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/com.genuitec.eclipse.aeri.server1/local-history.lucene60/write.lock -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/com.genuitec.eclipse.aeri.server1/server-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "v1", 3 | "title": "Spring IDE", 4 | "timestamp": 1522593922148, 5 | "ttl": 10080, 6 | "helpUrl": "https://aer.ctrlflow.com/spring-ide/help", 7 | "feedbackUrl": "https://www.codetrails.com/error-analytics/", 8 | "aboutUrl": "https://www.codetrails.com/error-analytics/", 9 | "submitUrl": "https://aer.ctrlflow.com/spring-ide/community/new", 10 | "maxReportSize": 524288, 11 | "problemsUrl": "https://aer.ctrlflow.com/downloads/spring-ide/problems.zip", 12 | "problemsTtl": 20160, 13 | "interestUrl": "https://aer.ctrlflow.com/spring-ide/community/interest", 14 | "connectTimeout": 5, 15 | "socketTimeout": 10, 16 | "acceptedProducts": [ 17 | "*" 18 | ], 19 | "acceptedPlugins": [ 20 | "*" 21 | ], 22 | "acceptedPackages": [ 23 | "ch.qos.*", 24 | "com.sun.*", 25 | "java.*", 26 | "javafx.*", 27 | "javax.*", 28 | "org.apache.*", 29 | "org.eclipse.*", 30 | "org.osgi.*", 31 | "org.slf4j.*", 32 | "org.springframework.*", 33 | "sun.*" 34 | ], 35 | "requiredPackages": [ 36 | "org.springframework.*" 37 | ], 38 | "acceptOtherPackages": true, 39 | "acceptUiFreezes": true, 40 | "ignoredStatuses": [ 41 | ":java.net.*:" 42 | ], 43 | "problemsZipLastDownloadTimestamp": 0 44 | } -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.jdt.core/assumedExternalFilesCache: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.jdt.core/externalFilesCache: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.jdt.core/index.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.plugins/org.eclipse.jdt.core/index.db -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.jdt.core/javaLikeNames.txt: -------------------------------------------------------------------------------- 1 | aj 2 | java -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.jdt.core/nonChainingJarsCache: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.jdt.core/variablesAndContainers.dat: -------------------------------------------------------------------------------- 1 | JRE_LIBJRE_SRC ASPECTJRT_LIB JRE_SRCROOT 2 | JUNIT_HOME ECLIPSE_HOMEM2_REPOJUNIT_SRC_HOME -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.jdt.ui/OpenTypeHistory.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.jdt.ui/QualifiedTypeNameHistory.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.jdt.ui/dialog_settings.xml: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 5 | 6 | 7 | 8 | 9 |
10 |
11 |
12 |
13 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/_0.cfs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/_0.cfs -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/segments.gen: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/segments.gen -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/segments_2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/segments_2 -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/write.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/write.lock -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.m2e.core/nexus/524abec12001e0d138ee468a3c5739cf/_0.cfs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.plugins/org.eclipse.m2e.core/nexus/524abec12001e0d138ee468a3c5739cf/_0.cfs -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.m2e.core/nexus/524abec12001e0d138ee468a3c5739cf/segments.gen: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.plugins/org.eclipse.m2e.core/nexus/524abec12001e0d138ee468a3c5739cf/segments.gen -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.m2e.core/nexus/524abec12001e0d138ee468a3c5739cf/segments_2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.plugins/org.eclipse.m2e.core/nexus/524abec12001e0d138ee468a3c5739cf/segments_2 -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.m2e.core/nexus/524abec12001e0d138ee468a3c5739cf/write.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.plugins/org.eclipse.m2e.core/nexus/524abec12001e0d138ee468a3c5739cf/write.lock -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_0.cfs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_0.cfs -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/segments.gen: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/segments.gen -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/segments_2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/segments_2 -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/write.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/write.lock -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.m2e.core/workspaceState.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.plugins/org.eclipse.m2e.core/workspaceState.ser -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.m2e.logback.configuration/logback.1.8.2.20171007-0217.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %date [%thread] %-5level %logger{35} - %msg%n 5 | 6 | 7 | OFF 8 | 9 | 10 | 11 | 12 | ${org.eclipse.m2e.log.dir}/0.log 13 | 14 | ${org.eclipse.m2e.log.dir}/%i.log 15 | 1 16 | 10 17 | 18 | 19 | 100MB 20 | 21 | 22 | %date [%thread] %-5level %logger{35} - %msg%n 23 | 24 | 25 | 26 | 27 | 28 | WARN 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.mylyn.github.ui/avatars.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.plugins/org.eclipse.mylyn.github.ui/avatars.ser -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.oomph.setup/workspace.setup: -------------------------------------------------------------------------------- 1 | 2 | 7 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.pde.core/.cache/clean-cache.properties: -------------------------------------------------------------------------------- 1 | #Cached timestamps 2 | #Sun Apr 01 07:47:45 PDT 2018 3 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.rse.core/.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.plugins/org.eclipse.rse.core/.log -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.rse.core/initializerMarks/org.eclipse.rse.internal.core.RSELocalConnectionInitializer.mark: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.plugins/org.eclipse.rse.core/initializerMarks/org.eclipse.rse.internal.core.RSELocalConnectionInitializer.mark -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.rse.core/profiles/PRF.vacsal52848_2016/FP.local.files_0/node.properties: -------------------------------------------------------------------------------- 1 | # RSE DOM Node 2 | 00-name=VACSAL52848\:local.files 3 | 01-type=FilterPool 4 | 03-attr.default=true 5 | 03-attr.deletable=true 6 | 03-attr.id=local.files 7 | 03-attr.nonRenamable=false 8 | 03-attr.owningParentName=null 9 | 03-attr.release=200 10 | 03-attr.singleFilterStringOnly=false 11 | 03-attr.singleFilterStringOnlyESet=false 12 | 03-attr.stringsCaseSensitive=true 13 | 03-attr.supportsDuplicateFilterStrings=false 14 | 03-attr.supportsNestedFilters=true 15 | 03-attr.type=default 16 | 06-child.00000.00-name=My Home 17 | 06-child.00000.01-type=Filter 18 | 06-child.00000.03-attr.default=false 19 | 06-child.00000.03-attr.filterType=default 20 | 06-child.00000.03-attr.id=My Home 21 | 06-child.00000.03-attr.nonChangable=false 22 | 06-child.00000.03-attr.nonDeletable=false 23 | 06-child.00000.03-attr.nonRenamable=false 24 | 06-child.00000.03-attr.promptable=false 25 | 06-child.00000.03-attr.relativeOrder=0 26 | 06-child.00000.03-attr.release=200 27 | 06-child.00000.03-attr.singleFilterStringOnly=false 28 | 06-child.00000.03-attr.stringsCaseSensitive=true 29 | 06-child.00000.03-attr.stringsNonChangable=false 30 | 06-child.00000.03-attr.supportsDuplicateFilterStrings=false 31 | 06-child.00000.03-attr.supportsNestedFilters=true 32 | 06-child.00000.06-child.00000.00-name=/Users/skargopolov/* 33 | 06-child.00000.06-child.00000.01-type=FilterString 34 | 06-child.00000.06-child.00000.03-attr.default=false 35 | 06-child.00000.06-child.00000.03-attr.string=/Users/skargopolov/* 36 | 06-child.00000.06-child.00000.03-attr.type=default 37 | 06-child.00001.00-name=Root 38 | 06-child.00001.01-type=Filter 39 | 06-child.00001.03-attr.default=false 40 | 06-child.00001.03-attr.filterType=default 41 | 06-child.00001.03-attr.id=Root 42 | 06-child.00001.03-attr.nonChangable=false 43 | 06-child.00001.03-attr.nonDeletable=false 44 | 06-child.00001.03-attr.nonRenamable=false 45 | 06-child.00001.03-attr.promptable=false 46 | 06-child.00001.03-attr.relativeOrder=0 47 | 06-child.00001.03-attr.release=200 48 | 06-child.00001.03-attr.singleFilterStringOnly=false 49 | 06-child.00001.03-attr.stringsCaseSensitive=true 50 | 06-child.00001.03-attr.stringsNonChangable=false 51 | 06-child.00001.03-attr.supportsDuplicateFilterStrings=false 52 | 06-child.00001.03-attr.supportsNestedFilters=true 53 | 06-child.00001.06-child.00000.00-name=/* 54 | 06-child.00001.06-child.00000.01-type=FilterString 55 | 06-child.00001.06-child.00000.03-attr.default=false 56 | 06-child.00001.06-child.00000.03-attr.string=/* 57 | 06-child.00001.06-child.00000.03-attr.type=default 58 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.rse.core/profiles/PRF.vacsal52848_2016/H.local_16/node.properties: -------------------------------------------------------------------------------- 1 | # RSE DOM Node 2 | 00-name=Local 3 | 01-type=Host 4 | 03-attr.description= 5 | 03-attr.hostname=LOCALHOST 6 | 03-attr.offline=false 7 | 03-attr.promptable=false 8 | 03-attr.systemType=org.eclipse.rse.systemtype.local 9 | 03-attr.type=Local 10 | 06-child.00000.00-name=Local Connector Service 11 | 06-child.00000.01-type=ConnectorService 12 | 06-child.00000.03-attr.group=Local Connector Service 13 | 06-child.00000.03-attr.port=0 14 | 06-child.00000.03-attr.useSSL=false 15 | 06-child.00000.06-child.00000.00-name=Local Files 16 | 06-child.00000.06-child.00000.01-type=SubSystem 17 | 06-child.00000.06-child.00000.03-attr.hidden=false 18 | 06-child.00000.06-child.00000.03-attr.type=local.files 19 | 06-child.00000.06-child.00000.06-child.00000.00-name=VACSAL52848___VACSAL52848\:local.files 20 | 06-child.00000.06-child.00000.06-child.00000.01-type=FilterPoolReference 21 | 06-child.00000.06-child.00000.06-child.00000.03-attr.refID=local.files 22 | 06-child.00000.06-child.00001.00-name=Local Shells 23 | 06-child.00000.06-child.00001.01-type=SubSystem 24 | 06-child.00000.06-child.00001.03-attr.hidden=false 25 | 06-child.00000.06-child.00001.03-attr.type=local.shells 26 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.rse.core/profiles/PRF.vacsal52848_2016/node.properties: -------------------------------------------------------------------------------- 1 | # RSE DOM Node 2 | 00-name=VACSAL52848 3 | 01-type=Profile 4 | 03-attr.defaultPrivate=true 5 | 03-attr.isActive=true 6 | 05-ref.00000=FP.local.files_0 7 | 05-ref.00001=H.local_16 8 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.rse.ui/.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.plugins/org.eclipse.rse.ui/.log -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 | 6 | 7 |
8 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.eclipse.ui/dialog_settings.xml: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.springframework.ide.eclipse.aop.core/.state: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.springframework.ide.eclipse.beans.core.metadata/metadata/.state: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.plugins/org.springframework.ide.eclipse.beans.core.metadata/metadata/.state -------------------------------------------------------------------------------- /.metadata/.plugins/org.springframework.ide.eclipse.beans.core.metadata/properties/.state: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.metadata/.plugins/org.springframework.ide.eclipse.beans.core.metadata/properties/.state -------------------------------------------------------------------------------- /.metadata/.plugins/org.springsource.ide.eclipse.commons.gettingstarted/dashboard/1522593921848/common/css/application.css: -------------------------------------------------------------------------------- 1 | #authentication{line-height:20px;padding:10px 0;}ul.download-links{list-style-type:none;margin-left:0;} 2 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.springsource.ide.eclipse.commons.gettingstarted/dashboard/1522593921848/common/css/blog.css: -------------------------------------------------------------------------------- 1 | .blog--container { 2 | padding: 0 0 40px 0; 3 | } 4 | 5 | .blog--container.blog-preview { 6 | margin: 0 0 40px 0; 7 | border-bottom: 1px solid #cccccc; 8 | } 9 | 10 | .blog--container.blog-preview .meta-data--container { 11 | margin-bottom: 0; 12 | } 13 | 14 | .blog--container.blog-preview .blog-preview--readmore { 15 | color: #5fa134; 16 | text-transform: uppercase; 17 | } 18 | 19 | .blog--container.blog-preview .blog-preview--readmore:hover { 20 | text-decoration: underline; 21 | } 22 | 23 | .blog--container.blog-preview .blog--post ul,.blog--container.blog-preview .blog--post ol,.blog--container.blog-preview .blog--post table,.blog--container.blog-preview .blog--post h3,.blog--container.blog-preview .blog--post h2 24 | { 25 | display: none; 26 | } 27 | 28 | .blog--container.blog-preview .blog--post p { 29 | margin-bottom: 15px; 30 | } 31 | 32 | .blog--container.blog-preview:last-child { 33 | margin: 0; 34 | } 35 | 36 | .blog--container .blog--title { 37 | font-size: 24px; 38 | margin-bottom: 12px; 39 | line-height: 35px; 40 | font-family: "Montserrat", sans-serif; 41 | color: #34302d; 42 | } 43 | 44 | .blog--container .blog--title a { 45 | color: #34302d; 46 | } 47 | 48 | .blog--container .blog--title a:hover { 49 | text-decoration: none; 50 | color: #5fa134; 51 | } 52 | 53 | .blog--container .meta-data--container { 54 | margin-bottom: 30px; 55 | } 56 | 57 | .blog--container .meta-data--container .meta-data--item { 58 | display: inline-block; 59 | margin: 2px 30px 0 0; 60 | font-size: 12px; 61 | line-height: 12px; 62 | text-transform: uppercase; 63 | } 64 | 65 | .blog--container .meta-data--container .meta-data--item .meta-data--icon 66 | { 67 | display: inline-block; 68 | height: 20px; 69 | width: 20px; 70 | vertical-align: middle; 71 | margin: -2px 5px 0 0; 72 | } 73 | 74 | .blog--container .meta-data--container .meta-data--item a { 75 | color: #34302d; 76 | } 77 | 78 | .blog--container .meta-data--container .meta-data--item a:hover { 79 | text-decoration: none; 80 | color: #5fa134; 81 | } 82 | 83 | .blog--container .blog--post { 84 | margin: 20px 0 30px; 85 | } 86 | 87 | .blog--container .blog--post a { 88 | color: #5fa134; 89 | } 90 | 91 | .blog--container .blog--post a:hover { 92 | text-decoration: underline; 93 | } 94 | 95 | .blog--container .blog--post h2 { 96 | font-family: "Montserrat", sans-serif; 97 | font-size: 18px; 98 | line-height: 28px; 99 | font-weight: 700; 100 | margin: 30px 0 15px; 101 | } 102 | 103 | .blog--container .blog--post h3,.blog--container .blog--post h4 { 104 | font-family: "Montserrat", sans-serif; 105 | font-size: 16px; 106 | line-height: 26px; 107 | font-weight: 700; 108 | margin: 30px 0 15px; 109 | } 110 | 111 | .blog--container .blog--post p { 112 | margin-bottom: 20px; 113 | } 114 | 115 | .blog--container .blog--post code { 116 | color: #305CB5; 117 | font-size: 14px; 118 | padding: 2px 6px; 119 | white-space: normal; 120 | } 121 | 122 | .blog--container .blog--post ul,.blog--container .blog--post ol { 123 | margin: 15px 0 20px 25px; 124 | } 125 | 126 | .blog--container .blog--post ul li,.blog--container .blog--post ol li { 127 | padding-bottom: 20px; 128 | font-size: 15px; 129 | line-height: 18px; 130 | } 131 | 132 | .blog--container .blog--post img { 133 | display: block; 134 | margin: 20px 0; 135 | } 136 | 137 | .blog--container .blog--post pre { 138 | margin: 20px 0; 139 | } 140 | 141 | .blog--container .blog--post strong { 142 | font-family: "Montserrat", sans-serif; 143 | } 144 | 145 | .blog--container .blog--post blockquote { 146 | margin: 20px 0; 147 | padding: 0 0 0 10px; 148 | border-left: 5px solid #dddddd; 149 | } 150 | 151 | .blog--container .blog--post blockquote p { 152 | margin-bottom: 20px; 153 | font-size: 15px; 154 | line-height: 24px; 155 | } 156 | 157 | .blog--container .blog--post blockquote code { 158 | color: #305CB5; 159 | font-size: 14px; 160 | padding: 2px 6px; 161 | } 162 | 163 | .blog--container .blog--post .highlight { 164 | margin-bottom: 20px; 165 | } 166 | 167 | .blog--container .blog--post .highlight pre { 168 | border-radius: 0; 169 | word-break: normal; 170 | word-wrap: normal; 171 | white-space: pre; 172 | overflow-x: auto; 173 | width: 96.9%; 174 | } 175 | 176 | .blog--container .blog--post .highlight .copy-button { 177 | position: absolute; 178 | margin-left: 633px; 179 | } 180 | 181 | .blog--container .blog--post .callout { 182 | border-left: 4px solid #6db33f; 183 | background-color: #EBF1E7; 184 | padding: 25px 20px; 185 | font-family: "Montserrat", sans-serif; 186 | margin: 20px 30px; 187 | } 188 | 189 | .blog--container .blog--post .callout .callout-title { 190 | font-size: 16px; 191 | line-height: 20px; 192 | font-weight: bold; 193 | margin-bottom: 6px; 194 | } 195 | 196 | .blog--container .blog--post .callout p { 197 | margin: 0; 198 | font-size: 14px; 199 | line-height: 20px; 200 | } 201 | 202 | .blog-comments--wrapper { 203 | border-top: 1px solid #cccccc; 204 | padding-top: 30px; 205 | } 206 | 207 | .blog-comments--wrapper .blog-comments--container { 208 | border: 1px solid #34302d; 209 | } 210 | 211 | .blog-comments--wrapper .blog-comments--container .blog-comments--header 212 | { 213 | background-color: #34302d; 214 | color: #f1f1f1; 215 | font-size: 14px; 216 | line-height: 14px; 217 | padding: 18px; 218 | } 219 | 220 | .blog-comments--wrapper .blog-comments--container .blog-comments--header a 221 | { 222 | color: #6db33f; 223 | } 224 | 225 | .blog-comments--wrapper .blog-comments--container .blog-comments--header .icon 226 | { 227 | margin-top: -11px; 228 | } 229 | 230 | .blog-comments--wrapper .blog-comments--container .blog-comments--body { 231 | padding: 18px; 232 | } 233 | 234 | .social-btn--container { 235 | margin: 40px 0; 236 | text-align: center; 237 | } 238 | 239 | .social-btn--container .social-btn { 240 | background-image: url("../img/iconsprite.png"); 241 | display: inline-block; 242 | width: 36px; 243 | height: 36px; 244 | margin: 0 3.5%; 245 | } 246 | 247 | .social-btn--container .social-btn.twitter { 248 | background-position: 1000px 694px; 249 | } 250 | 251 | .social-btn--container .social-btn.twitter:hover { 252 | background-position: 917px 694px; 253 | } 254 | 255 | .social-btn--container .social-btn.googleplus { 256 | background-position: 1000px 617px; 257 | } 258 | 259 | .social-btn--container .social-btn.googleplus:hover { 260 | background-position: 917px 617px; 261 | } 262 | 263 | .social-btn--container .social-btn.linkedin { 264 | background-position: 1000px 540px; 265 | } 266 | 267 | .social-btn--container .social-btn.linkedin:hover { 268 | background-position: 917px 540px; 269 | } 270 | 271 | .social-btn--container .social-btn.facebook { 272 | background-position: 1000px 464px; 273 | } 274 | 275 | .social-btn--container .social-btn.facebook:hover { 276 | background-position: 917px 464px; 277 | } 278 | 279 | .social-btn--container .social-btn.youtube { 280 | background-position: 1000px 387px; 281 | } 282 | 283 | .social-btn--container .social-btn.youtube:hover { 284 | background-position: 917px 387px; 285 | } 286 | 287 | .promo-material { 288 | padding: 75px 0; 289 | margin: 0 0 40px 0; 290 | text-align: center; 291 | text-transform: uppercase; 292 | border: 6px solid white; 293 | color: #ccc; 294 | background-color: #ddd; 295 | } 296 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.springsource.ide.eclipse.commons.gettingstarted/dashboard/1522593921848/common/css/buttons.css: -------------------------------------------------------------------------------- 1 | .btn.btn-black{background-color:#34302d;background-image:none;border-radius:0;color:#f1f1f1;font-size:14px;line-height:14px;font-family:"Montserrat",sans-serif;border:2px solid #6db33f;padding:21px 60px;text-shadow:none;transition:border 0.15s;-webkit-transition:border 0.15s;-moz-transition:border 0.15s;-o-transition:border 0.15s;-ms-transition:border 0.15s;}.btn.btn-black.compact{padding:6px 12px;font-size:12px;}.btn.btn-black.sub-text{padding:12px 0;}.btn.btn-black.sub-text p{margin-top:6px;color:#eeeeee;font-size:14px;line-height:14px;font-family:"Montserrat",sans-serif;text-transform:none;}.btn.btn-black.on-black:hover{border-color:#6db33f;box-shadow:0 1px 3px #0b0a0a;}.btn.btn-black.on-black:active{box-shadow:0 1px 3px #0b0a0a,inset 0 3px 6px #0b0a0a;border-color:#6db33f;}.btn.btn-black.with-icon [class^="icon-"]{margin-right:21px;font-size:20px;vertical-align:top;line-height:10px;}.btn.btn-black:hover{border-color:#34302d;box-shadow:none;text-decoration:none;}.btn.btn-black:active{box-shadow:inset 0 3px 6px #0b0a0a;border-color:#34302d;}.btn.uppercase{text-transform:uppercase;} 2 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.springsource.ide.eclipse.commons.gettingstarted/dashboard/1522593921848/common/css/dashboard.css: -------------------------------------------------------------------------------- 1 | .content-right-pane--container .ide_widget { 2 | display: block; 3 | text-align: center; 4 | margin: 10px 20px; 5 | } 6 | 7 | .btn.btn-black { 8 | font-size: 12px; 9 | line-height: 12px; 10 | padding: 10px 20px; 11 | background-color: #34302d; 12 | color: white; 13 | border: 0px; 14 | border-top: 3px solid #6db33f; 15 | } 16 | 17 | .btn.btn-black:hover { 18 | color: white; 19 | border-color: #34302d; 20 | background-color: #6db33f; 21 | border: 0px; 22 | border-top: 3px solid #6db33f; 23 | } 24 | 25 | .new-star { 26 | color: gold; 27 | border-color: black; 28 | font-size: 14px; 29 | } 30 | 31 | .content-right-pane--container .gettingStartedButton { 32 | display: block; 33 | text-align: center; 34 | margin: 45px 6.2%; 35 | } 36 | 37 | .main-body--wrapper { 38 | padding-top: 20px; 39 | margin-top: 0px; 40 | } 41 | 42 | .blog--title { 43 | margin-top: 6px !important; 44 | margin-bottom: 2px !important; 45 | } 46 | 47 | .blog--container { 48 | margin-bottom: 0px !important; 49 | padding: 0px !important; 50 | } 51 | 52 | div .blog--post,.blog--container.blog-preview { 53 | margin: 0px !important; 54 | padding: 0px !important; 55 | } 56 | 57 | div .blog--post { 58 | line-height: 10px !important; 59 | } 60 | 61 | .blog--title a { 62 | font-size: 14px; 63 | line-height: 15px; 64 | } 65 | 66 | .blog--post p { 67 | font-size: 11px; 68 | line-height: 15px; 69 | margin-bottom: 10px !important; 70 | } 71 | 72 | .author { 73 | font-size: 11px; 74 | line-height: 15px; 75 | font-style: oblique; 76 | } 77 | 78 | .feed-header { 79 | color: #6db33f; 80 | margin-bottom: 0px; 81 | } 82 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.springsource.ide.eclipse.commons.gettingstarted/dashboard/1522593921848/common/css/docs.css: -------------------------------------------------------------------------------- 1 | .docs--header .docs-icon{background-color:#34302d;width:94px;height:122px;margin:0 40px 40px 0;padding:39px;background-image:url("../img/iconsprite.png");background-repeat:no-repeat;background-position:37px -506px;}.docs--body{width:auto;min-height:50px;display:block!important;}.docs--body .docs-item--wrapper{padding:0 20px;margin:20px -22px;}.docs--body .empty-project{margin-bottom:-40px;}.docs--body .docs-section-title{margin:40px 20px 30px;border-top:1px solid white;padding-top:40px;font-family:"Montserrat",sans-serif;font-weight:bold;}.docs--body .docs-section-title.no-border{border:0;padding-top:0;}.docs--item{display:inline-block;width:295px;vertical-align:top;margin:0 22px;}.docs--item .docs-version--dropdown{width:86.5%;}.docs--item .docs-version--dropdown p{display:inline-block;}.docs--item .docs-version--dropdown .icon{vertical-align:top;margin:2px 0 0 6px;} 2 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.springsource.ide.eclipse.commons.gettingstarted/dashboard/1522593921848/common/css/flexbox.css: -------------------------------------------------------------------------------- 1 | 2 | /* GENERAL STYLES */ 3 | body { 4 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 5 | margin: 3%; 6 | font-size: 0.9em; 7 | } 8 | 9 | #page-header { 10 | margin-top: 1%; 11 | } 12 | 13 | #title { 14 | font-size: 1.2em; 15 | } 16 | 17 | #link-to-article { 18 | font-size: 0.8em; 19 | } 20 | 21 | #link-to-article a{ 22 | padding: 3px 0 10px 35px; 23 | background: url(../images/nettuts-logo.jpg) no-repeat; 24 | display: inline-block; 25 | } 26 | 27 | .example { 28 | min-height: 20px; 29 | padding: 2%; 30 | margin-bottom: 3%; 31 | background-color: whiteSmoke; 32 | border: 1px solid #EEE; 33 | border: 1px solid rgba(0, 0, 0, 0.05); 34 | -webkit-border-radius: 4px; 35 | -moz-border-radius: 4px; 36 | border-radius: 4px; 37 | -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); 38 | -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); 39 | box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); 40 | overflow: hidden; 41 | } 42 | 43 | .example header { 44 | margin-bottom: 10px; 45 | } 46 | 47 | .example header h1, .example header p { 48 | margin: 0 0 2% 0; 49 | padding: 0; 50 | font-size: 1.1em; 51 | } 52 | 53 | .example header p { 54 | font-size: 1em; 55 | } 56 | 57 | .flexbox-message { 58 | display: none; 59 | padding: 1% 3%; 60 | margin-bottom: 20px; 61 | color: #C09853; 62 | text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); 63 | background-color: #FCF8E3; 64 | border: 1px solid #FBEED5; 65 | -webkit-border-radius: 4px; 66 | -moz-border-radius: 4px; 67 | border-radius: 4px; 68 | color: #B94A48; 69 | background-color: #F2DEDE; 70 | border-color: #EED3D7; 71 | } 72 | 73 | .no-flexbox-legacy .flexbox-message{ 74 | display: block; 75 | } 76 | 77 | code { 78 | padding: 0 3px 2px; 79 | font-family: Menlo, Monaco, Consolas, "Courier New", monospace; 80 | font-size: 0.9em; 81 | color: #333; 82 | -webkit-border-radius: 3px; 83 | -moz-border-radius: 3px; 84 | border-radius: 3px; 85 | padding: 2px 4px; 86 | color: #D14; 87 | background-color: #F7F7F9; 88 | border: 1px solid #E1E1E8; 89 | } 90 | 91 | 92 | 93 | 94 | .btn { 95 | display: inline-block; 96 | padding: 4px 10px 4px; 97 | margin-bottom: 10px; 98 | font-size: 13px; 99 | line-height: 18px; 100 | color: 101 | #333; 102 | text-align: center; 103 | text-shadow: 0 1px 1px 104 | rgba(255, 255, 255, 0.75); 105 | vertical-align: middle; 106 | cursor: pointer; 107 | background-color: 108 | whiteSmoke; 109 | background-image: -ms-linear-gradient(top, 110 | white, 111 | #E6E6E6); 112 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from( 113 | white), to( 114 | #E6E6E6)); 115 | background-image: -webkit-linear-gradient(top, 116 | white, 117 | #E6E6E6); 118 | background-image: -o-linear-gradient(top, 119 | white, 120 | #E6E6E6); 121 | background-image: linear-gradient(top, 122 | white, 123 | #E6E6E6); 124 | background-image: -moz-linear-gradient(top, 125 | white, 126 | #E6E6E6); 127 | background-repeat: repeat-x; 128 | border: 1px solid 129 | #CCC; 130 | border-color: 131 | rgba(0, 0, 0, 0.1) 132 | rgba(0, 0, 0, 0.1) 133 | rgba(0, 0, 0, 0.25); 134 | border-color: 135 | #E6E6E6 136 | #E6E6E6 137 | #BFBFBF; 138 | border-bottom-color: 139 | #B3B3B3; 140 | -webkit-border-radius: 4px; 141 | -moz-border-radius: 4px; 142 | border-radius: 4px; 143 | filter: progid:dximagetransform.microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0); 144 | filter: progid:dximagetransform.microsoft.gradient(enabled=false); 145 | -webkit-box-shadow: inset 0 1px 0 146 | rgba(255, 255, 255, 0.2), 0 1px 2px 147 | rgba(0, 0, 0, 0.05); 148 | -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); 149 | box-shadow: inset 0 1px 0 150 | rgba(255, 255, 255, 0.2), 0 1px 2px 151 | rgba(0, 0, 0, 0.05); 152 | } 153 | 154 | .btn.active, .btn:active { 155 | background-color: 156 | #E6E6E6; 157 | background-color: 158 | #D9D9D9 9; 159 | background-image: none; 160 | outline: 0; 161 | -webkit-box-shadow: inset 0 2px 4px 162 | rgba(0, 0, 0, 0.15), 0 1px 2px 163 | rgba(0, 0, 0, 0.05); 164 | -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); 165 | box-shadow: inset 0 2px 4px 166 | rgba(0, 0, 0, 0.15), 0 1px 2px 167 | rgba(0, 0, 0, 0.05); 168 | } 169 | 170 | 171 | #example-5 .different-flex-example > div:nth-child(2), 172 | #example-5 .final-flex-example > div:nth-child(2), 173 | #example-6 .ordering-example > div:nth-child(1) 174 | { 175 | background-image: -webkit-linear-gradient(top, 176 | #62C462, 177 | #51A351); 178 | background-image: -o-linear-gradient(top, 179 | #62C462, 180 | #51A351); 181 | background-image: -moz-linear-gradient(top, 182 | #62C462, 183 | #51A351); 184 | background-image: linear-gradient(top, 185 | #62C462, 186 | #51A351); 187 | } 188 | 189 | 190 | 191 | /* Smartphones (landscape) ----------- */ 192 | @media only screen and (min-width : 321px) { 193 | /* Styles */ 194 | } 195 | 196 | /* Smartphones (portrait) ----------- */ 197 | @media only screen and (max-width : 320px) { 198 | 199 | .example header h1, .example header p { 200 | margin: 0 0 4% 0; 201 | padding: 0; 202 | font-size: 1.1em; 203 | } 204 | 205 | .example { 206 | margin-bottom: 5%; 207 | } 208 | 209 | 210 | } 211 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.springsource.ide.eclipse.commons.gettingstarted/dashboard/1522593921848/common/css/fontcustom.css: -------------------------------------------------------------------------------- 1 | @font-face{font-family:"fontcustom";src:url("../font-custom/fontcustom.eot");src:url("../font-custom/fontcustom.eot?#iefix") format("embedded-opentype"),url("../font-custom/fontcustom.woff") format("woff"),url("../font-custom/fontcustom.ttf") format("truetype"),url("../font-custom/fontcustom.svg#fontcustom") format("svg");font-weight:normal;font-style:normal;}.icon-community-support,.icon-gs-guides-black,.icon-professional-support,.icon-spring-amqp,.icon-spring-android,.icon-spring-batch,.icon-spring-data,.icon-spring-framework,.icon-spring-hateos,.icon-spring-integration,.icon-spring-leaf,.icon-spring-logo,.icon-spring-mobile,.icon-spring-security,.icon-spring-social,.icon-spring-web-flow,.icon-spring-web-services,.icon-tutorials-black{font-family:"fontcustom"!important;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;display:inline-block!important;text-decoration:inherit;}.icon-community-support:before{content:"\f100";}.icon-gs-guides-black:before{content:"\f101";}.icon-professional-support:before{content:"\f102";}.icon-spring-amqp:before{content:"\f103";}.icon-spring-android:before{content:"\f104";}.icon-spring-batch:before{content:"\f105";}.icon-spring-data:before{content:"\f106";}.icon-spring-framework:before{content:"\f107";}.icon-spring-hateos:before{content:"\f108";}.icon-spring-integration:before{content:"\f109";}.icon-spring-leaf:before{content:"\f10a";}.icon-spring-logo:before{content:"\f10b";}.icon-spring-mobile:before{content:"\f10c";}.icon-spring-security:before{content:"\f10d";}.icon-spring-social:before{content:"\f10e";}.icon-spring-web-flow:before{content:"\f10f";}.icon-spring-web-services:before{content:"\f110";}.icon-tutorials-black:before{content:"\f111";} 2 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.springsource.ide.eclipse.commons.gettingstarted/dashboard/1522593921848/common/css/highlight.css: -------------------------------------------------------------------------------- 1 | .highlight .hll{background-color:#ffffcc;}.highlight .c{color:#999988;font-style:italic;}.highlight .err{color:#a61717;background-color:#e3d2d2;}.highlight .k{color:#000000;font-weight:bold;}.highlight .o{color:#000000;font-weight:bold;}.highlight .cm{color:#999988;font-style:italic;}.highlight .cp{color:#999999;font-weight:bold;font-style:italic;}.highlight .c1{color:#999988;font-style:italic;}.highlight .cs{color:#999999;font-weight:bold;font-style:italic;}.highlight .gd{color:#000000;background-color:#ffdddd;}.highlight .ge{color:#000000;font-style:italic;}.highlight .gr{color:#aa0000;}.highlight .gh{color:#999999;}.highlight .gi{color:#000000;background-color:#ddffdd;}.highlight .go{color:#888888;}.highlight .gp{color:#555555;}.highlight .gs{font-weight:bold;}.highlight .gu{color:#aaaaaa;}.highlight .gt{color:#aa0000;}.highlight .kc{color:#000000;font-weight:bold;}.highlight .kd{color:#000000;font-weight:bold;}.highlight .kn{color:#000000;font-weight:bold;}.highlight .kp{color:#000000;font-weight:bold;}.highlight .kr{color:#000000;font-weight:bold;}.highlight .kt{color:#445588;font-weight:bold;}.highlight .m{color:#009999;}.highlight .s{color:#d01040;}.highlight .na{color:teal;}.highlight .nb{color:#0086b3;}.highlight .nc{color:#445588;font-weight:bold;}.highlight .no{color:teal;}.highlight .nd{color:#3c5d5d;font-weight:bold;}.highlight .ni{color:purple;}.highlight .ne{color:#990000;font-weight:bold;}.highlight .nf{color:#990000;font-weight:bold;}.highlight .nl{color:#990000;font-weight:bold;}.highlight .nn{color:#555555;}.highlight .nt{color:navy;}.highlight .nv{color:teal;}.highlight .ow{color:#000000;font-weight:bold;}.highlight .w{color:#bbbbbb;}.highlight .mf{color:#009999;}.highlight .mh{color:#009999;}.highlight .mi{color:#009999;}.highlight .mo{color:#009999;}.highlight .sb{color:#d01040;}.highlight .sc{color:#d01040;}.highlight .sd{color:#d01040;}.highlight .s2{color:#d01040;}.highlight .se{color:#d01040;}.highlight .sh{color:#d01040;}.highlight .si{color:#d01040;}.highlight .sx{color:#d01040;}.highlight .sr{color:#009926;}.highlight .s1{color:#d01040;}.highlight .ss{color:#990073;}.highlight .bp{color:#999999;}.highlight .vc{color:teal;}.highlight .vg{color:teal;}.highlight .vi{color:teal;}.highlight .il{color:#009999;} 2 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.springsource.ide.eclipse.commons.gettingstarted/dashboard/1522593921848/common/css/homepage.css: -------------------------------------------------------------------------------- 1 | .homepage-billboard{background-image:url("../img/homepage-bg.jpg");background-size:cover;background-repeat:no-repeat;text-align:center;}.homepage-title--container{margin-top:66px;}.homepage-title,.homepage-subtitle{background:rgba(52,48,45,0.8);color:#f1f1f1;display:inline-block;}.homepage-title{font-size:48px;line-height:68px;font-family:"Montserrat",sans-serif;padding:0 15px;letter-spacing:-2px;}.homepage-subtitle{font-size:22px;line-height:18px;padding:2px 19px 12px;}.homepage-subtitle:first-child{padding-top:12px;}.homepage--body .platform--wrapper{background:url("../img/platform-bg.png") #34302d 50% 50% no-repeat;height:auto;text-align:center;padding:60px 0;background-size:694px;}.homepage--body .platform--wrapper .platform--icon{background:url("../img/spring-platform-watermark.png") no-repeat;width:241px;height:74px;display:inline-block;margin-bottom:43px;}.homepage--body .platform--wrapper .platform--title{font-family:"Montserrat",sans-serif;color:#f1f1f1;font-size:30px;line-height:30px;margin-bottom:20px;text-transform:uppercase;}.homepage--body .platform--wrapper .platform--text{color:#f1f1f1;font-size:18px;line-height:28px;margin-bottom:20px;}.homepage--body .platform--wrapper .platform--link{font-size:18px;line-height:28px;}.homepage--body .platform--wrapper .platform--link [class^="icon-"]{margin-left:15px;line-height:10px;vertical-align:middle;text-decoration:none;}.homepage--body .key-feature--wrapper{background-color:#6db33f;padding:60px 0;}.homepage--body .key-feature--wrapper .key-feature--container{text-align:center;color:#f1f1f1;}.homepage--body .key-feature--wrapper .key-feature--container .key-feature--icon--container{height:88px;text-align:center;margin-bottom:44px;}.homepage--body .key-feature--wrapper .key-feature--container .key-feature--title{text-transform:uppercase;font-family:"Montserrat",sans-serif;font-size:30px;line-height:30px;margin-bottom:20px;}.homepage--body .key-feature--wrapper .key-feature--container .key-feature--text{font-size:18px;line-height:28px;}.homepage--body .key-feature--wrapper .key-feature--container .key-feature--text.highlight{text-transform:uppercase;}.homepage--body .offset-feature--container{border-bottom:1px solid #dddbda;transition:all 0.25s;-webkit-transition:all 0.25s;-moz-transition:all 0.25s;-o-transition:all 0.25s;-ms-transition:all 0.25s;}.homepage--body .offset-feature--container .feature--content{padding:90px 0;}.homepage--body .offset-feature--container .offset-feature--title{font-size:30px;line-height:30px;font-family:"Montserrat",sans-serif;margin-bottom:20px;color:#34302d;}.homepage--body .offset-feature--container .offset-feature--text{font-size:18px;line-height:28px;margin-bottom:20px;color:#34302d;}.homepage--body .offset-feature--container .offset-feature--link{color:#5fa134;font-size:18px;line-height:18px;}.homepage--body .offset-feature--container .offset-feature--link i{font-size:18px;line-height:10px;margin-left:10px;text-decoration:none;}.homepage--body .offset-feature--container.feature-guides{background-image:url("../img/homepage-feature-guides.png");background-repeat:no-repeat;background-position:148% 0;}.homepage--body .offset-feature--container.feature-sts{background-image:url("../img/homepage-feature-sts.png");background-repeat:no-repeat;background-position:-40% 100%;}.homepage--body .offset-feature--container.feature-projects{background-image:url("../img/homepage-feature-projects.png");background-repeat:no-repeat;background-position:130px 0;}.homepage--body .offset-feature--container:last-child{border:none;}.homepage--body .offset-feature--container:nth-child(even){background-color:#ebf1e7;}.support--wrapper{background-color:#5d5d5d;padding:50px 0 60px;}.support--wrapper .support--container .icon{float:left;margin-right:45px;}.support--wrapper .support--container .support--title{font-size:18px;line-height:18px;text-transform:uppercase;color:#f1f1f1;margin:22px 0;}.support--wrapper .support--container .support-links a{color:#5fa134;padding:0 20px;}.support--wrapper .support--container .support-links a:first-child{padding-left:0;}.support--wrapper.about-page{position:absolute;left:0;right:0;}.tool-suite{text-align:right;} 2 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.springsource.ide.eclipse.commons.gettingstarted/dashboard/1522593921848/common/css/icons.css: -------------------------------------------------------------------------------- 1 | .icon{background-image:url("../img/iconsprite.png");display:inline-block!important;}.icon.icon-spring-logo-mobile{width:204px;height:60px;background-position:904px 302px;margin-top:-13px;transform:scale(0.5);-moz-transform:scale(0.5);-webkit-transform:scale(0.5);-o-transform:scale(0.5);-ms-transform:scale(0.5);}.icon.icon-spring-logo-big{width:154px;height:154px;background-position:154px 191px;}.icon.project--logo.logo-spring-framework{width:135px;height:133px;background-position:518px 837px;margin-top:2px;}.icon.project--logo.logo-spring-security{width:99px;height:137px;background-position:519px 677px;}.icon.project--logo.logo-spring-data{width:111px;height:111px;background-position:519px 512px;margin-top:13px;}.icon.project--logo.logo-spring-batch{width:104px;height:108px;background-position:360px 837px;margin-top:14px;}.icon.project--logo.logo-spring-integration{width:145px;height:104px;background-position:361px 677px;margin-top:16px;}.icon.project--logo.logo-spring-amqp{width:109px;height:98px;background-position:361px 513px;margin:19px;}.icon.project--logo.logo-spring-default{width:100px;height:100px;background-position:-805px 0;margin-top:18px;}.icon.project--logo.logo-spring-mobile{width:104px;height:137px;background-position:196px 677px;}.icon.project--logo.logo-spring-android{width:104px;height:126px;background-position:196px 513px;margin-top:10px;}.icon.project--logo.logo-spring-social{width:130px;height:100px;background-position:518px 357px;margin-top:18px;}.icon.project--logo.logo-spring-hateoas{width:126px;height:99px;background-position:518px 256px;margin-top:19px;}.icon.project--logo.logo-spring-webflow{width:99px;height:99px;background-position:619px 256px;margin-top:19px;}.icon.project--logo.logo-spring-web-services{width:100px;height:100px;background-position:532px 155px;margin-top:19px;}.icon.project--logo.logo-spring-xd{width:104px;height:113px;background-position:247px 837px;margin-top:11px;}.icon.project--logo.logo-spring-boot{width:102px;height:90px;background-position:143px 837px;margin-top:23px;}.icon.project--logo.logo-spring-ldap{width:93px;height:107px;background-position:247px 944px;margin-top:19px;}.icon.project--logo.logo-grails{width:107px;height:100px;background-position:361px 944px;margin-top:23px;}.icon.project--logo.logo-groovy{width:183px;height:92px;background-position:546px 940px;margin-top:23px;}.icon.icon-projects{width:28px;height:28px;background-position:-641px -481px;}.icon.icon-projects:hover{background-position:-641px -521px;}.icon.icon-forum{width:32px;height:32px;background-position:-409px -450px;}.icon.icon-forum:hover{background-position:-449px -450px;}.icon.icon-current-version{height:13px;width:42px;background-position:718px 317px;}.icon.icon-pre-release{height:13px;width:23px;background-position:657px 317px;}.icon.icon-ga-release{margin-left:0!important;height:13px;width:9px;background-position:626px 317px;background-color:#6db33f;padding:0 2px;border-radius:10px;}.icon.icon-snapshot-release{height:13px;width:46px;background-position:603px 317px;}.icon.logo-eclipse-text{width:159px;height:38px;background-position:603px 38px;}.icon.icon-social-twitter{width:36px;height:36px;background-position:-1px -143px;}.icon.icon-social-twitter:hover{background-position:-84px -143px;}.icon.icon-build-anything{width:107px;background-position:107px 279px;height:88px;}.icon.icon-run-anywhere{background-position:120px 344px;width:120px;height:65px;margin-top:11px;}.icon.icon-rest-assured{background-position:253px 86px;width:86px;height:86px;margin-top:1px;}.icon.icon-community-support{width:97px;height:97px;background-position:257px 185px;font-size:0;}.icon.icon-professional-support{width:126px;height:97px;background-position:272px 282px;font-size:0;}.icon.icon-gs-guides{width:73px;height:101px;background-position:356px 101px;}.icon.icon-tutorial{width:73px;height:101px;background-position:430px 101px;}.icon.blog-icon{width:20px;height:20px;vertical-align:middle;}.icon.blog-icon.calendar{background-position:20px 594px;}.icon.blog-icon.all-posts{background-position:20px 561px;}.icon.blog-icon.broadcasts{background-position:20px 519px;}.icon.blog-icon.engineering{background-position:20px 477px;}.icon.blog-icon.releases{background-position:20px 433px;}.icon.blog-icon.news-and-events{background-position:20px 387px;}.icon.about-icon.team{width:183px;height:127px;background-position:902px 202px;}.icon.about-icon.jobs{width:112px;height:85px;background-position:387px 415px;margin:21px 0;}.icon.about-icon.pivotal{width:93px;height:114px;background-position:387px 329px;margin:6px 0 7px;}i.icon{background-image:none;} 2 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.springsource.ide.eclipse.commons.gettingstarted/dashboard/1522593921848/common/css/markdown-content.css: -------------------------------------------------------------------------------- 1 | a[name="gs"],a[name="tutorials"] { 2 | text-decoration: none !important; 3 | } 4 | 5 | .content--container h1 { 6 | margin-bottom: 15px; 7 | } 8 | 9 | .content--container a { 10 | color: #5fa134; 11 | } 12 | 13 | .content--container p,.content--container ul { 14 | margin-bottom: 20px; 15 | border-radius: 0; 16 | } 17 | 18 | .content--container pre { 19 | margin-top: -10px; 20 | margin-bottom: 20px; 21 | border-radius: 0; 22 | } 23 | 24 | .content--container h2 { 25 | font-family: "Montserrat", sans-serif; 26 | font-size: 20px; 27 | line-height: 28px; 28 | font-weight: 400; 29 | margin: 30px 0 10px; 30 | } 31 | 32 | .content--container h3,.content--container h4 { 33 | font-family: "Montserrat", sans-serif; 34 | font-size: 16px; 35 | line-height: 26px; 36 | font-weight: 400; 37 | margin: 20px 0 10px; 38 | } 39 | 40 | .content--container p code { 41 | color: #305CB5; 42 | font-size: 14px; 43 | padding: 2px 6px; 44 | } 45 | 46 | .content--container ul li { 47 | margin-bottom: 5px; 48 | } 49 | 50 | .content--container ul li code { 51 | color: #305CB5; 52 | font-size: 14px; 53 | padding: 2px 6px; 54 | } 55 | 56 | .content--container blockquote { 57 | padding: 0 0 0 10px; 58 | border-left: 4px solid #6db33f; 59 | background-color: #EBF1E7; 60 | padding: 25px 20px; 61 | margin: 30px 0; 62 | font-family: "Montserrat", sans-serif; 63 | } 64 | 65 | .content--container blockquote strong { 66 | font-size: 16px; 67 | line-height: 20px; 68 | font-weight: bold; 69 | margin-bottom: 6px; 70 | } 71 | 72 | .content--container blockquote p { 73 | margin: 0; 74 | font-size: 14px; 75 | line-height: 20px; 76 | } 77 | 78 | .content--container pre { 79 | word-break: normal; 80 | word-wrap: normal; 81 | white-space: pre; 82 | overflow-x: auto; 83 | width: 96.9%; 84 | } 85 | 86 | .content--container .highlight .copy-button { 87 | position: absolute; 88 | margin-left: 634px; 89 | } 90 | 91 | .content--container strong { 92 | font-family: "Montserrat", sans-serif; 93 | } 94 | 95 | .content-right-pane--container h2 { 96 | margin: 15px 6.2%; 97 | } 98 | 99 | .content-right-pane--container p { 100 | font-size: 14px; 101 | line-height: 21px; 102 | margin: 15px 6.2%; 103 | } 104 | 105 | .content-right-pane--container h3 { 106 | border-top: 1px solid #dddddd; 107 | padding: 6px 6.2%; 108 | font-family: "Montserrat", sans-serif; 109 | margin: 0; 110 | } 111 | 112 | .content-right-pane--container ul { 113 | margin: 0; 114 | } 115 | 116 | .content-right-pane--container ul li { 117 | line-height: 21px; 118 | } 119 | 120 | .content-right-pane--container ul li:last-child { 121 | padding-bottom: 28px; 122 | } 123 | 124 | .content-right-pane--container ul li:first-child { 125 | padding-bottom: 12px; 126 | } 127 | 128 | .content-right-pane--container .btn-group { 129 | margin: 0 6.2%; 130 | display: block; 131 | } 132 | 133 | .content-right-pane--container .btn-group .btn { 134 | font-family: "Varela Round", sans-serif; 135 | padding: 12px 6.4% 10px; 136 | font-size: 16px; 137 | line-height: 16px; 138 | border: 1px solid #dddddd; 139 | box-shadow: none; 140 | } 141 | 142 | .content-right-pane--container .btn-group .btn.active { 143 | background: #fff; 144 | box-shadow: none; 145 | } 146 | 147 | .content-right-pane--container .btn-group .btn:active { 148 | box-shadow: inset 0 1px 3px #c8c8c8; 149 | } 150 | 151 | .content-right-pane--container .clone-url { 152 | border: 1px solid #cccccc; 153 | background-color: white; 154 | cursor: pointer; 155 | margin: 15px 6.2%; 156 | } 157 | 158 | .content-right-pane--container .clone-url input { 159 | background-color: transparent; 160 | border: none; 161 | box-shadow: none; 162 | margin: 0; 163 | padding: 10px 0 10px 14px; 164 | } 165 | 166 | .content-right-pane--container .clone-url input:focus { 167 | outline: none; 168 | } 169 | 170 | .content-right-pane--container .clone-url button { 171 | padding: 20px; 172 | margin: 0; 173 | float: right; 174 | } 175 | 176 | .content-right-pane--container .github_download { 177 | display: block; 178 | text-align: center; 179 | margin: 15px 6.2%; 180 | } 181 | 182 | .go-to-repo--container { 183 | margin-top: 20px; 184 | padding: 10px 6.2%; 185 | border-top: 1px solid white; 186 | } 187 | 188 | .go-to-repo--container a { 189 | vertical-align: middle; 190 | color: #5fa134; 191 | text-transform: uppercase; 192 | font-family: "Montserrat", sans-serif; 193 | font-size: 12px; 194 | line-height: 24px; 195 | text-decoration: none; 196 | margin-top: 1px; 197 | } 198 | 199 | .go-to-repo--container a:hover { 200 | color: #6ab43a; 201 | } 202 | 203 | .go-to-repo--container i { 204 | color: #d4d4d4; 205 | font-size: 24px; 206 | margin-right: 10px; 207 | float: left; 208 | margin-top: -2px; 209 | } 210 | 211 | .copy-button { 212 | background-color: #cccccc; 213 | margin: 1px 1px 10px 0; 214 | padding: 20px; 215 | background-image: url("../img/iconsprite.png"); 216 | background-repeat: no-repeat; 217 | background-position: 2px -429px; 218 | width: 20px; 219 | height: 22px; 220 | border: none; 221 | background-color: #34302d; 222 | } 223 | 224 | .copy-button.snippet { 225 | float: right; 226 | } 227 | 228 | a.ci-status { 229 | float: right; 230 | margin-top: -27px; 231 | } 232 | 233 | .gs-guide-import { 234 | display: none; 235 | } 236 | 237 | .tutorial-text img { 238 | border: 6px solid white; 239 | box-shadow: 0 0px 4px #cccccc, 0 1px 0 #cccccc; 240 | } 241 | 242 | .tutorial-text table { 243 | border-color: #808080; 244 | text-align: left; 245 | margin: 60px 0; 246 | } 247 | 248 | .tutorial-text table th { 249 | text-transform: uppercase; 250 | font-size: 12px; 251 | line-height: 15px; 252 | border-bottom: 1px solid #cccccc; 253 | padding: 0 30px 5px 8px; 254 | vertical-align: bottom; 255 | font-family: "Montserrat", sans-serif; 256 | } 257 | 258 | .tutorial-text table th:last-child { 259 | padding-right: 8px; 260 | } 261 | 262 | .tutorial-text table tr:last-child { 263 | border-bottom: 1px solid #cccccc; 264 | } 265 | 266 | .tutorial-text table td { 267 | padding: 8px 20px 8px 8px; 268 | line-height: 20px; 269 | text-align: left; 270 | vertical-align: top; 271 | border-top: 1px solid #dddddd; 272 | } 273 | 274 | .tutorial-text table td:last-child { 275 | padding-right: 8px; 276 | border-right: 1px solid #cccccc; 277 | } 278 | 279 | .tutorial-text table td:first-child { 280 | border-left: 1px solid #cccccc; 281 | } 282 | 283 | .tutorial-text table tr:nth-child(odd)>td,.tutorial-text table .table-striped tbody>tr:nth-child(odd)>th 284 | { 285 | background-color: #F9F9F9; 286 | } 287 | 288 | .tutorial-text article.markdown-body h1 { 289 | font-size: 21px; 290 | line-height: 28px; 291 | font-weight: 400; 292 | margin: 30px 0 10px; 293 | } 294 | 295 | .tutorial-text article.markdown-body h2 { 296 | font-family: "Varela Round", sans-serif; 297 | font-size: 19px; 298 | } 299 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.springsource.ide.eclipse.commons.gettingstarted/dashboard/1522593921848/common/css/panes.css: -------------------------------------------------------------------------------- 1 | /* Generic pane rules */ 2 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.springsource.ide.eclipse.commons.gettingstarted/dashboard/1522593921848/common/css/projects.css: -------------------------------------------------------------------------------- 1 | .projects--wrapper{margin-left:-0.5%;}.projects--wrapper.project-aggregator .project--container{height:160px;}.projects--wrapper.project-aggregator .project--container .project-links--container{margin-top:42px;}.projects--wrapper.top-separator{padding-top:30px;margin-top:10px;margin-bottom:10px;border-top:1px solid #dddddd;}.project--container{border:1px solid #34302d;display:inline-block;width:21.8%;height:340px;margin:0 0.5% 20px 0.5%;vertical-align:top;text-align:center;padding:30px 5%;}.project--container.auto-height{height:auto;}.project--container.short-fixed{height:262px;}.project--container.shorter-fixed{height:239px;}.project--container .project-logo--container{margin-bottom:25px;height:137px;vertical-align:middle;}.project--container .project--logo{display:inline-block;vertical-align:middle;}.project--container .project--logo.small{margin-bottom:20px;}.project--container .project--title{font-family:"Montserrat",sans-serif;font-size:16px;line-height:20px;margin-bottom:20px;text-transform:uppercase;}.project--container .project--description{font-size:14px;line-height:20px;}.project--container .project-links--container{position:absolute;background-color:rgba(109,179,63,0.95);padding:13px 0;width:326px;margin:127px 0 0 -20px;height:58px;opacity:0;transition:opacity 0.15s;-webkit-transition:opacity 0.15s;-moz-transition:opacity 0.15s;-o-transition:opacity 0.15s;-ms-transition:opacity 0.15s;}.project--container .project-links--container .project-link{display:inline-block;margin:0 15px;}.project--container .project-links--container .project-link [class^=icon-]{font-size:34px;width:34px;height:34px;color:rgba(241,241,241,0.75);}.project--container .project-links--container .project-link p{margin:6px 0;color:rgba(241,241,241,0.75);font-size:14px;line-height:14px;}.project--container .project-links--container .project-link:hover{text-decoration:none;}.project--container .project-links--container .project-link:hover [class^=icon-]{color:white;}.project--container:hover .project-links--container{opacity:1;}.project--container.parent-project{position:relative;}.project--container.parent-project .child-project-count--wrapper{position:absolute;top:30px;right:20px;}.project--container.parent-project .child-project-count--wrapper .child-project-count--number{position:relative;z-index:101;color:#f1f1f1;margin:-22px -9px 0 9px;}.project--container.parent-project .child-project-count--wrapper .child-project-count--background{position:absolute;margin:-54px 0 0 -5px;z-index:100;width:0;height:0;border-top:40px solid transparent;border-bottom:40px solid transparent;border-left:40px solid #6db33f;transform:rotate(-45deg);-webkit-transform:rotate(-45deg);-moz-transform:rotate(-45deg);-o-transform:rotate(-45deg);-ms-transform:rotate(-45deg);}.project--container.full-width{background-color:#ddd;border-color:white;display:block;height:auto;width:auto;text-align:left;}.project--container.full-width .project--title{margin-bottom:10px;}.project--container.full-width .project--description{margin-bottom:20px;}.project--container.full-width .project--link{color:#5fa134;text-transform:uppercase;font-size:12px;}.project--container.project--container--link{color:#34302d;transition:all 0.2s;-webkit-transition:all 0.2s;-moz-transition:all 0.2s;-ms-transition:all 0.2s;-o-transition:all 0.2s;}.project--container.project--container--link:hover{text-decoration:none;box-shadow:0 0 3px #6db33f;border-color:#6db33f;}.project--container.project--container--link:active{box-shadow:none;}.project--container.min-height{height:308px;}.project-header--wrapper .billboard--container{margin-top:60px;}.project-header--wrapper .content--title{position:relative;margin-bottom:30px;margin-top:0;}.project-header--wrapper .content--title a{color:#f1f1f1;}.project-header--wrapper .project--title{font-family:"Montserrat",sans-serif;font-size:24px;line-height:24px;color:#ebf1e7;}.project-header--wrapper .project--links--container{float:right;margin-top:-2px;}.project-header--wrapper .project--links--container .project-link{display:inline-block;vertical-align:middle;margin-right:10px;}.project-header--wrapper .project--links--container .project-link [class^=icon-]{font-size:37px;width:34px;height:34px;color:#d4d4d4;}.project-header--wrapper .project--links--container .project-link:last-child{margin-right:0;}.project-header--wrapper .project--links--container .project-link:hover{text-decoration:none;}.project-header--wrapper .project--links--container .project-link:hover [class^=icon-]{color:#6db33f;}.project-header--wrapper .project--links--container .project-link div.icon{margin-top:3px;}.project-header--wrapper .project--description{color:#f1f1f1;font-size:16px;line-height:24px;margin-top:20px;}.project-header--wrapper .project--description a{color:#5fa134;}.project-header--wrapper .project-quickstart-btn{margin-top:40px;}.project-header--wrapper .billboard-bg{background-color:#666;}.project-header--wrapper .billboard-bg .billboard-icon{width:330px;height:364px;position:absolute;right:0;margin-top:25px;opacity:0.5;}.project-header--wrapper .billboard-bg .billboard-icon.icon-spring-data-large{background-image:url("../img/icon-spring-data-large.png");}.project-body--container .project-body--section{margin-bottom:30px;padding-right:20px;}.project-body--container .project-body--section p{font-size:14px;line-height:20px;margin-bottom:20px;}.project-body--container .project-body--section li{padding:5px 0;}.project-body--container .project-body--section .underlined-title{border-bottom:1px solid white;padding-bottom:10px;margin-bottom:20px;}.project-body--container .project-body--section h3{font-family:"Montserrat",sans-serif;font-weight:bold;}.project-body--container .project-body--section pre{border-radius:0;}.quickstart--container{border:1px solid #34302d;}.quickstart--container .quickstart--title{font-family:"Montserrat",sans-serif;color:#f1f1f1;background-color:#34302d;font-size:16px;line-height:16px;padding:17px 0;width:211px;text-align:center;display:inline-block;}.quickstart--container .quickstart--dropdown{display:inline-block;width:34.6%;margin-left:16px;}.quickstart--container .quickstart--dropdown .item-dropdown--title{padding:9px 0 7px 20px;border:1px solid #34302d;}.quickstart--container .quickstart--dropdown .item-dropdown--title .icon{margin:-3px 0 0 6px;vertical-align:middle;}.quickstart--container .quickstart--dropdown .item-dropdown--icon{padding:9px;background-color:#34302d;}.quickstart--container .quickstart--dropdown .project-version--dropdown{width:100%%;padding:0;}.quickstart--container .quickstart--dropdown .project-version--dropdown .project-version{color:#f1f1f1;padding:8px 20px;border-top:1px solid #4a4440;cursor:pointer;}.quickstart--container .quickstart--dropdown .project-version--dropdown .project-version .icon{margin:-3px 0 0 6px;vertical-align:middle;}.quickstart--container .quickstart--dropdown .project-version--dropdown .project-version.active{background-color:black;border-color:transparent;}.quickstart--container .quickstart--dropdown .project-version--dropdown .project-version.active:hover{background-color:black;}.quickstart--container .quickstart--dropdown .project-version--dropdown .project-version:first-child{border:none;}.quickstart--container .quickstart--dropdown .project-version--dropdown .project-version:hover{background-color:rgba(0,0,0,0.3);}.quickstart--container .quickstart--dropdown.js-open .item-dropdown--title{border:1px solid #6db33f;}.quickstart--container .quickstart--dropdown:hover .item-dropdown--icon{color:white;}.quickstart--container .quickstart--body{padding:20px;}.project-documentation--container{border-color:#34302d;}.project-documentation--container .item-dropdown--title{background-color:transparent;border-bottom:1px solid #34302d;padding:20px;font-family:"Montserrat",sans-serif;font-size:14px;line-height:14px;}.project-documentation--container .item--dropdown{display:block;position:relative;width:100%;padding:0;border:none;background-color:transparent;}.project-documentation--container .item--dropdown .item--body-title{padding-top:15px;color:#34302d;margin:0 20px;border-color:#d7d5d3;}.project-documentation--container .item--dropdown .item--body--version{margin:0 20px;border-color:#d7d5d3;}.project-documentation--container .item--dropdown .item--body--version p{color:#34302d;display:inline-block;}.project-documentation--container .item--dropdown .item--body--version .icon{vertical-align:top;margin:2px 0 0 6px;}.project-documentation--container .item--dropdown .item--body--version .icon.icon-pre-release{background-color:#34302d;border-radius:2px;}.project-documentation--container .item--dropdown .item--body--version:last-child{margin-bottom:20px;}.project-sub-link--wrapper{padding:20px 20px 18px;}.project-sub-link--wrapper .project-sub-link{background-color:#cbcaca;width:30px;height:30px;display:inline-block;margin-right:2.9%;}.project-sub-link--wrapper .project-sub-link:last-child{margin-right:0;}.project-additional-resource--wrapper{padding:20px;}.project-additional-resource--wrapper h3{margin:5px 0;}.project-additional-resource--wrapper ul{margin:0 0 25px 0;}.project-additional-resource--wrapper ul li{border:none;padding:5px 0;}.project-additional-resource--wrapper ul:last-child{margin-bottom:0;}.github-fork-ribbon--wrapper{width:150px;height:150px;position:absolute;overflow:hidden;margin-top:-102px;z-index:9999;right:0;}.github-fork-ribbon--wrapper .github-fork-ribbon{position:absolute;padding:2px 0;background-color:#34302d;-webkit-box-shadow:0px 2px 3px 0px rgba(0,0,0,0.33);box-shadow:0px 2px 3px 0px rgba(0,0,0,0.33);z-index:9999;top:42px;right:-43px;-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-o-transform:rotate(45deg);}.github-fork-ribbon--wrapper .github-fork-ribbon a{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:500;color:#f1f1f1;text-decoration:none;text-shadow:0 -1px rgba(0,0,0,0.5);text-align:center;width:200px;line-height:20px;display:inline-block;padding:2px 0;border:1px dotted rgba(255,255,255,0.75);border-width:1px 0;}.github-fork-ribbon--wrapper .github-fork-ribbon a i{font-size:23px;vertical-align:middle;margin:0 3px 0 0;color:black;} 2 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.springsource.ide.eclipse.commons.gettingstarted/dashboard/1522593921848/common/css/typography.css: -------------------------------------------------------------------------------- 1 | body, h1, h2, h3, p, input { 2 | margin: 0; 3 | font-weight: 400; 4 | font-family: "Montserrat", sans-serif; 5 | color: #34302d; 6 | } 7 | 8 | h1 { 9 | font-size: 24px; 10 | line-height: 30px; 11 | font-family: "Montserrat", sans-serif; 12 | } 13 | 14 | h2 { 15 | font-size: 18px; 16 | font-weight: 700; 17 | line-height: 24px; 18 | margin-bottom: 10px; 19 | font-family: "Montserrat", sans-serif; 20 | } 21 | 22 | h3 { 23 | font-size: 16px; 24 | line-height: 24px; 25 | margin-bottom: 10px; 26 | font-weight: 700; 27 | } 28 | 29 | p { 30 | font-size: 15px; 31 | line-height: 24px; 32 | } 33 | 34 | p a { 35 | color: #5fa134; 36 | } 37 | 38 | p a:hover { 39 | color: #5fa134; 40 | } 41 | 42 | code { 43 | font-size: 14px; 44 | } 45 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.springsource.ide.eclipse.commons.gettingstarted/dashboard/1522593921848/common/font-custom/fontcustom.woff: -------------------------------------------------------------------------------- 1 | wOFF� 2 | �FFTM�h�xdOS/2�J`A9^FcmapBB��cvt XDgasp���glyf�x���t�head0.6��hhea`$��hmtx�)T"gloca\,,=�B�maxp| r�nameY���post\i�~�2�x�c`d``��+���m�2p31��9�W���L ��\�4T� #x�c`d``<���IFT 3 | P��x�c`d``e d�f& fd�90���x�c`a��������ч1����Je�dha``b`cf��! �5���G�����`�c<��fDR���� 4 | x�c�� ����c>��W�[ ��Cƌ���a���x�c```f�`F���| ��@�G����$�����P� �l 0&#�`b@� �N��D***��L��(�:��  P � 5 | ` 6 | � " bx�}X ��y>���s�<�<��ݻ��{��̾���{�`�zWPc�1f�1;�\9S�!(���X)�X����("��Fm��*TU���T5B���V�RT!U�V@Qz����5�J��9�������?��r ��p�����+\%�d/1�_ׯ(��%E�5I���b� 7 | Hz��^�{��;��w}σ� B~� 8 | %� 9 | ��y�����@�q�n�.��?,6 �¤��0Ϣ���w���s�Q��Q�E�A�~��MH��YӤv��a�� �fQ���_���T 3�7^�eH�x�����;�v@.�[�A�����K�gN?�1 ����w��Y��.N��h��~��ղa��n����OR��X��إ[�sL����}�Ğ�7� � 10 | �h�B���BJZR�󪆢�m���� 11 | XQ]�5`@���Ul��&\�i���P�*��T��sq��ckd#�.�Q���ɝT�����ݹ/u����C���A��8?�woݲ��O�y�ñO&[y����uM���s`w���ʾ}+i<���S����C9�0�R�G)׍kV^��P��J��UL��(J��� 12 | �spTy���R �^�\����Rr�p[A�fro$w�4tz�;D�ߞ.���;�;��n9�G�~o���d������÷]�?�A��I���.�Jd7�����RK������ ����Gaċ�#�b�$-x�,��6��b��R��Dx�(�%p �~`k����z���� n�ף��paϼ*��9J��j����t��q'X���[�-J.�<^̨03C[rnwFoG�R���H.���[h���K�ֈIl�&y�|�|����S�X��������ql"|������5Ew��.h�<̳O�k3�w 14 | ��J�Q�э��Z��D��(�6��=4�6���o(� |a6�a��d 19 | �M����:��_�ݵ�~���i���=�W��w��=LUCa�4�G�[����}��yu�\u�߬���!ڮLܷj��o]�C��gOQjf�5��Uve�薫>R��{.�|&��U���]�A|֕�6D��>�.ڨ��� 20 | �F1 "�(�(t`,Q��; 21 | �lA��6ީe��z�Z�Fό�k� 22 | ��n�"��;�v��Q�9n��DY�m��.�����y�y�Z�b���ݯ��ٚh�iiK�iƨ�'u�0�;.����9���4�[����;xg��"NDE��qY�d�w�}o�y�…�…��� �.\8����a��Ą  23 | 8ƟeԲR�hA<����z�.���gN(?y�";'`]9y?�g<~"|���‹a�"�?~< 24 | �q$�ɏa��\O���8�<�"y��z^C�hU�Kh��6l�]�M��L^>aη��и%�u��d�[�")����]��TF%��FXؕ��$3(�Ǹ%e�!�S ��������~��&B������4[��Ϭlu�-k�n�5� 25 | �B��_m�K�W��v���f��;��-�n��p֘�2]�=�~I��)g���L�@�1j���T��V�H�55���;a�755�>�2�3as�F& _w���4�b�J8-X4�Gl�K^�F���Oa���a�u�l��LB�q[���l��4�KP��N��fu��D,v�� }W��WtCy@�\��Pi�R��sǰth�������xRsݐ��ݍ����1!5�w��j�K���ggP�vpe|����|/ٚLf��`��K�Χ�8���G���L��4Bm^�gn�~��^r���b��� C����3�/ݙ�%�b k���+�;��,��3'L�6�ƴ�g��l�Ǻ�egu��o����g��+�oE+��3����uF�-K9 26 | y�"��mȆaK�F��G}2�?D?�����)0��Q<蔽��Yr�i���G��]�XL&Ξ=�8�Hx�_�VWi�2j�煜�PI�!�Ϗg.���IҶ����2�t��q�q(�eayW)�)(�i"cj�A��2G愥��_�I�?5���~�⭪]�T0�b7���7�^��7~��:h�E��a�N� ���j��ԟ�7\�an��Vp����}.��h���⺯p�п���K��l��\�Iz%�%�>�e�>Φ,���� 31 | ��>C���������^o�Ap��{��V��+������פ�5�jW�p]Q5��{�} 32 | ����bը��?�p�i<�8�g'׬y��e��E�Tu�q�O�Fi{��K�X"�T�$��[��Rs��U�"�H�i��崄3�/$����/?̣g��BV�F(�0-Ф�H�xx��o��������_:��< �ѣ��)��*�1��ܪ��( �R�(�R���T��]�P1[Q�*�T\��GUD�s�Q4š�n8�|�S�����n~FkR��H~[=y���ZT�fc�L��k1�k`h��V�P 33 | �{Qj���8�c��%U1k�WMq&���zͮy��L�Eݲd,��xs�z�i%I7` 34 | �"E����@'ٰa�A1}��z��᯴�7�Z7�`�gM�����鋷_����ۦV��7as�㔊<�u��;jLH����D��_%'К0*�� �ʴc��oe 35 | S�䙬�6�c�.�<��>A��cC+��(N�<*r�׏<�ȥF��?^�6"+ $e.data('title')+"").popover({content:contents,trigger:'click',html:true});});return this;};$(".js-item--open-dropdown").click(function(){var dropdownItem=$(this).parents(".js-item-dropdown--wrapper");var documentHeight=$(document).height();var headerHeight=$("header").outerHeight();var footerHeight=$("footer").outerHeight();var scrimHeight=documentHeight- headerHeight- footerHeight;dropdownItem.toggleClass("js-open");dropdownItem.siblings().removeClass("js-open");$(this).parents(".js-item-dropdown-widget--wrapper").siblings().find(".js-item-dropdown--wrapper").removeClass("js-open");$("#scrim").addClass("js-show").css("height",scrimHeight).css("top",headerHeight);$("#scrim").click(function(){$(".js-item-dropdown--wrapper").removeClass("js-open");$(this).removeClass("js-show");});});$(".js-search-input-open").click(function(){$(".nav-search").addClass("js-highlight");var inputContainer=$(".js-search-dropdown");var input=$(".js-search-input");inputContainer.addClass("js-show");setTimeout(function(){input.focus();},100);$(".body--container, .js-search-input-close, .homepage--body").click(function(){inputContainer.removeClass("js-show");$(".nav-search").removeClass("js-highlight");$("#scrim").removeClass("js-show");});});if(window.location.pathname=="/search"){$(".nav-search").addClass("js-highlight");$(".js-search-dropdown").addClass("js-show no-animation");var searchQuery=decodeURIComponent(window.location.search.replace(/\+/g," "));var seachStart=searchQuery.search("q=");var searchString=searchQuery.substr(seachStart+ 2);$(".js-search-input-close").click(function(){$(".js-search-dropdown").removeClass("js-show no-animation");$(".nav-search").removeClass("js-highlight");});};$.fn.showPreferredLink=function(){this.find("li."+ detectOs()+ detectArch()).show();return this;};$('.download-links').showPreferredLink();var moveItemSlider=function(){var activeItem=$(".js-item-slider--wrapper .js-item.js-active");if(activeItem.length==0){return;}else{var activeItemPosition=activeItem.position();var activeItemOffset=activeItemPosition.left;var activeItemWidth=activeItem.outerWidth();var slider=$(".js-item--slider");var sliderPosition=slider.position();var sliderOffset=sliderPosition.left;var sliderTarget=activeItemOffset- sliderOffset;slider.width(activeItemWidth);slider.css("margin-left",sliderTarget);};} 2 | moveItemSlider();$(".js-item").click(function(){$(this).addClass("js-active");$(this).siblings().removeClass("js-active");moveItemSlider();});window.addEventListener("orientationchange",function(){var deviceHeight=$(window).height();var openDrawer=$(".js-open-nav-drawer.js-slide-right");if(!openDrawer.length){return;}else{$(".viewport").height(deviceHeight).addClass("constrained");}},false);$(".js-open-nav-drawer").click(function(){$(".navigation-drawer--container").addClass("js-open");$(".mobile-nav, .body--container, .homepage--body").addClass("js-slide-right");var deviceHeight=$(window).height();$(".viewport").height(deviceHeight).addClass("constrained");$("#scrim").addClass("js-show js-open-mobile-nav");$("#scrim").click(function(){$(".navigation-drawer--container").removeClass("js-open");$(".mobile-nav, .body--container, .homepage--body").removeClass("js-slide-right");$(".viewport").removeClass("constrained");});});var initializeFacetSearchWidget=function(){var searchFacet=$(".search-facets");if(!searchFacet.length){return;}else{$(".sub-facet--list, .facet-section--header").addClass('js-close');$(".js-toggle-sub-facet-list").click(function(){$(this).closest(".facet").find(".sub-facet--list:first").toggleClass('js-close');});$(".projects-facet .js-toggle-sub-facet-list:first").click(function(){$(".facet-section--header").toggleClass('js-close');});$(".js-checkbox-pill").click(function(){var facet=$(this).closest('.facet');var group=facet.parents(".facet").first();var checkBoxes=facet.find("input[type='checkbox']");var checkBox=checkBoxes.first();var uncheckedCheckBoxes=group.find(".sub-facet--list input[type='checkbox']:not(:checked)");if(checkBox.prop('checked')==false){$(this).prop('checked',false);function firstCheckbox(context){context.siblings(".facet--wrapper").find("input[type='checkbox']").first().prop('checked',false);} 3 | firstCheckbox($(this).parents(".sub-facet--list"));firstCheckbox($(this).closest(".sub-facet--list"));$(this).parents(".facet--wrapper").siblings(".sub-facet--list, .facet-section--header").find("input[type='checkbox']").prop('checked',false);}else{checkBoxes.prop('checked',true);};if(uncheckedCheckBoxes.length==0){group.find("input[type='checkbox']").first().prop('checked',true);}});$('.sub-facet--list').each(function(){var checkedCheckBoxes=$("input[type='checkbox']:checked",this);var uncheckedBoxes=$("input[type='checkbox']:not(:checked)",this);if(checkedCheckBoxes.length!==0&&uncheckedBoxes.length!==0){$(this).removeClass('js-close');}});if($(".projects-facet input[type='checkbox']:checked").length){$(".facet-section--header").removeClass("js-close");$(".projects-facet .sub-facet--list").first().removeClass("js-close");} 4 | $(".facets--clear-filters").click(function(){$(".facet--wrapper input[type='checkbox']:checked").prop('checked',false);$(".sub-facet--list, .facet-section--header").addClass("js-close");});}} 5 | initializeFacetSearchWidget();});var detectOs=function(){if(navigator.appVersion.indexOf("Win")!=-1)return"Windows";if(navigator.appVersion.indexOf("Mac")!=-1)return"Mac";if(navigator.appVersion.indexOf("Linux")!=-1)return"Linux";return"Unknown";} 6 | var detectArch=function(){if(navigator.platform.indexOf("Win64")!==-1){return"64"} 7 | if(navigator.platform.indexOf("Linux x86_64")!==-1){return"64";} 8 | if(/Mac OS X 10.[0-5]/.test(navigator.userAgent)){return"32"} 9 | if(navigator.userAgent.indexOf("Mac OS X")!==-1){return"64"} 10 | return"32";} 11 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.springsource.ide.eclipse.commons.gettingstarted/dashboard/1522593921848/common/js/filter.js: -------------------------------------------------------------------------------- 1 | $.fn.contentFilter=function(){this.keyup(function(){var rex=new RegExp($(this).val(),'i');$('[data-filterable]').each(function(){var filterable=$(this);if(rex.test(filterable.data('filterable'))){filterable.show();}else{filterable.hide();}});$('[data-filterable-container]').each(function(){var container=$(this);container.show();if(container.find('[data-filterable]:visible').length==0){container.hide();}});});}; 2 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.springsource.ide.eclipse.commons.gettingstarted/dashboard/1522593921848/common/js/guide.js: -------------------------------------------------------------------------------- 1 | ZeroClipboard.setDefaults({moviePath:'/js/ZeroClipboard.swf'});$(document).ready(function(){if(ZeroClipboard.detectFlashSupport()){createCodeCopyButtons();createCopyButton($('button.copy-button.github'));} 2 | $('.github-actions button').click(function(){$('.github-actions button').removeClass('active');$(this).addClass('active');$('.clone-url').hide();$('.clone-url.'+ $(this).data('protocol')).show();});if(typeof(sts_import)==='function'){$(".gs-guide-import").show().click(function(e){var linkElement=e.target;var url=linkElement.href;sts_import("guide",url);e.preventDefault();});}});function createCodeCopyButtons(){$('article .highlight pre').each(function(index){var codeBlockId="code-block-"+ index;$(this).attr('id',codeBlockId);var button=$('');$(this).before(button);createCopyButton(button);});} 3 | function createCopyButton($el){if($el.length===0)return;var zero=new ZeroClipboard($el);$(zero.htmlBridge).tooltip({title:"copy to clipboard",placement:'bottom'});} 4 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.springsource.ide.eclipse.commons.gettingstarted/dashboard/1522593921848/common/js/modernizer.flexbox.js: -------------------------------------------------------------------------------- 1 | 2 | /* Modernizr 2.5.3 (Custom Build) | MIT & BSD 3 | * Build: http://www.modernizr.com/download/#-flexbox-flexbox_legacy-cssclasses-testprop-testallprops-domprefixes 4 | */ 5 | ;window.Modernizr=function(a,b,c){function x(a){j.cssText=a}function y(a,b){return x(prefixes.join(a+";")+(b||""))}function z(a,b){return typeof a===b}function A(a,b){return!!~(""+a).indexOf(b)}function B(a,b){for(var d in a)if(j[a[d]]!==c)return b=="pfx"?a[d]:!0;return!1}function C(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:z(f,"function")?f.bind(d||b):f}return!1}function D(a,b,c){var d=a.charAt(0).toUpperCase()+a.substr(1),e=(a+" "+n.join(d+" ")+d).split(" ");return z(b,"string")||z(b,"undefined")?B(e,b):(e=(a+" "+o.join(d+" ")+d).split(" "),C(e,b,c))}var d="2.5.3",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k,l={}.toString,m="Webkit Moz O ms",n=m.split(" "),o=m.toLowerCase().split(" "),p={},q={},r={},s=[],t=s.slice,u,v={}.hasOwnProperty,w;!z(v,"undefined")&&!z(v.call,"undefined")?w=function(a,b){return v.call(a,b)}:w=function(a,b){return b in a&&z(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=t.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(t.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(t.call(arguments)))};return e}),p.flexbox=function(){return D("flexOrder")},p["flexbox-legacy"]=function(){return D("boxDirection")};for(var E in p)w(p,E)&&(u=E.toLowerCase(),e[u]=p[E](),s.push((e[u]?"":"no-")+u));return x(""),i=k=null,e._version=d,e._domPrefixes=o,e._cssomPrefixes=n,e.testProp=function(a){return B([a])},e.testAllProps=D,g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+s.join(" "):""),e}(this,this.document); 6 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.springsource.ide.eclipse.commons.gettingstarted/dashboard/1522593921848/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Spring 5 | 8 | 9 | 11 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 63 |
64 | 103 |
104 |
106 | 107 |
108 |
109 |

Tooling Updates

110 |
111 | Loading updates... 112 |
113 |

News

114 |
115 | Loading feeds... 116 |
117 |
118 | 119 | 133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 | © 141 | 145 | Pivotal Software, Inc. All Rights Reserved. 146 |
147 |
148 |
149 |
150 |
151 | 152 | 153 | -------------------------------------------------------------------------------- /.metadata/.plugins/org.springsource.ide.eclipse.dashboard.ui/feeds/dashboard.feeds.update/623127801.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Spring Tool Suites Updates 5 | https://spring.io/tools 6 | This feeds imforms about important updates relevant to users of STS. 7 | Feeder 2.0.7(1195) http://reinventedsoftware.com/feeder/ 8 | http://blogs.law.harvard.edu/tech/rss 9 | en-us 10 | sts@springsource.com 11 | Thu, 22 Mar 2018 10:38:33 +0100 12 | Thu, 22 Mar 2018 10:38:33 +0100 13 | 14 | 15 | 16 | Thanks for installing STS 3.9.3 17 | http://spring.io/tools 18 |

Pivotal has released an update to Spring Tool Suite (STS), the best Eclipse-powered development environment for building Spring powered enterprise application.

19 |

Please review the following documents:

20 |
  • 3.9.3 New & Noteworthy
  • ]]>
    21 | Thu, 22 Mar 2018 12:13:33 +0100 22 | version=[3.9.3.201803200759-RELEASE,4.0.0) 23 | 24 | thanks-for-installing-sts-393 25 |
    26 | 27 | 28 | STS 3.9.3 has been released 29 | http://spring.io/tools 30 |

    Pivotal has released an update to Spring Tool Suite (STS), the best Eclipse-powered development environment for building Spring powered enterprise application.

    It is recommend to update as soon as possible.

    31 |

    Please review the following documents:

    32 |
  • 3.9.3 New & Noteworthy
  • ]]>
    33 | Thu, 22 Mar 2018 12:12:33 +0100 34 | version=[0,3.9.3.201803200759-RELEASE) 35 | severity=important 36 | sts-393-released 37 |
    38 | 39 |
    40 |
    41 | -------------------------------------------------------------------------------- /.metadata/version.ini: -------------------------------------------------------------------------------- 1 | #Sun Apr 01 07:45:15 PDT 2018 2 | org.eclipse.core.runtime=2 3 | org.eclipse.platform=4.7.2.v20171130-0510 4 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simplyi/springmvc-ws/61338287871b7d6bc65524631d11906a8fd1aa5d/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.3/apache-maven-3.5.3-bin.zip 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # springmvc-ws 2 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Migwn, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | # TODO classpath? 118 | fi 119 | 120 | if [ -z "$JAVA_HOME" ]; then 121 | javaExecutable="`which javac`" 122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 123 | # readlink(1) is not available as standard on Solaris 10. 124 | readLink=`which readlink` 125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 126 | if $darwin ; then 127 | javaHome="`dirname \"$javaExecutable\"`" 128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 129 | else 130 | javaExecutable="`readlink -f \"$javaExecutable\"`" 131 | fi 132 | javaHome="`dirname \"$javaExecutable\"`" 133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 134 | JAVA_HOME="$javaHome" 135 | export JAVA_HOME 136 | fi 137 | fi 138 | fi 139 | 140 | if [ -z "$JAVACMD" ] ; then 141 | if [ -n "$JAVA_HOME" ] ; then 142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 143 | # IBM's JDK on AIX uses strange locations for the executables 144 | JAVACMD="$JAVA_HOME/jre/sh/java" 145 | else 146 | JAVACMD="$JAVA_HOME/bin/java" 147 | fi 148 | else 149 | JAVACMD="`which java`" 150 | fi 151 | fi 152 | 153 | if [ ! -x "$JAVACMD" ] ; then 154 | echo "Error: JAVA_HOME is not defined correctly." >&2 155 | echo " We cannot execute $JAVACMD" >&2 156 | exit 1 157 | fi 158 | 159 | if [ -z "$JAVA_HOME" ] ; then 160 | echo "Warning: JAVA_HOME environment variable is not set." 161 | fi 162 | 163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 164 | 165 | # traverses directory structure from process work directory to filesystem root 166 | # first directory with .mvn subdirectory is considered project base directory 167 | find_maven_basedir() { 168 | 169 | if [ -z "$1" ] 170 | then 171 | echo "Path not specified to find_maven_basedir" 172 | return 1 173 | fi 174 | 175 | basedir="$1" 176 | wdir="$1" 177 | while [ "$wdir" != '/' ] ; do 178 | if [ -d "$wdir"/.mvn ] ; then 179 | basedir=$wdir 180 | break 181 | fi 182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 183 | if [ -d "${wdir}" ]; then 184 | wdir=`cd "$wdir/.."; pwd` 185 | fi 186 | # end of workaround 187 | done 188 | echo "${basedir}" 189 | } 190 | 191 | # concatenates all lines of a file 192 | concat_lines() { 193 | if [ -f "$1" ]; then 194 | echo "$(tr -s '\n' ' ' < "$1")" 195 | fi 196 | } 197 | 198 | BASE_DIR=`find_maven_basedir "$(pwd)"` 199 | if [ -z "$BASE_DIR" ]; then 200 | exit 1; 201 | fi 202 | 203 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 204 | echo $MAVEN_PROJECTBASEDIR 205 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 206 | 207 | # For Cygwin, switch paths to Windows format before running java 208 | if $cygwin; then 209 | [ -n "$M2_HOME" ] && 210 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 211 | [ -n "$JAVA_HOME" ] && 212 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 213 | [ -n "$CLASSPATH" ] && 214 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 215 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 216 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 217 | fi 218 | 219 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 220 | 221 | exec "$JAVACMD" \ 222 | $MAVEN_OPTS \ 223 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 224 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 225 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 226 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 84 | @REM Fallback to current working directory if not found. 85 | 86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 88 | 89 | set EXEC_DIR=%CD% 90 | set WDIR=%EXEC_DIR% 91 | :findBaseDir 92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 93 | cd .. 94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 95 | set WDIR=%CD% 96 | goto findBaseDir 97 | 98 | :baseDirFound 99 | set MAVEN_PROJECTBASEDIR=%WDIR% 100 | cd "%EXEC_DIR%" 101 | goto endDetectBaseDir 102 | 103 | :baseDirNotFound 104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 105 | cd "%EXEC_DIR%" 106 | 107 | :endDetectBaseDir 108 | 109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 110 | 111 | @setlocal EnableExtensions EnableDelayedExpansion 112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 114 | 115 | :endReadAdditionalConfig 116 | 117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 118 | 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 123 | if ERRORLEVEL 1 goto error 124 | goto end 125 | 126 | :error 127 | set ERROR_CODE=1 128 | 129 | :end 130 | @endlocal & set ERROR_CODE=%ERROR_CODE% 131 | 132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 136 | :skipRcPost 137 | 138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 140 | 141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 142 | 143 | exit /B %ERROR_CODE% 144 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.appsdeveloperblog.app.ws 7 | mobile-app-ws 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | mobile-app-ws 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.0.1.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-web 31 | 32 | 33 | com.fasterxml.jackson.dataformat 34 | jackson-dataformat-xml 35 | 36 | 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-starter-data-jpa 41 | 42 | 43 | 44 | 45 | mysql 46 | mysql-connector-java 47 | 48 | 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-starter-security 53 | 54 | 55 | 56 | io.jsonwebtoken 57 | jjwt 58 | 0.9.0 59 | 60 | 61 | 62 | 63 | org.springframework.boot 64 | spring-boot-starter-tomcat 65 | 66 | 67 | 68 | org.modelmapper 69 | modelmapper 70 | 2.0.0 71 | 72 | 73 | 74 | org.springframework.boot 75 | spring-boot-starter-hateoas 76 | 77 | 78 | 79 | 80 | com.amazonaws 81 | aws-java-sdk-ses 82 | 1.11.362 83 | 84 | 85 | 86 | org.springframework.boot 87 | spring-boot-starter-test 88 | test 89 | 90 | 91 | 92 | org.junit.jupiter 93 | junit-jupiter-engine 94 | test 95 | 96 | 97 | 98 | 99 | com.h2database 100 | h2 101 | runtime 102 | 103 | 104 | 105 | 106 | 107 | io.springfox 108 | springfox-swagger2 109 | 2.9.2 110 | 111 | 112 | 113 | 114 | io.springfox 115 | springfox-swagger-ui 116 | 2.9.2 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | org.springframework.boot 127 | spring-boot-maven-plugin 128 | 129 | 130 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/MobileAppWsApplication.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.builder.SpringApplicationBuilder; 6 | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 9 | 10 | import com.appsdeveloperblog.app.ws.security.AppProperties; 11 | import com.appsdeveloperblog.app.ws.shared.AmazonSES; 12 | 13 | @SpringBootApplication 14 | public class MobileAppWsApplication extends SpringBootServletInitializer { 15 | 16 | @Override 17 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 18 | return application.sources(MobileAppWsApplication.class); 19 | } 20 | 21 | public static void main(String[] args) { 22 | SpringApplication.run(MobileAppWsApplication.class, args); 23 | } 24 | 25 | @Bean 26 | public BCryptPasswordEncoder bCryptPasswordEncoder() { 27 | return new BCryptPasswordEncoder(); 28 | } 29 | 30 | @Bean 31 | public AmazonSES getAmazonSES() { 32 | return new AmazonSES(); 33 | } 34 | 35 | @Bean 36 | public SpringApplicationContext springApplicationContext() 37 | { 38 | return new SpringApplicationContext(); 39 | } 40 | 41 | @Bean(name="AppProperties") 42 | public AppProperties getAppProperties() 43 | { 44 | return new AppProperties(); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/SpringApplicationContext.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.context.ApplicationContext; 5 | import org.springframework.context.ApplicationContextAware; 6 | 7 | public class SpringApplicationContext implements ApplicationContextAware { 8 | private static ApplicationContext CONTEXT; 9 | 10 | @Override 11 | public void setApplicationContext(ApplicationContext context) throws BeansException { 12 | CONTEXT = context; 13 | } 14 | 15 | public static Object getBean(String beanName) { 16 | return CONTEXT.getBean(beanName); 17 | } 18 | } -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/SwaggerConfig.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.HashSet; 6 | import java.util.List; 7 | 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.context.annotation.Configuration; 10 | 11 | import springfox.documentation.builders.PathSelectors; 12 | import springfox.documentation.builders.RequestHandlerSelectors; 13 | import springfox.documentation.service.ApiInfo; 14 | import springfox.documentation.service.Contact; 15 | import springfox.documentation.service.VendorExtension; 16 | import springfox.documentation.spi.DocumentationType; 17 | import springfox.documentation.spring.web.plugins.Docket; 18 | import springfox.documentation.swagger2.annotations.EnableSwagger2; 19 | 20 | @Configuration 21 | @EnableSwagger2 22 | public class SwaggerConfig { 23 | 24 | Contact contact = new Contact( 25 | "Sergey Kargopolov", 26 | "http://www.appsdeveloperblog.com", 27 | "developer@appsdeveloperblog.com" 28 | ); 29 | 30 | List vendorExtensions = new ArrayList<>(); 31 | 32 | ApiInfo apiInfo = new ApiInfo( 33 | "Photo app RESTful Web Service documentation", 34 | "This pages documents Photo app RESTful Web Service endpoints", 35 | "1.0", 36 | "http://www.appsdeveloperblog.com/service.html", 37 | contact, 38 | "Apache 2.0", 39 | "http://www.apache.org/licenses/LICENSE-2.0", 40 | vendorExtensions); 41 | 42 | @Bean 43 | public Docket apiDocket() { 44 | 45 | Docket docket = new Docket(DocumentationType.SWAGGER_2) 46 | .protocols(new HashSet<>(Arrays.asList("HTTP","HTTPs"))) 47 | .apiInfo(apiInfo) 48 | .select() 49 | .apis(RequestHandlerSelectors.basePackage("com.appsdeveloperblog.app.ws")).paths(PathSelectors.any()) 50 | .build(); 51 | 52 | return docket; 53 | 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/WebConfig.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.web.servlet.config.annotation.CorsRegistry; 5 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 6 | 7 | @Configuration 8 | public class WebConfig implements WebMvcConfigurer { 9 | 10 | @Override 11 | public void addCorsMappings(CorsRegistry registry) { 12 | 13 | registry 14 | .addMapping("/**") 15 | .allowedMethods("*") 16 | .allowedOrigins("*"); 17 | 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/exceptions/AppExceptionsHandler.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.exceptions; 2 | 3 | import java.util.Date; 4 | 5 | import org.springframework.http.HttpHeaders; 6 | import org.springframework.http.HttpStatus; 7 | import org.springframework.http.ResponseEntity; 8 | import org.springframework.web.bind.annotation.ControllerAdvice; 9 | import org.springframework.web.bind.annotation.ExceptionHandler; 10 | import org.springframework.web.context.request.WebRequest; 11 | 12 | import com.appsdeveloperblog.app.ws.ui.model.response.ErrorMessage; 13 | 14 | @ControllerAdvice 15 | public class AppExceptionsHandler { 16 | 17 | @ExceptionHandler(value = {UserServiceException.class}) 18 | public ResponseEntity handleUserServiceException(UserServiceException ex, WebRequest request) 19 | { 20 | ErrorMessage errorMessage = new ErrorMessage(new Date(), ex.getMessage()); 21 | 22 | return new ResponseEntity<>(errorMessage, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR); 23 | } 24 | 25 | 26 | @ExceptionHandler(value = {Exception.class}) 27 | public ResponseEntity handleOtherExceptions(Exception ex, WebRequest request) 28 | { 29 | ErrorMessage errorMessage = new ErrorMessage(new Date(), ex.getMessage()); 30 | 31 | return new ResponseEntity<>(errorMessage, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/exceptions/UserServiceException.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.exceptions; 2 | 3 | public class UserServiceException extends RuntimeException{ 4 | 5 | private static final long serialVersionUID = 1348771109171435607L; 6 | 7 | public UserServiceException(String message) 8 | { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/io/entity/AddressEntity.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.io.entity; 2 | 3 | import java.io.Serializable; 4 | 5 | import javax.persistence.Column; 6 | import javax.persistence.Entity; 7 | import javax.persistence.GeneratedValue; 8 | import javax.persistence.Id; 9 | import javax.persistence.JoinColumn; 10 | import javax.persistence.ManyToOne; 11 | 12 | @Entity(name="addresses") 13 | public class AddressEntity implements Serializable { 14 | 15 | private static final long serialVersionUID = 7809200551672852690L; 16 | 17 | @Id 18 | @GeneratedValue 19 | private long id; 20 | 21 | @Column(length=30, nullable=false) 22 | private String addressId; 23 | 24 | @Column(length=15, nullable=false) 25 | private String city; 26 | 27 | @Column(length=15, nullable=false) 28 | private String country; 29 | 30 | @Column(length=100, nullable=false) 31 | private String streetName; 32 | 33 | @Column(length=7, nullable=false) 34 | private String postalCode; 35 | 36 | @Column(length=10, nullable=false) 37 | private String type; 38 | 39 | @ManyToOne 40 | @JoinColumn(name="users_id") 41 | private UserEntity userDetails; 42 | 43 | public long getId() { 44 | return id; 45 | } 46 | 47 | public void setId(long id) { 48 | this.id = id; 49 | } 50 | 51 | public String getAddressId() { 52 | return addressId; 53 | } 54 | 55 | public void setAddressId(String addressId) { 56 | this.addressId = addressId; 57 | } 58 | 59 | public String getCity() { 60 | return city; 61 | } 62 | 63 | public void setCity(String city) { 64 | this.city = city; 65 | } 66 | 67 | public String getCountry() { 68 | return country; 69 | } 70 | 71 | public void setCountry(String country) { 72 | this.country = country; 73 | } 74 | 75 | public String getStreetName() { 76 | return streetName; 77 | } 78 | 79 | public void setStreetName(String streetName) { 80 | this.streetName = streetName; 81 | } 82 | 83 | public String getPostalCode() { 84 | return postalCode; 85 | } 86 | 87 | public void setPostalCode(String postalCode) { 88 | this.postalCode = postalCode; 89 | } 90 | 91 | public String getType() { 92 | return type; 93 | } 94 | 95 | public void setType(String type) { 96 | this.type = type; 97 | } 98 | 99 | public UserEntity getUserDetails() { 100 | return userDetails; 101 | } 102 | 103 | public void setUserDetails(UserEntity userDetails) { 104 | this.userDetails = userDetails; 105 | } 106 | 107 | 108 | 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/io/entity/PasswordResetTokenEntity.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.io.entity; 2 | 3 | import java.io.Serializable; 4 | 5 | import javax.persistence.Entity; 6 | import javax.persistence.GeneratedValue; 7 | import javax.persistence.Id; 8 | import javax.persistence.JoinColumn; 9 | import javax.persistence.OneToOne; 10 | 11 | @Entity(name = "password_reset_tokens") 12 | public class PasswordResetTokenEntity implements Serializable { 13 | 14 | /** 15 | * 16 | */ 17 | private static final long serialVersionUID = 8051324316462829780L; 18 | 19 | @Id 20 | @GeneratedValue 21 | private long id; 22 | 23 | private String token; 24 | 25 | @OneToOne() 26 | @JoinColumn(name = "users_id") 27 | private UserEntity userDetails; 28 | 29 | public long getId() { 30 | return id; 31 | } 32 | 33 | public void setId(long id) { 34 | this.id = id; 35 | } 36 | 37 | public String getToken() { 38 | return token; 39 | } 40 | 41 | public void setToken(String token) { 42 | this.token = token; 43 | } 44 | 45 | public UserEntity getUserDetails() { 46 | return userDetails; 47 | } 48 | 49 | public void setUserDetails(UserEntity userDetails) { 50 | this.userDetails = userDetails; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/io/entity/UserEntity.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.io.entity; 2 | 3 | import java.io.Serializable; 4 | import java.util.List; 5 | 6 | import javax.persistence.CascadeType; 7 | import javax.persistence.Column; 8 | import javax.persistence.Entity; 9 | import javax.persistence.GeneratedValue; 10 | import javax.persistence.Id; 11 | import javax.persistence.OneToMany; 12 | import javax.persistence.Table; 13 | 14 | @Entity 15 | @Table(name="users") 16 | public class UserEntity implements Serializable { 17 | 18 | private static final long serialVersionUID = 5313493413859894403L; 19 | 20 | @Id 21 | @GeneratedValue 22 | private long id; 23 | 24 | @Column(nullable=false) 25 | private String userId; 26 | 27 | @Column(nullable=false, length=50) 28 | private String firstName; 29 | 30 | @Column(nullable=false, length=50) 31 | private String lastName; 32 | 33 | @Column(nullable=false, length=120) 34 | private String email; 35 | 36 | @Column(nullable=false) 37 | private String encryptedPassword; 38 | 39 | private String emailVerificationToken; 40 | 41 | @Column(nullable=false) 42 | private Boolean emailVerificationStatus = false; 43 | 44 | @OneToMany(mappedBy="userDetails", cascade=CascadeType.ALL) 45 | private List addresses; 46 | 47 | public long getId() { 48 | return id; 49 | } 50 | 51 | public void setId(long id) { 52 | this.id = id; 53 | } 54 | 55 | public String getUserId() { 56 | return userId; 57 | } 58 | 59 | public void setUserId(String userId) { 60 | this.userId = userId; 61 | } 62 | 63 | public String getFirstName() { 64 | return firstName; 65 | } 66 | 67 | public void setFirstName(String firstName) { 68 | this.firstName = firstName; 69 | } 70 | 71 | public String getLastName() { 72 | return lastName; 73 | } 74 | 75 | public void setLastName(String lastName) { 76 | this.lastName = lastName; 77 | } 78 | 79 | public String getEmail() { 80 | return email; 81 | } 82 | 83 | public void setEmail(String email) { 84 | this.email = email; 85 | } 86 | 87 | public String getEncryptedPassword() { 88 | return encryptedPassword; 89 | } 90 | 91 | public void setEncryptedPassword(String encryptedPassword) { 92 | this.encryptedPassword = encryptedPassword; 93 | } 94 | 95 | public String getEmailVerificationToken() { 96 | return emailVerificationToken; 97 | } 98 | 99 | public void setEmailVerificationToken(String emailVerificationToken) { 100 | this.emailVerificationToken = emailVerificationToken; 101 | } 102 | 103 | public Boolean getEmailVerificationStatus() { 104 | return emailVerificationStatus; 105 | } 106 | 107 | public void setEmailVerificationStatus(Boolean emailVerificationStatus) { 108 | this.emailVerificationStatus = emailVerificationStatus; 109 | } 110 | 111 | public List getAddresses() { 112 | return addresses; 113 | } 114 | 115 | public void setAddresses(List addresses) { 116 | this.addresses = addresses; 117 | } 118 | 119 | 120 | 121 | } 122 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/io/repository/AddressRepository.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.io.repository; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.repository.CrudRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import com.appsdeveloperblog.app.ws.io.entity.AddressEntity; 9 | import com.appsdeveloperblog.app.ws.io.entity.UserEntity; 10 | 11 | @Repository 12 | public interface AddressRepository extends CrudRepository { 13 | List findAllByUserDetails(UserEntity userEntity); 14 | AddressEntity findByAddressId(String addressId); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/io/repository/PasswordResetTokenRepository.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.io.repository; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | import com.appsdeveloperblog.app.ws.io.entity.PasswordResetTokenEntity; 6 | 7 | public interface PasswordResetTokenRepository extends CrudRepository{ 8 | PasswordResetTokenEntity findByToken(String token); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/io/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.io.repository; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.domain.Page; 6 | import org.springframework.data.domain.Pageable; 7 | import org.springframework.data.jpa.repository.Modifying; 8 | import org.springframework.data.jpa.repository.Query; 9 | import org.springframework.data.repository.PagingAndSortingRepository; 10 | import org.springframework.data.repository.query.Param; 11 | import org.springframework.stereotype.Repository; 12 | import org.springframework.transaction.annotation.Transactional; 13 | 14 | import com.appsdeveloperblog.app.ws.io.entity.UserEntity; 15 | 16 | @Repository 17 | public interface UserRepository extends PagingAndSortingRepository { 18 | UserEntity findByEmail(String email); 19 | UserEntity findByUserId(String userId); 20 | UserEntity findUserByEmailVerificationToken(String token); 21 | 22 | @Query(value="select * from Users u where u.EMAIL_VERIFICATION_STATUS = 'true'", 23 | countQuery="select count(*) from Users u where u.EMAIL_VERIFICATION_STATUS = 'true'", 24 | nativeQuery = true) 25 | Page findAllUsersWithConfirmedEmailAddress( Pageable pageableRequest ); 26 | 27 | @Query(value="select * from Users u where u.first_name = ?1",nativeQuery=true) 28 | List findUserByFirstName(String firstName); 29 | 30 | @Query(value="select * from Users u where u.last_name = :lastName",nativeQuery=true) 31 | List findUserByLastName(@Param("lastName") String lastName); 32 | 33 | @Query(value="select * from Users u where first_name LIKE %:keyword% or last_name LIKE %:keyword%",nativeQuery=true) 34 | List findUsersByKeyword(@Param("keyword") String keyword); 35 | 36 | @Query(value="select u.first_name, u.last_name from Users u where u.first_name LIKE %:keyword% or u.last_name LIKE %:keyword%",nativeQuery=true) 37 | List findUserFirstNameAndLastNameByKeyword(@Param("keyword") String keyword); 38 | 39 | @Transactional 40 | @Modifying 41 | @Query(value="update users u set u.EMAIL_VERIFICATION_STATUS=:emailVerificationStatus where u.user_id=:userId", nativeQuery=true) 42 | void updateUserEmailVerificationStatus(@Param("emailVerificationStatus") boolean emailVerificationStatus, 43 | @Param("userId") String userId); 44 | 45 | @Query("select user from UserEntity user where user.userId =:userId") 46 | UserEntity findUserEntityByUserId(@Param("userId") String userId); 47 | 48 | @Query("select user.firstName, user.lastName from UserEntity user where user.userId =:userId") 49 | List getUserEntityFullNameById(@Param("userId") String userId); 50 | 51 | @Modifying 52 | @Transactional 53 | @Query("UPDATE UserEntity u set u.emailVerificationStatus =:emailVerificationStatus where u.userId = :userId") 54 | void updateUserEntityEmailVerificationStatus( 55 | @Param("emailVerificationStatus") boolean emailVerificationStatus, 56 | @Param("userId") String userId); 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/security/AppProperties.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.security; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.core.env.Environment; 5 | import org.springframework.stereotype.Component; 6 | 7 | @Component 8 | public class AppProperties { 9 | 10 | @Autowired 11 | private Environment env; 12 | 13 | public String getTokenSecret() 14 | { 15 | return env.getProperty("tokenSecret"); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/security/AuthenticationFilter.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.security; 2 | 3 | import java.io.IOException; 4 | import java.util.ArrayList; 5 | import java.util.Date; 6 | 7 | import javax.servlet.FilterChain; 8 | import javax.servlet.ServletException; 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletResponse; 11 | 12 | import org.springframework.security.authentication.AuthenticationManager; 13 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 14 | import org.springframework.security.core.Authentication; 15 | import org.springframework.security.core.AuthenticationException; 16 | import org.springframework.security.core.userdetails.User; 17 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 18 | 19 | import com.appsdeveloperblog.app.ws.SpringApplicationContext; 20 | import com.appsdeveloperblog.app.ws.service.UserService; 21 | import com.appsdeveloperblog.app.ws.shared.dto.UserDto; 22 | import com.appsdeveloperblog.app.ws.ui.model.request.UserLoginRequestModel; 23 | import com.fasterxml.jackson.databind.ObjectMapper; 24 | 25 | import io.jsonwebtoken.Jwts; 26 | import io.jsonwebtoken.SignatureAlgorithm; 27 | 28 | public class AuthenticationFilter extends UsernamePasswordAuthenticationFilter { 29 | private final AuthenticationManager authenticationManager; 30 | 31 | private String contentType; 32 | 33 | public AuthenticationFilter(AuthenticationManager authenticationManager) { 34 | this.authenticationManager = authenticationManager; 35 | } 36 | 37 | @Override 38 | public Authentication attemptAuthentication(HttpServletRequest req, 39 | HttpServletResponse res) throws AuthenticationException { 40 | try { 41 | 42 | contentType = req.getHeader("Accept"); 43 | 44 | UserLoginRequestModel creds = new ObjectMapper() 45 | .readValue(req.getInputStream(), UserLoginRequestModel.class); 46 | 47 | return authenticationManager.authenticate( 48 | new UsernamePasswordAuthenticationToken( 49 | creds.getEmail(), 50 | creds.getPassword(), 51 | new ArrayList<>()) 52 | ); 53 | 54 | } catch (IOException e) { 55 | throw new RuntimeException(e); 56 | } 57 | } 58 | 59 | @Override 60 | protected void successfulAuthentication(HttpServletRequest req, 61 | HttpServletResponse res, 62 | FilterChain chain, 63 | Authentication auth) throws IOException, ServletException { 64 | 65 | String userName = ((User) auth.getPrincipal()).getUsername(); 66 | 67 | String token = Jwts.builder() 68 | .setSubject(userName) 69 | .setExpiration(new Date(System.currentTimeMillis() + SecurityConstants.EXPIRATION_TIME)) 70 | .signWith(SignatureAlgorithm.HS512, SecurityConstants.getTokenSecret() ) 71 | .compact(); 72 | UserService userService = (UserService)SpringApplicationContext.getBean("userServiceImpl"); 73 | UserDto userDto = userService.getUser(userName); 74 | 75 | res.addHeader(SecurityConstants.HEADER_STRING, SecurityConstants.TOKEN_PREFIX + token); 76 | res.addHeader("UserID", userDto.getUserId()); 77 | 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/security/AuthorizationFilter.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.security; 2 | 3 | import java.io.IOException; 4 | import java.util.ArrayList; 5 | 6 | import javax.servlet.FilterChain; 7 | import javax.servlet.ServletException; 8 | import javax.servlet.http.HttpServletRequest; 9 | import javax.servlet.http.HttpServletResponse; 10 | 11 | import org.springframework.security.authentication.AuthenticationManager; 12 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 13 | import org.springframework.security.core.context.SecurityContextHolder; 14 | import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; 15 | 16 | import io.jsonwebtoken.Jwts; 17 | 18 | public class AuthorizationFilter extends BasicAuthenticationFilter { 19 | 20 | public AuthorizationFilter(AuthenticationManager authManager) { 21 | super(authManager); 22 | } 23 | 24 | @Override 25 | protected void doFilterInternal(HttpServletRequest req, 26 | HttpServletResponse res, 27 | FilterChain chain) throws IOException, ServletException { 28 | 29 | String header = req.getHeader(SecurityConstants.HEADER_STRING); 30 | 31 | if (header == null || !header.startsWith(SecurityConstants.TOKEN_PREFIX)) { 32 | chain.doFilter(req, res); 33 | return; 34 | } 35 | 36 | UsernamePasswordAuthenticationToken authentication = getAuthentication(req); 37 | SecurityContextHolder.getContext().setAuthentication(authentication); 38 | chain.doFilter(req, res); 39 | } 40 | 41 | private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) { 42 | String token = request.getHeader(SecurityConstants.HEADER_STRING); 43 | 44 | if (token != null) { 45 | 46 | token = token.replace(SecurityConstants.TOKEN_PREFIX, ""); 47 | 48 | String user = Jwts.parser() 49 | .setSigningKey( SecurityConstants.getTokenSecret() ) 50 | .parseClaimsJws( token ) 51 | .getBody() 52 | .getSubject(); 53 | 54 | if (user != null) { 55 | return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>()); 56 | } 57 | 58 | return null; 59 | } 60 | 61 | return null; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/security/SecurityConstants.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.security; 2 | 3 | import com.appsdeveloperblog.app.ws.SpringApplicationContext; 4 | 5 | public class SecurityConstants { 6 | public static final long EXPIRATION_TIME = 864000000; // 10 days 7 | public static final long PASSWORD_RESET_EXPIRATION_TIME = 3600000; // 1 hour 8 | public static final String TOKEN_PREFIX = "Bearer "; 9 | public static final String HEADER_STRING = "Authorization"; 10 | public static final String SIGN_UP_URL = "/users"; 11 | public static final String VERIFICATION_EMAIL_URL = "/users/email-verification"; 12 | public static final String PASSWORD_RESET_REQUEST_URL = "/users/password-reset-request"; 13 | public static final String PASSWORD_RESET_URL = "/users/password-reset"; 14 | public static final String H2_CONSOLE = "/h2-console/**"; 15 | 16 | public static String getTokenSecret() 17 | { 18 | AppProperties appProperties = (AppProperties) SpringApplicationContext.getBean("AppProperties"); 19 | return appProperties.getTokenSecret(); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/security/WebSecurity.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.security; 2 | 3 | import java.util.Arrays; 4 | 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.http.HttpMethod; 7 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 8 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 9 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 10 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 11 | import org.springframework.security.config.http.SessionCreationPolicy; 12 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 13 | import org.springframework.web.cors.CorsConfiguration; 14 | import org.springframework.web.cors.CorsConfigurationSource; 15 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource; 16 | 17 | import com.appsdeveloperblog.app.ws.service.UserService; 18 | 19 | @EnableWebSecurity 20 | public class WebSecurity extends WebSecurityConfigurerAdapter{ 21 | 22 | private final UserService userDetailsService; 23 | private final BCryptPasswordEncoder bCryptPasswordEncoder; 24 | 25 | public WebSecurity(UserService userDetailsService, BCryptPasswordEncoder bCryptPasswordEncoder) { 26 | this.userDetailsService = userDetailsService; 27 | this.bCryptPasswordEncoder = bCryptPasswordEncoder; 28 | } 29 | 30 | @Override 31 | protected void configure(HttpSecurity http) throws Exception { 32 | http 33 | .cors().and() 34 | .csrf().disable().authorizeRequests() 35 | .antMatchers(HttpMethod.POST, SecurityConstants.SIGN_UP_URL) 36 | .permitAll() 37 | .antMatchers(HttpMethod.GET, SecurityConstants.VERIFICATION_EMAIL_URL) 38 | .permitAll() 39 | .antMatchers(HttpMethod.POST, SecurityConstants.PASSWORD_RESET_REQUEST_URL) 40 | .permitAll() 41 | .antMatchers(HttpMethod.POST, SecurityConstants.PASSWORD_RESET_URL) 42 | .permitAll() 43 | .antMatchers(SecurityConstants.H2_CONSOLE) 44 | .permitAll() 45 | .antMatchers("/v2/api-docs", "/configuration/**", "/swagger*/**", "/webjars/**") 46 | .permitAll() 47 | .anyRequest().authenticated().and() 48 | .addFilter(getAuthenticationFilter()) 49 | .addFilter(new AuthorizationFilter(authenticationManager())) 50 | .sessionManagement() 51 | .sessionCreationPolicy(SessionCreationPolicy.STATELESS); 52 | 53 | http.headers().frameOptions().disable(); 54 | } 55 | 56 | @Override 57 | protected void configure(AuthenticationManagerBuilder auth) throws Exception { 58 | auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder); 59 | } 60 | 61 | protected AuthenticationFilter getAuthenticationFilter() throws Exception { 62 | final AuthenticationFilter filter = new AuthenticationFilter(authenticationManager()); 63 | filter.setFilterProcessesUrl("/users/login"); 64 | return filter; 65 | } 66 | 67 | @Bean 68 | public CorsConfigurationSource corsConfigurationSource() 69 | { 70 | final CorsConfiguration configuration = new CorsConfiguration(); 71 | 72 | configuration.setAllowedOrigins(Arrays.asList("*")); 73 | configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE","OPTIONS")); 74 | configuration.setAllowCredentials(true); 75 | configuration.setAllowedHeaders(Arrays.asList("*")); 76 | 77 | final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); 78 | source.registerCorsConfiguration("/**", configuration); 79 | 80 | return source; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/service/AddressService.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.service; 2 | 3 | import java.util.List; 4 | 5 | import com.appsdeveloperblog.app.ws.shared.dto.AddressDTO; 6 | 7 | public interface AddressService { 8 | List getAddresses(String userId); 9 | AddressDTO getAddress(String addressId); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.service; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.security.core.userdetails.UserDetailsService; 6 | 7 | import com.appsdeveloperblog.app.ws.shared.dto.UserDto; 8 | 9 | public interface UserService extends UserDetailsService{ 10 | UserDto createUser(UserDto user); 11 | UserDto getUser(String email); 12 | UserDto getUserByUserId(String userId); 13 | UserDto updateUser(String userId, UserDto user); 14 | void deleteUser(String userId); 15 | List getUsers(int page, int limit); 16 | boolean verifyEmailToken(String token); 17 | boolean requestPasswordReset(String email); 18 | boolean resetPassword(String token, String password); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/service/impl/AddressServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.service.impl; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import org.modelmapper.ModelMapper; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Service; 9 | 10 | import com.appsdeveloperblog.app.ws.io.entity.AddressEntity; 11 | import com.appsdeveloperblog.app.ws.io.entity.UserEntity; 12 | import com.appsdeveloperblog.app.ws.io.repository.AddressRepository; 13 | import com.appsdeveloperblog.app.ws.io.repository.UserRepository; 14 | import com.appsdeveloperblog.app.ws.service.AddressService; 15 | import com.appsdeveloperblog.app.ws.shared.dto.AddressDTO; 16 | 17 | @Service 18 | public class AddressServiceImpl implements AddressService { 19 | 20 | @Autowired 21 | UserRepository userRepository; 22 | 23 | @Autowired 24 | AddressRepository addressRepository; 25 | 26 | @Override 27 | public List getAddresses(String userId) { 28 | List returnValue = new ArrayList<>(); 29 | ModelMapper modelMapper = new ModelMapper(); 30 | 31 | UserEntity userEntity = userRepository.findByUserId(userId); 32 | if(userEntity==null) return returnValue; 33 | 34 | Iterable addresses = addressRepository.findAllByUserDetails(userEntity); 35 | for(AddressEntity addressEntity:addresses) 36 | { 37 | returnValue.add( modelMapper.map(addressEntity, AddressDTO.class) ); 38 | } 39 | 40 | return returnValue; 41 | } 42 | 43 | @Override 44 | public AddressDTO getAddress(String addressId) { 45 | AddressDTO returnValue = null; 46 | 47 | AddressEntity addressEntity = addressRepository.findByAddressId(addressId); 48 | 49 | if(addressEntity!=null) 50 | { 51 | returnValue = new ModelMapper().map(addressEntity, AddressDTO.class); 52 | } 53 | 54 | return returnValue; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.service.impl; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import org.modelmapper.ModelMapper; 7 | import org.springframework.beans.BeanUtils; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.data.domain.Page; 10 | import org.springframework.data.domain.PageRequest; 11 | import org.springframework.data.domain.Pageable; 12 | import org.springframework.security.core.userdetails.User; 13 | import org.springframework.security.core.userdetails.UserDetails; 14 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 15 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 16 | import org.springframework.stereotype.Service; 17 | import org.springframework.transaction.annotation.Transactional; 18 | 19 | import com.appsdeveloperblog.app.ws.exceptions.UserServiceException; 20 | import com.appsdeveloperblog.app.ws.io.entity.PasswordResetTokenEntity; 21 | import com.appsdeveloperblog.app.ws.io.entity.UserEntity; 22 | import com.appsdeveloperblog.app.ws.io.repository.PasswordResetTokenRepository; 23 | import com.appsdeveloperblog.app.ws.io.repository.UserRepository; 24 | import com.appsdeveloperblog.app.ws.service.UserService; 25 | import com.appsdeveloperblog.app.ws.shared.AmazonSES; 26 | import com.appsdeveloperblog.app.ws.shared.Utils; 27 | import com.appsdeveloperblog.app.ws.shared.dto.AddressDTO; 28 | import com.appsdeveloperblog.app.ws.shared.dto.UserDto; 29 | import com.appsdeveloperblog.app.ws.ui.model.response.ErrorMessages; 30 | 31 | @Service 32 | public class UserServiceImpl implements UserService { 33 | 34 | @Autowired 35 | UserRepository userRepository; 36 | 37 | @Autowired 38 | Utils utils; 39 | 40 | @Autowired 41 | BCryptPasswordEncoder bCryptPasswordEncoder; 42 | 43 | @Autowired 44 | PasswordResetTokenRepository passwordResetTokenRepository; 45 | 46 | @Autowired 47 | AmazonSES amazonSES; 48 | 49 | @Override 50 | public UserDto createUser(UserDto user) { 51 | 52 | if (userRepository.findByEmail(user.getEmail()) != null) 53 | throw new UserServiceException("Record already exists"); 54 | 55 | for(int i=0;i()); 107 | 108 | //return new User(userEntity.getEmail(), userEntity.getEncryptedPassword(), new ArrayList<>()); 109 | } 110 | 111 | @Override 112 | public UserDto getUserByUserId(String userId) { 113 | UserDto returnValue = new UserDto(); 114 | UserEntity userEntity = userRepository.findByUserId(userId); 115 | 116 | if (userEntity == null) 117 | throw new UsernameNotFoundException("User with ID: " + userId + " not found"); 118 | 119 | BeanUtils.copyProperties(userEntity, returnValue); 120 | 121 | return returnValue; 122 | } 123 | 124 | @Override 125 | public UserDto updateUser(String userId, UserDto user) { 126 | UserDto returnValue = new UserDto(); 127 | 128 | UserEntity userEntity = userRepository.findByUserId(userId); 129 | 130 | if (userEntity == null) 131 | throw new UserServiceException(ErrorMessages.NO_RECORD_FOUND.getErrorMessage()); 132 | 133 | userEntity.setFirstName(user.getFirstName()); 134 | userEntity.setLastName(user.getLastName()); 135 | 136 | UserEntity updatedUserDetails = userRepository.save(userEntity); 137 | returnValue = new ModelMapper().map(updatedUserDetails, UserDto.class); 138 | 139 | return returnValue; 140 | } 141 | 142 | @Transactional 143 | @Override 144 | public void deleteUser(String userId) { 145 | UserEntity userEntity = userRepository.findByUserId(userId); 146 | 147 | if (userEntity == null) 148 | throw new UserServiceException(ErrorMessages.NO_RECORD_FOUND.getErrorMessage()); 149 | 150 | userRepository.delete(userEntity); 151 | 152 | } 153 | 154 | @Override 155 | public List getUsers(int page, int limit) { 156 | List returnValue = new ArrayList<>(); 157 | 158 | if(page>0) page = page-1; 159 | 160 | Pageable pageableRequest = PageRequest.of(page, limit); 161 | 162 | Page usersPage = userRepository.findAll(pageableRequest); 163 | List users = usersPage.getContent(); 164 | 165 | for (UserEntity userEntity : users) { 166 | UserDto userDto = new UserDto(); 167 | BeanUtils.copyProperties(userEntity, userDto); 168 | returnValue.add(userDto); 169 | } 170 | 171 | return returnValue; 172 | } 173 | 174 | @Override 175 | public boolean verifyEmailToken(String token) { 176 | boolean returnValue = false; 177 | 178 | // Find user by token 179 | UserEntity userEntity = userRepository.findUserByEmailVerificationToken(token); 180 | 181 | if (userEntity != null) { 182 | boolean hastokenExpired = Utils.hasTokenExpired(token); 183 | if (!hastokenExpired) { 184 | userEntity.setEmailVerificationToken(null); 185 | userEntity.setEmailVerificationStatus(Boolean.TRUE); 186 | userRepository.save(userEntity); 187 | returnValue = true; 188 | } 189 | } 190 | 191 | return returnValue; 192 | } 193 | 194 | @Override 195 | public boolean requestPasswordReset(String email) { 196 | 197 | boolean returnValue = false; 198 | 199 | UserEntity userEntity = userRepository.findByEmail(email); 200 | 201 | if (userEntity == null) { 202 | return returnValue; 203 | } 204 | 205 | String token = new Utils().generatePasswordResetToken(userEntity.getUserId()); 206 | 207 | PasswordResetTokenEntity passwordResetTokenEntity = new PasswordResetTokenEntity(); 208 | passwordResetTokenEntity.setToken(token); 209 | passwordResetTokenEntity.setUserDetails(userEntity); 210 | passwordResetTokenRepository.save(passwordResetTokenEntity); 211 | 212 | returnValue = new AmazonSES().sendPasswordResetRequest( 213 | userEntity.getFirstName(), 214 | userEntity.getEmail(), 215 | token); 216 | 217 | return returnValue; 218 | } 219 | 220 | @Override 221 | public boolean resetPassword(String token, String password) { 222 | boolean returnValue = false; 223 | 224 | if( Utils.hasTokenExpired(token) ) 225 | { 226 | return returnValue; 227 | } 228 | 229 | PasswordResetTokenEntity passwordResetTokenEntity = passwordResetTokenRepository.findByToken(token); 230 | 231 | if (passwordResetTokenEntity == null) { 232 | return returnValue; 233 | } 234 | 235 | // Prepare new password 236 | String encodedPassword = bCryptPasswordEncoder.encode(password); 237 | 238 | // Update User password in database 239 | UserEntity userEntity = passwordResetTokenEntity.getUserDetails(); 240 | userEntity.setEncryptedPassword(encodedPassword); 241 | UserEntity savedUserEntity = userRepository.save(userEntity); 242 | 243 | // Verify if password was saved successfully 244 | if (savedUserEntity != null && savedUserEntity.getEncryptedPassword().equalsIgnoreCase(encodedPassword)) { 245 | returnValue = true; 246 | } 247 | 248 | // Remove Password Reset token from database 249 | passwordResetTokenRepository.delete(passwordResetTokenEntity); 250 | 251 | return returnValue; 252 | } 253 | 254 | } 255 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/shared/AmazonSES.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.shared; 2 | 3 | import org.springframework.stereotype.Service; 4 | 5 | import com.amazonaws.regions.Regions; 6 | import com.amazonaws.services.simpleemail.AmazonSimpleEmailService; 7 | import com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceClientBuilder; 8 | import com.amazonaws.services.simpleemail.model.Body; 9 | import com.amazonaws.services.simpleemail.model.Content; 10 | import com.amazonaws.services.simpleemail.model.Destination; 11 | import com.amazonaws.services.simpleemail.model.Message; 12 | import com.amazonaws.services.simpleemail.model.SendEmailRequest; 13 | import com.amazonaws.services.simpleemail.model.SendEmailResult; 14 | import com.appsdeveloperblog.app.ws.shared.dto.UserDto; 15 | 16 | @Service 17 | public class AmazonSES { 18 | // This address must be verified with Amazon SES. 19 | final String FROM = "sergey.kargopolov@swiftdeveloperblog.com"; 20 | 21 | // The subject line for the email. 22 | final String SUBJECT = "One last step to complete your registration with PhotoApp"; 23 | 24 | final String PASSWORD_RESET_SUBJECT = "Password reset request"; 25 | 26 | // The HTML body for the email. 27 | final String HTMLBODY = "

    Please verify your email address

    " 28 | + "

    Thank you for registering with our mobile app. To complete registration process and be able to log in," 29 | + " click on the following link: " 30 | + "" 31 | + "Final step to complete your registration" + "

    " 32 | + "Thank you! And we are waiting for you inside!"; 33 | 34 | // The email body for recipients with non-HTML email clients. 35 | final String TEXTBODY = "Please verify your email address. " 36 | + "Thank you for registering with our mobile app. To complete registration process and be able to log in," 37 | + " open then the following URL in your browser window: " 38 | + " http://ec2-35-173-238-100.compute-1.amazonaws.com:8080/verification-service/email-verification.html?token=$tokenValue" 39 | + " Thank you! And we are waiting for you inside!"; 40 | 41 | 42 | final String PASSWORD_RESET_HTMLBODY = "

    A request to reset your password

    " 43 | + "

    Hi, $firstName!

    " 44 | + "

    Someone has requested to reset your password with our project. If it were not you, please ignore it." 45 | + " otherwise please click on the link below to set a new password: " 46 | + "" 47 | + " Click this link to Reset Password" 48 | + "

    " 49 | + "Thank you!"; 50 | 51 | // The email body for recipients with non-HTML email clients. 52 | final String PASSWORD_RESET_TEXTBODY = "A request to reset your password " 53 | + "Hi, $firstName! " 54 | + "Someone has requested to reset your password with our project. If it were not you, please ignore it." 55 | + " otherwise please open the link below in your browser window to set a new password:" 56 | + " http://localhost:8080/verification-service/password-reset.html?token=$tokenValue" 57 | + " Thank you!"; 58 | 59 | 60 | public void verifyEmail(UserDto userDto) { 61 | 62 | // You can also set your keys this way. And it will work! 63 | //System.setProperty("aws.accessKeyId", ""); 64 | //System.setProperty("aws.secretKey", ""); 65 | 66 | AmazonSimpleEmailService client = AmazonSimpleEmailServiceClientBuilder.standard().withRegion(Regions.US_EAST_1) 67 | .build(); 68 | 69 | String htmlBodyWithToken = HTMLBODY.replace("$tokenValue", userDto.getEmailVerificationToken()); 70 | String textBodyWithToken = TEXTBODY.replace("$tokenValue", userDto.getEmailVerificationToken()); 71 | 72 | SendEmailRequest request = new SendEmailRequest() 73 | .withDestination(new Destination().withToAddresses(userDto.getEmail())) 74 | .withMessage(new Message() 75 | .withBody(new Body().withHtml(new Content().withCharset("UTF-8").withData(htmlBodyWithToken)) 76 | .withText(new Content().withCharset("UTF-8").withData(textBodyWithToken))) 77 | .withSubject(new Content().withCharset("UTF-8").withData(SUBJECT))) 78 | .withSource(FROM); 79 | 80 | client.sendEmail(request); 81 | 82 | System.out.println("Email sent!"); 83 | 84 | } 85 | 86 | public boolean sendPasswordResetRequest(String firstName, String email, String token) 87 | { 88 | boolean returnValue = false; 89 | 90 | AmazonSimpleEmailService client = 91 | AmazonSimpleEmailServiceClientBuilder.standard() 92 | .withRegion(Regions.US_EAST_1).build(); 93 | 94 | String htmlBodyWithToken = PASSWORD_RESET_HTMLBODY.replace("$tokenValue", token); 95 | htmlBodyWithToken = htmlBodyWithToken.replace("$firstName", firstName); 96 | 97 | String textBodyWithToken = PASSWORD_RESET_TEXTBODY.replace("$tokenValue", token); 98 | textBodyWithToken = textBodyWithToken.replace("$firstName", firstName); 99 | 100 | 101 | SendEmailRequest request = new SendEmailRequest() 102 | .withDestination( 103 | new Destination().withToAddresses( email ) ) 104 | .withMessage(new Message() 105 | .withBody(new Body() 106 | .withHtml(new Content() 107 | .withCharset("UTF-8").withData(htmlBodyWithToken)) 108 | .withText(new Content() 109 | .withCharset("UTF-8").withData(textBodyWithToken))) 110 | .withSubject(new Content() 111 | .withCharset("UTF-8").withData(PASSWORD_RESET_SUBJECT))) 112 | .withSource(FROM); 113 | 114 | SendEmailResult result = client.sendEmail(request); 115 | if(result != null && (result.getMessageId()!=null && !result.getMessageId().isEmpty())) 116 | { 117 | returnValue = true; 118 | } 119 | 120 | return returnValue; 121 | } 122 | 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/shared/Utils.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.shared; 2 | 3 | import java.security.SecureRandom; 4 | import java.util.Date; 5 | import java.util.Random; 6 | 7 | import org.springframework.stereotype.Service; 8 | 9 | import com.appsdeveloperblog.app.ws.security.SecurityConstants; 10 | 11 | import io.jsonwebtoken.Claims; 12 | import io.jsonwebtoken.ExpiredJwtException; 13 | import io.jsonwebtoken.Jwts; 14 | import io.jsonwebtoken.SignatureAlgorithm; 15 | 16 | @Service 17 | public class Utils { 18 | 19 | private final Random RANDOM = new SecureRandom(); 20 | private final String ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 21 | 22 | public String generateUserId(int length) { 23 | return generateRandomString(length); 24 | } 25 | 26 | public String generateAddressId(int length) { 27 | return generateRandomString(length); 28 | } 29 | 30 | private String generateRandomString(int length) { 31 | StringBuilder returnValue = new StringBuilder(length); 32 | 33 | for (int i = 0; i < length; i++) { 34 | returnValue.append(ALPHABET.charAt(RANDOM.nextInt(ALPHABET.length()))); 35 | } 36 | 37 | return new String(returnValue); 38 | } 39 | 40 | public static boolean hasTokenExpired(String token) { 41 | boolean returnValue = false; 42 | 43 | try { 44 | Claims claims = Jwts.parser().setSigningKey(SecurityConstants.getTokenSecret()).parseClaimsJws(token) 45 | .getBody(); 46 | 47 | Date tokenExpirationDate = claims.getExpiration(); 48 | Date todayDate = new Date(); 49 | 50 | returnValue = tokenExpirationDate.before(todayDate); 51 | } catch (ExpiredJwtException ex) { 52 | returnValue = true; 53 | } 54 | 55 | return returnValue; 56 | } 57 | 58 | public String generateEmailVerificationToken(String userId) { 59 | String token = Jwts.builder() 60 | .setSubject(userId) 61 | .setExpiration(new Date(System.currentTimeMillis() + SecurityConstants.EXPIRATION_TIME)) 62 | .signWith(SignatureAlgorithm.HS512, SecurityConstants.getTokenSecret()) 63 | .compact(); 64 | return token; 65 | } 66 | 67 | public String generatePasswordResetToken(String userId) 68 | { 69 | String token = Jwts.builder() 70 | .setSubject(userId) 71 | .setExpiration(new Date(System.currentTimeMillis() + SecurityConstants.EXPIRATION_TIME)) 72 | .signWith(SignatureAlgorithm.HS512, SecurityConstants.getTokenSecret()) 73 | .compact(); 74 | return token; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/shared/dto/AddressDTO.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.shared.dto; 2 | 3 | public class AddressDTO { 4 | private long id; 5 | private String addressId; 6 | private String city; 7 | private String country; 8 | private String streetName; 9 | private String postalCode; 10 | private String type; 11 | private UserDto userDetails; 12 | 13 | public long getId() { 14 | return id; 15 | } 16 | 17 | public void setId(long id) { 18 | this.id = id; 19 | } 20 | 21 | public String getCity() { 22 | return city; 23 | } 24 | 25 | public void setCity(String city) { 26 | this.city = city; 27 | } 28 | 29 | public String getCountry() { 30 | return country; 31 | } 32 | 33 | public void setCountry(String country) { 34 | this.country = country; 35 | } 36 | 37 | public String getStreetName() { 38 | return streetName; 39 | } 40 | 41 | public void setStreetName(String streetName) { 42 | this.streetName = streetName; 43 | } 44 | 45 | public String getPostalCode() { 46 | return postalCode; 47 | } 48 | 49 | public void setPostalCode(String postalCode) { 50 | this.postalCode = postalCode; 51 | } 52 | 53 | public String getType() { 54 | return type; 55 | } 56 | 57 | public void setType(String type) { 58 | this.type = type; 59 | } 60 | 61 | public UserDto getUserDetails() { 62 | return userDetails; 63 | } 64 | 65 | public void setUserDetails(UserDto userDetails) { 66 | this.userDetails = userDetails; 67 | } 68 | 69 | public String getAddressId() { 70 | return addressId; 71 | } 72 | 73 | public void setAddressId(String addressId) { 74 | this.addressId = addressId; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/shared/dto/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.shared.dto; 2 | 3 | import java.io.Serializable; 4 | import java.util.List; 5 | 6 | public class UserDto implements Serializable{ 7 | 8 | private static final long serialVersionUID = 6835192601898364280L; 9 | private long id; 10 | private String userId; 11 | private String firstName; 12 | private String lastName; 13 | private String email; 14 | private String password; 15 | private String encryptedPassword; 16 | private String emailVerificationToken; 17 | private Boolean emailVerificationStatus = false; 18 | private List addresses; 19 | 20 | public long getId() { 21 | return id; 22 | } 23 | public void setId(long id) { 24 | this.id = id; 25 | } 26 | public String getUserId() { 27 | return userId; 28 | } 29 | public void setUserId(String userId) { 30 | this.userId = userId; 31 | } 32 | public String getFirstName() { 33 | return firstName; 34 | } 35 | public void setFirstName(String firstName) { 36 | this.firstName = firstName; 37 | } 38 | public String getLastName() { 39 | return lastName; 40 | } 41 | public void setLastName(String lastName) { 42 | this.lastName = lastName; 43 | } 44 | public String getEmail() { 45 | return email; 46 | } 47 | public void setEmail(String email) { 48 | this.email = email; 49 | } 50 | public String getPassword() { 51 | return password; 52 | } 53 | public void setPassword(String password) { 54 | this.password = password; 55 | } 56 | public String getEncryptedPassword() { 57 | return encryptedPassword; 58 | } 59 | public void setEncryptedPassword(String encryptedPassword) { 60 | this.encryptedPassword = encryptedPassword; 61 | } 62 | public String getEmailVerificationToken() { 63 | return emailVerificationToken; 64 | } 65 | public void setEmailVerificationToken(String emailVerificationToken) { 66 | this.emailVerificationToken = emailVerificationToken; 67 | } 68 | public Boolean getEmailVerificationStatus() { 69 | return emailVerificationStatus; 70 | } 71 | public void setEmailVerificationStatus(Boolean emailVerificationStatus) { 72 | this.emailVerificationStatus = emailVerificationStatus; 73 | } 74 | public List getAddresses() { 75 | return addresses; 76 | } 77 | public void setAddresses(List addresses) { 78 | this.addresses = addresses; 79 | } 80 | 81 | 82 | 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/ui/contoller/AuthenticationController.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.ui.contoller; 2 | 3 | import org.springframework.web.bind.annotation.PostMapping; 4 | import org.springframework.web.bind.annotation.RequestBody; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | import io.swagger.annotations.ApiOperation; 8 | import io.swagger.annotations.ApiResponse; 9 | import io.swagger.annotations.ApiResponses; 10 | import io.swagger.annotations.ResponseHeader; 11 | 12 | import com.appsdeveloperblog.app.ws.ui.model.request.LoginRequestModel; 13 | 14 | @RestController 15 | public class AuthenticationController { 16 | 17 | @ApiOperation("User login") 18 | @ApiResponses(value = { 19 | @ApiResponse(code = 200, 20 | message = "Response Headers", 21 | responseHeaders = { 22 | @ResponseHeader(name = "authorization", 23 | description = "Bearer "), 24 | @ResponseHeader(name = "userId", 25 | description = "") 26 | }) 27 | }) 28 | @PostMapping("/users/login") 29 | public void theFakeLogin(@RequestBody LoginRequestModel loginRequestModel) 30 | { 31 | throw new IllegalStateException("This method should not be called. This method is implemented by Spring Security"); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/ui/contoller/RequestOperationName.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.ui.contoller; 2 | 3 | public enum RequestOperationName { 4 | DELETE, 5 | VERIFY_EMAIL, 6 | REQUEST_PASSWORD_RESET, 7 | PASSWORD_RESET 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/ui/model/request/AddressRequestModel.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.ui.model.request; 2 | 3 | public class AddressRequestModel { 4 | private String city; 5 | private String country; 6 | private String streetName; 7 | private String postalCode; 8 | private String type; 9 | 10 | public String getCity() { 11 | return city; 12 | } 13 | 14 | public void setCity(String city) { 15 | this.city = city; 16 | } 17 | 18 | public String getCountry() { 19 | return country; 20 | } 21 | 22 | public void setCountry(String country) { 23 | this.country = country; 24 | } 25 | 26 | public String getStreetName() { 27 | return streetName; 28 | } 29 | 30 | public void setStreetName(String streetName) { 31 | this.streetName = streetName; 32 | } 33 | 34 | public String getPostalCode() { 35 | return postalCode; 36 | } 37 | 38 | public void setPostalCode(String postalCode) { 39 | this.postalCode = postalCode; 40 | } 41 | 42 | public String getType() { 43 | return type; 44 | } 45 | 46 | public void setType(String type) { 47 | this.type = type; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/ui/model/request/LoginRequestModel.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.ui.model.request; 2 | 3 | public class LoginRequestModel { 4 | private String email; 5 | private String password; 6 | 7 | public String getEmail() { 8 | return email; 9 | } 10 | 11 | public void setEmail(String email) { 12 | this.email = email; 13 | } 14 | 15 | public String getPassword() { 16 | return password; 17 | } 18 | 19 | public void setPassword(String password) { 20 | this.password = password; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/ui/model/request/PasswordResetModel.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.ui.model.request; 2 | 3 | public class PasswordResetModel { 4 | private String token; 5 | private String password; 6 | 7 | public String getToken() { 8 | return token; 9 | } 10 | 11 | public void setToken(String token) { 12 | this.token = token; 13 | } 14 | 15 | public String getPassword() { 16 | return password; 17 | } 18 | 19 | public void setPassword(String password) { 20 | this.password = password; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/ui/model/request/PasswordResetRequestModel.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.ui.model.request; 2 | 3 | public class PasswordResetRequestModel { 4 | private String email; 5 | 6 | public String getEmail() { 7 | return email; 8 | } 9 | 10 | public void setEmail(String email) { 11 | this.email = email; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/ui/model/request/UserDetailsRequestModel.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.ui.model.request; 2 | 3 | import java.util.List; 4 | 5 | public class UserDetailsRequestModel { 6 | 7 | private String firstName; 8 | private String lastName; 9 | private String email; 10 | private String password; 11 | private List addresses; 12 | 13 | public String getFirstName() { 14 | return firstName; 15 | } 16 | public void setFirstName(String firstName) { 17 | this.firstName = firstName; 18 | } 19 | public String getLastName() { 20 | return lastName; 21 | } 22 | public void setLastName(String lastName) { 23 | this.lastName = lastName; 24 | } 25 | public String getEmail() { 26 | return email; 27 | } 28 | public void setEmail(String email) { 29 | this.email = email; 30 | } 31 | public String getPassword() { 32 | return password; 33 | } 34 | public void setPassword(String password) { 35 | this.password = password; 36 | } 37 | public List getAddresses() { 38 | return addresses; 39 | } 40 | public void setAddresses(List addresses) { 41 | this.addresses = addresses; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/ui/model/request/UserLoginRequestModel.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.ui.model.request; 2 | 3 | public class UserLoginRequestModel { 4 | private String email; 5 | private String password; 6 | 7 | public String getEmail() { 8 | return email; 9 | } 10 | 11 | public void setEmail(String email) { 12 | this.email = email; 13 | } 14 | 15 | public String getPassword() { 16 | return password; 17 | } 18 | 19 | public void setPassword(String password) { 20 | this.password = password; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/ui/model/response/AddressesRest.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.ui.model.response; 2 | 3 | import org.springframework.hateoas.ResourceSupport; 4 | 5 | public class AddressesRest extends ResourceSupport{ 6 | private String addressId; 7 | private String city; 8 | private String country; 9 | private String streetName; 10 | private String postalCode; 11 | private String type; 12 | 13 | public String getAddressId() { 14 | return addressId; 15 | } 16 | 17 | public void setAddressId(String addressId) { 18 | this.addressId = addressId; 19 | } 20 | 21 | public String getCity() { 22 | return city; 23 | } 24 | 25 | public void setCity(String city) { 26 | this.city = city; 27 | } 28 | 29 | public String getCountry() { 30 | return country; 31 | } 32 | 33 | public void setCountry(String country) { 34 | this.country = country; 35 | } 36 | 37 | public String getStreetName() { 38 | return streetName; 39 | } 40 | 41 | public void setStreetName(String streetName) { 42 | this.streetName = streetName; 43 | } 44 | 45 | public String getPostalCode() { 46 | return postalCode; 47 | } 48 | 49 | public void setPostalCode(String postalCode) { 50 | this.postalCode = postalCode; 51 | } 52 | 53 | public String getType() { 54 | return type; 55 | } 56 | 57 | public void setType(String type) { 58 | this.type = type; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/ui/model/response/ErrorMessage.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.ui.model.response; 2 | 3 | import java.util.Date; 4 | 5 | public class ErrorMessage { 6 | private Date timestamp; 7 | private String message; 8 | 9 | public ErrorMessage() {} 10 | 11 | public ErrorMessage(Date timestamp, String message) 12 | { 13 | this.timestamp = timestamp; 14 | this.message = message; 15 | } 16 | 17 | public Date getTimestamp() { 18 | return timestamp; 19 | } 20 | 21 | public void setTimestamp(Date timestamp) { 22 | this.timestamp = timestamp; 23 | } 24 | 25 | public String getMessage() { 26 | return message; 27 | } 28 | 29 | public void setMessage(String message) { 30 | this.message = message; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/ui/model/response/ErrorMessages.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.ui.model.response; 2 | 3 | public enum ErrorMessages { 4 | 5 | MISSING_REQUIRED_FIELD("Missing required field. Please check documentation for required fields"), 6 | RECORD_ALREADY_EXISTS("Record already exists"), 7 | INTERNAL_SERVER_ERROR("Internal server error"), 8 | NO_RECORD_FOUND("Record with provided id is not found"), 9 | AUTHENTICATION_FAILED("Authentication failed"), 10 | COULD_NOT_UPDATE_RECORD("Could not update record"), 11 | COULD_NOT_DELETE_RECORD("Could not delete record"), 12 | EMAIL_ADDRESS_NOT_VERIFIED("Email address could not be verified"); 13 | 14 | 15 | private String errorMessage; 16 | 17 | ErrorMessages(String errorMessage) { 18 | this.errorMessage = errorMessage; 19 | } 20 | 21 | /** 22 | * @return the errorMessage 23 | */ 24 | public String getErrorMessage() { 25 | return errorMessage; 26 | } 27 | 28 | /** 29 | * @param errorMessage the errorMessage to set 30 | */ 31 | public void setErrorMessage(String errorMessage) { 32 | this.errorMessage = errorMessage; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/ui/model/response/OperationStatusModel.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.ui.model.response; 2 | 3 | public class OperationStatusModel { 4 | private String operationResult; 5 | private String operationName; 6 | 7 | public String getOperationResult() { 8 | return operationResult; 9 | } 10 | 11 | public void setOperationResult(String operationResult) { 12 | this.operationResult = operationResult; 13 | } 14 | 15 | public String getOperationName() { 16 | return operationName; 17 | } 18 | 19 | public void setOperationName(String operationName) { 20 | this.operationName = operationName; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/ui/model/response/RequestOperationStatus.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.ui.model.response; 2 | 3 | public enum RequestOperationStatus { 4 | ERROR, SUCCESS 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/appsdeveloperblog/app/ws/ui/model/response/UserRest.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.ui.model.response; 2 | 3 | import java.util.List; 4 | 5 | public class UserRest { 6 | private String userId; 7 | private String firstName; 8 | private String lastName; 9 | private String email; 10 | private List addresses; 11 | 12 | public String getUserId() { 13 | return userId; 14 | } 15 | 16 | public void setUserId(String userId) { 17 | this.userId = userId; 18 | } 19 | 20 | public String getFirstName() { 21 | return firstName; 22 | } 23 | 24 | public void setFirstName(String firstName) { 25 | this.firstName = firstName; 26 | } 27 | 28 | public String getLastName() { 29 | return lastName; 30 | } 31 | 32 | public void setLastName(String lastName) { 33 | this.lastName = lastName; 34 | } 35 | 36 | public String getEmail() { 37 | return email; 38 | } 39 | 40 | public void setEmail(String email) { 41 | this.email = email; 42 | } 43 | 44 | public List getAddresses() { 45 | return addresses; 46 | } 47 | 48 | public void setAddresses(List addresses) { 49 | this.addresses = addresses; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.username=sergey 2 | spring.datasource.password=sergey 3 | #spring.datasource.url=jdbc:mysql://localhost:3306/photo_app 4 | spring.jpa.hibernate.ddl-auto=update 5 | tokenSecret = jf9i4jgu83nfl0jfu57ejf7 6 | server.servlet.context-path=/mobile-app-ws 7 | server.port=8080 8 | spring.h2.console.enabled=true -------------------------------------------------------------------------------- /src/main/webapp/META-INF/context.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/test/java/com/appsdeveloperblog/app/ws/MobileAppWsApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class MobileAppWsApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/com/appsdeveloperblog/app/ws/io/repository/UserRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.io.repository; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import org.junit.jupiter.api.BeforeEach; 8 | import org.junit.jupiter.api.Test; 9 | import org.junit.jupiter.api.extension.ExtendWith; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.boot.test.context.SpringBootTest; 12 | import org.springframework.data.domain.Page; 13 | import org.springframework.data.domain.PageRequest; 14 | import org.springframework.data.domain.Pageable; 15 | import org.springframework.test.context.junit.jupiter.SpringExtension; 16 | 17 | import com.appsdeveloperblog.app.ws.io.entity.AddressEntity; 18 | import com.appsdeveloperblog.app.ws.io.entity.UserEntity; 19 | 20 | @ExtendWith(SpringExtension.class) 21 | @SpringBootTest 22 | class UserRepositoryTest { 23 | 24 | @Autowired 25 | UserRepository userRepository; 26 | 27 | static boolean recordsCreated = false; 28 | 29 | 30 | @BeforeEach 31 | void setUp() throws Exception { 32 | 33 | if(!recordsCreated) createRecrods(); 34 | } 35 | 36 | @Test 37 | final void testGetVerifiedUsers() { 38 | Pageable pageableRequest = PageRequest.of(1, 1); 39 | Page page = userRepository.findAllUsersWithConfirmedEmailAddress(pageableRequest); 40 | assertNotNull(page); 41 | 42 | List userEntities = page.getContent(); 43 | assertNotNull(userEntities); 44 | assertTrue(userEntities.size() == 1); 45 | } 46 | 47 | @Test 48 | final void testFindUserByFirstName() 49 | { 50 | String firstName="Sergey"; 51 | List users = userRepository.findUserByFirstName(firstName); 52 | assertNotNull(users); 53 | assertTrue(users.size() == 2); 54 | 55 | UserEntity user = users.get(0); 56 | assertTrue(user.getFirstName().equals(firstName)); 57 | } 58 | 59 | @Test 60 | final void testFindUserByLastName() 61 | { 62 | String lastName="Kargopolov"; 63 | List users = userRepository.findUserByLastName(lastName); 64 | assertNotNull(users); 65 | assertTrue(users.size() == 2); 66 | 67 | UserEntity user = users.get(0); 68 | assertTrue(user.getLastName().equals(lastName)); 69 | } 70 | 71 | @Test 72 | final void testFindUsersByKeyword() 73 | { 74 | String keyword="erg"; 75 | List users = userRepository.findUsersByKeyword(keyword); 76 | assertNotNull(users); 77 | assertTrue(users.size() == 2); 78 | 79 | UserEntity user = users.get(0); 80 | assertTrue( 81 | user.getLastName().contains(keyword) || 82 | user.getFirstName().contains(keyword) 83 | ); 84 | } 85 | 86 | @Test 87 | final void testFindUserFirstNameAndLastNameByKeyword() 88 | { 89 | String keyword="erg"; 90 | List users = userRepository.findUserFirstNameAndLastNameByKeyword(keyword); 91 | assertNotNull(users); 92 | assertTrue(users.size() == 2); 93 | 94 | Object[] user = users.get(0); 95 | 96 | assertTrue(user.length == 2); 97 | 98 | String userFirstName = String.valueOf(user[0]); 99 | String userLastName = String.valueOf(user[1]); 100 | 101 | assertNotNull(userFirstName); 102 | assertNotNull(userLastName); 103 | 104 | System.out.println("First name = " + userFirstName); 105 | System.out.println("Last name = " + userLastName); 106 | 107 | } 108 | 109 | @Test 110 | final void testUpdateUserEmailVerificationStatus() 111 | { 112 | boolean newEmailVerificationStatus = true; 113 | userRepository.updateUserEmailVerificationStatus(newEmailVerificationStatus, "1a2b3c"); 114 | 115 | UserEntity storedUserDetails = userRepository.findByUserId("1a2b3c"); 116 | 117 | boolean storedEmailVerificationStatus = storedUserDetails.getEmailVerificationStatus(); 118 | 119 | assertTrue(storedEmailVerificationStatus == newEmailVerificationStatus); 120 | 121 | } 122 | 123 | 124 | @Test 125 | final void testFindUserEntityByUserId() 126 | { 127 | String userId = "1a2b3c"; 128 | UserEntity userEntity = userRepository.findUserEntityByUserId(userId); 129 | 130 | assertNotNull(userEntity); 131 | assertTrue(userEntity.getUserId().equals(userId)); 132 | } 133 | 134 | @Test 135 | final void testGetUserEntityFullNameById() 136 | { 137 | String userId = "1a2b3c"; 138 | List records = userRepository.getUserEntityFullNameById(userId); 139 | 140 | assertNotNull(records); 141 | assertTrue(records.size() == 1); 142 | 143 | Object[] userDetails = records.get(0); 144 | 145 | String firstName = String.valueOf(userDetails[0]); 146 | String lastName = String.valueOf(userDetails[1]); 147 | 148 | assertNotNull(firstName); 149 | assertNotNull(lastName); 150 | } 151 | 152 | @Test 153 | final void testUpdateUserEntityEmailVerificationStatus() 154 | { 155 | boolean newEmailVerificationStatus = true; 156 | userRepository.updateUserEntityEmailVerificationStatus(newEmailVerificationStatus, "1a2b3c"); 157 | 158 | UserEntity storedUserDetails = userRepository.findByUserId("1a2b3c"); 159 | 160 | boolean storedEmailVerificationStatus = storedUserDetails.getEmailVerificationStatus(); 161 | 162 | assertTrue(storedEmailVerificationStatus == newEmailVerificationStatus); 163 | 164 | } 165 | 166 | private void createRecrods() 167 | { 168 | // Prepare User Entity 169 | UserEntity userEntity = new UserEntity(); 170 | userEntity.setFirstName("Sergey"); 171 | userEntity.setLastName("Kargopolov"); 172 | userEntity.setUserId("1a2b3c"); 173 | userEntity.setEncryptedPassword("xxx"); 174 | userEntity.setEmail("test@test.com"); 175 | userEntity.setEmailVerificationStatus(true); 176 | 177 | // Prepare User Addresses 178 | AddressEntity addressEntity = new AddressEntity(); 179 | addressEntity.setType("shipping"); 180 | addressEntity.setAddressId("ahgyt74hfy"); 181 | addressEntity.setCity("Vancouver"); 182 | addressEntity.setCountry("Canada"); 183 | addressEntity.setPostalCode("ABCCDA"); 184 | addressEntity.setStreetName("123 Street Address"); 185 | 186 | List addresses = new ArrayList<>(); 187 | addresses.add(addressEntity); 188 | 189 | userEntity.setAddresses(addresses); 190 | 191 | userRepository.save(userEntity); 192 | 193 | 194 | 195 | 196 | // Prepare User Entity 197 | UserEntity userEntity2 = new UserEntity(); 198 | userEntity2.setFirstName("Sergey"); 199 | userEntity2.setLastName("Kargopolov"); 200 | userEntity2.setUserId("1a2b3cddddd"); 201 | userEntity2.setEncryptedPassword("xxx"); 202 | userEntity2.setEmail("test@test.com"); 203 | userEntity2.setEmailVerificationStatus(true); 204 | 205 | // Prepare User Addresses 206 | AddressEntity addressEntity2 = new AddressEntity(); 207 | addressEntity2.setType("shipping"); 208 | addressEntity2.setAddressId("ahgyt74hfywwww"); 209 | addressEntity2.setCity("Vancouver"); 210 | addressEntity2.setCountry("Canada"); 211 | addressEntity2.setPostalCode("ABCCDA"); 212 | addressEntity2.setStreetName("123 Street Address"); 213 | 214 | List addresses2 = new ArrayList<>(); 215 | addresses2.add(addressEntity2); 216 | 217 | userEntity2.setAddresses(addresses2); 218 | 219 | userRepository.save(userEntity2); 220 | 221 | recordsCreated = true; 222 | 223 | } 224 | 225 | } 226 | -------------------------------------------------------------------------------- /src/test/java/com/appsdeveloperblog/app/ws/service/impl/UserServiceImplTest.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.service.impl; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.assertNotNull; 5 | import static org.junit.jupiter.api.Assertions.assertThrows; 6 | import static org.mockito.ArgumentMatchers.any; 7 | import static org.mockito.ArgumentMatchers.anyInt; 8 | import static org.mockito.ArgumentMatchers.anyString; 9 | import static org.mockito.Mockito.times; 10 | import static org.mockito.Mockito.verify; 11 | import static org.mockito.Mockito.when; 12 | 13 | import java.lang.reflect.Type; 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | import org.junit.jupiter.api.BeforeEach; 18 | import org.junit.jupiter.api.Test; 19 | import org.mockito.InjectMocks; 20 | import org.mockito.Mock; 21 | import org.mockito.Mockito; 22 | import org.mockito.MockitoAnnotations; 23 | import org.modelmapper.ModelMapper; 24 | import org.modelmapper.TypeToken; 25 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 26 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 27 | 28 | import com.appsdeveloperblog.app.ws.exceptions.UserServiceException; 29 | import com.appsdeveloperblog.app.ws.io.entity.AddressEntity; 30 | import com.appsdeveloperblog.app.ws.io.entity.UserEntity; 31 | import com.appsdeveloperblog.app.ws.io.repository.UserRepository; 32 | import com.appsdeveloperblog.app.ws.shared.AmazonSES; 33 | import com.appsdeveloperblog.app.ws.shared.Utils; 34 | import com.appsdeveloperblog.app.ws.shared.dto.AddressDTO; 35 | import com.appsdeveloperblog.app.ws.shared.dto.UserDto; 36 | 37 | class UserServiceImplTest { 38 | 39 | @InjectMocks 40 | UserServiceImpl userService; 41 | 42 | @Mock 43 | UserRepository userRepository; 44 | 45 | @Mock 46 | Utils utils; 47 | 48 | @Mock 49 | AmazonSES amazonSES; 50 | 51 | @Mock 52 | BCryptPasswordEncoder bCryptPasswordEncoder; 53 | 54 | String userId = "hhty57ehfy"; 55 | String encryptedPassword = "74hghd8474jf"; 56 | 57 | UserEntity userEntity; 58 | 59 | @BeforeEach 60 | void setUp() throws Exception { 61 | MockitoAnnotations.initMocks(this); 62 | 63 | userEntity = new UserEntity(); 64 | userEntity.setId(1L); 65 | userEntity.setFirstName("Sergey"); 66 | userEntity.setLastName("Kargopolov"); 67 | userEntity.setUserId(userId); 68 | userEntity.setEncryptedPassword(encryptedPassword); 69 | userEntity.setEmail("test@test.com"); 70 | userEntity.setEmailVerificationToken("7htnfhr758"); 71 | userEntity.setAddresses(getAddressesEntity()); 72 | } 73 | 74 | @Test 75 | final void testGetUser() { 76 | 77 | when(userRepository.findByEmail(anyString())).thenReturn(userEntity); 78 | 79 | UserDto userDto = userService.getUser("test@test.com"); 80 | 81 | assertNotNull(userDto); 82 | assertEquals("Sergey", userDto.getFirstName()); 83 | 84 | } 85 | 86 | @Test 87 | final void testGetUser_UsernameNotFoundException() { 88 | when(userRepository.findByEmail(anyString())).thenReturn(null); 89 | 90 | assertThrows(UsernameNotFoundException.class, 91 | 92 | () -> { 93 | userService.getUser("test@test.com"); 94 | } 95 | 96 | ); 97 | } 98 | 99 | @Test 100 | final void testCreateUser_CreateUserServiceException() 101 | { 102 | when(userRepository.findByEmail(anyString())).thenReturn(userEntity); 103 | UserDto userDto = new UserDto(); 104 | userDto.setAddresses(getAddressesDto()); 105 | userDto.setFirstName("Sergey"); 106 | userDto.setLastName("Kargopolov"); 107 | userDto.setPassword("12345678"); 108 | userDto.setEmail("test@test.com"); 109 | 110 | assertThrows(UserServiceException.class, 111 | 112 | () -> { 113 | userService.createUser(userDto); 114 | } 115 | 116 | ); 117 | } 118 | 119 | @Test 120 | final void testCreateUser() 121 | { 122 | when(userRepository.findByEmail(anyString())).thenReturn(null); 123 | when(utils.generateAddressId(anyInt())).thenReturn("hgfnghtyrir884"); 124 | when(utils.generateUserId(anyInt())).thenReturn(userId); 125 | when(bCryptPasswordEncoder.encode(anyString())).thenReturn(encryptedPassword); 126 | when(userRepository.save(any(UserEntity.class))).thenReturn(userEntity); 127 | Mockito.doNothing().when(amazonSES).verifyEmail(any(UserDto.class)); 128 | 129 | UserDto userDto = new UserDto(); 130 | userDto.setAddresses(getAddressesDto()); 131 | userDto.setFirstName("Sergey"); 132 | userDto.setLastName("Kargopolov"); 133 | userDto.setPassword("12345678"); 134 | userDto.setEmail("test@test.com"); 135 | 136 | UserDto storedUserDetails = userService.createUser(userDto); 137 | assertNotNull(storedUserDetails); 138 | assertEquals(userEntity.getFirstName(), storedUserDetails.getFirstName()); 139 | assertEquals(userEntity.getLastName(), storedUserDetails.getLastName()); 140 | assertNotNull(storedUserDetails.getUserId()); 141 | assertEquals(storedUserDetails.getAddresses().size(), userEntity.getAddresses().size()); 142 | verify(utils,times(storedUserDetails.getAddresses().size())).generateAddressId(30); 143 | verify(bCryptPasswordEncoder, times(1)).encode("12345678"); 144 | verify(userRepository,times(1)).save(any(UserEntity.class)); 145 | } 146 | 147 | private List getAddressesDto() { 148 | AddressDTO addressDto = new AddressDTO(); 149 | addressDto.setType("shipping"); 150 | addressDto.setCity("Vancouver"); 151 | addressDto.setCountry("Canada"); 152 | addressDto.setPostalCode("ABC123"); 153 | addressDto.setStreetName("123 Street name"); 154 | 155 | AddressDTO billingAddressDto = new AddressDTO(); 156 | billingAddressDto.setType("billling"); 157 | billingAddressDto.setCity("Vancouver"); 158 | billingAddressDto.setCountry("Canada"); 159 | billingAddressDto.setPostalCode("ABC123"); 160 | billingAddressDto.setStreetName("123 Street name"); 161 | 162 | List addresses = new ArrayList<>(); 163 | addresses.add(addressDto); 164 | addresses.add(billingAddressDto); 165 | 166 | return addresses; 167 | 168 | } 169 | 170 | private List getAddressesEntity() 171 | { 172 | List addresses = getAddressesDto(); 173 | 174 | Type listType = new TypeToken>() {}.getType(); 175 | 176 | return new ModelMapper().map(addresses, listType); 177 | } 178 | 179 | 180 | } 181 | -------------------------------------------------------------------------------- /src/test/java/com/appsdeveloperblog/app/ws/shared/UtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.shared; 2 | 3 | import static org.junit.Assert.assertNotNull; 4 | import static org.junit.Assert.assertTrue; 5 | import static org.junit.jupiter.api.Assertions.assertFalse; 6 | import static org.junit.jupiter.api.Assertions.assertThrows; 7 | import static org.junit.jupiter.api.Assertions.fail; 8 | 9 | import org.junit.jupiter.api.BeforeEach; 10 | import org.junit.jupiter.api.Disabled; 11 | import org.junit.jupiter.api.Test; 12 | import org.junit.jupiter.api.extension.ExtendWith; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.boot.test.context.SpringBootTest; 15 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 16 | import org.springframework.test.context.junit.jupiter.SpringExtension; 17 | 18 | import io.jsonwebtoken.SignatureException; 19 | 20 | @ExtendWith(SpringExtension.class) 21 | @SpringBootTest 22 | class UtilsTest { 23 | 24 | @Autowired 25 | Utils utils; 26 | 27 | @BeforeEach 28 | void setUp() throws Exception { 29 | } 30 | 31 | @Test 32 | final void testGenerateUserId() { 33 | String userId = utils.generateUserId(30); 34 | String userId2 = utils.generateUserId(30); 35 | 36 | assertNotNull(userId); 37 | assertNotNull(userId2); 38 | 39 | assertTrue(userId.length() == 30); 40 | assertTrue( !userId.equalsIgnoreCase(userId2) ); 41 | } 42 | 43 | @Test 44 | final void testHasTokenNotExpired() { 45 | String token = utils.generateEmailVerificationToken("4yr65hhyid84"); 46 | assertNotNull(token); 47 | 48 | boolean hasTokenExpired = Utils.hasTokenExpired(token); 49 | assertFalse(hasTokenExpired); 50 | } 51 | 52 | @Test 53 | final void testHasTokenExpired() 54 | { 55 | String expiredToken = "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MUB0ZXN0LmNvbSIsImV4cCI6MTUzMjc3Nzc3NX0.cdudUo3pwZLN9UiTuXiT7itpaQs6BgUPU0yWbNcz56-l1Z0476N3H_qSEHXQI5lUfaK2ePtTWJfROmf0213UJA"; 56 | boolean hasTokenExpired = Utils.hasTokenExpired(expiredToken); 57 | 58 | assertTrue(hasTokenExpired); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/test/java/com/appsdeveloperblog/app/ws/ui/controller/UserControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.appsdeveloperblog.app.ws.ui.controller; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | import static org.mockito.Mockito.when; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | import static org.mockito.ArgumentMatchers.*; 10 | import org.junit.jupiter.api.BeforeEach; 11 | import org.junit.jupiter.api.Test; 12 | import org.mockito.InjectMocks; 13 | import org.mockito.Mock; 14 | import org.mockito.MockitoAnnotations; 15 | 16 | import com.appsdeveloperblog.app.ws.service.impl.UserServiceImpl; 17 | import com.appsdeveloperblog.app.ws.shared.dto.AddressDTO; 18 | import com.appsdeveloperblog.app.ws.shared.dto.UserDto; 19 | import com.appsdeveloperblog.app.ws.ui.contoller.UserController; 20 | import com.appsdeveloperblog.app.ws.ui.model.response.UserRest; 21 | 22 | class UserControllerTest { 23 | 24 | @InjectMocks 25 | UserController userController; 26 | 27 | @Mock 28 | UserServiceImpl userService; 29 | 30 | UserDto userDto; 31 | 32 | final String USER_ID = "bfhry47fhdjd7463gdh"; 33 | 34 | @BeforeEach 35 | void setUp() throws Exception { 36 | MockitoAnnotations.initMocks(this); 37 | 38 | userDto = new UserDto(); 39 | userDto.setFirstName("Sergey"); 40 | userDto.setLastName("Kargopolov"); 41 | userDto.setEmail("test@test.com"); 42 | userDto.setEmailVerificationStatus(Boolean.FALSE); 43 | userDto.setEmailVerificationToken(null); 44 | userDto.setUserId(USER_ID); 45 | userDto.setAddresses(getAddressesDto()); 46 | userDto.setEncryptedPassword("xcf58tugh47"); 47 | 48 | } 49 | 50 | @Test 51 | final void testGetUser() { 52 | when(userService.getUserByUserId(anyString())).thenReturn(userDto); 53 | 54 | UserRest userRest = userController.getUser(USER_ID); 55 | 56 | assertNotNull(userRest); 57 | assertEquals(USER_ID, userRest.getUserId()); 58 | assertEquals(userDto.getFirstName(), userRest.getFirstName()); 59 | assertEquals(userDto.getLastName(), userRest.getLastName()); 60 | assertTrue(userDto.getAddresses().size() == userRest.getAddresses().size()); 61 | } 62 | 63 | 64 | private List getAddressesDto() { 65 | AddressDTO addressDto = new AddressDTO(); 66 | addressDto.setType("shipping"); 67 | addressDto.setCity("Vancouver"); 68 | addressDto.setCountry("Canada"); 69 | addressDto.setPostalCode("ABC123"); 70 | addressDto.setStreetName("123 Street name"); 71 | 72 | AddressDTO billingAddressDto = new AddressDTO(); 73 | billingAddressDto.setType("billling"); 74 | billingAddressDto.setCity("Vancouver"); 75 | billingAddressDto.setCountry("Canada"); 76 | billingAddressDto.setPostalCode("ABC123"); 77 | billingAddressDto.setStreetName("123 Street name"); 78 | 79 | List addresses = new ArrayList<>(); 80 | addresses.add(addressDto); 81 | addresses.add(billingAddressDto); 82 | 83 | return addresses; 84 | 85 | } 86 | 87 | } 88 | --------------------------------------------------------------------------------