├── .gitignore ├── README.MD ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── javaeeeee │ │ ├── SpringBootBookmarksApplication.java │ │ ├── components │ │ └── JpaAuthenticationProvider.java │ │ ├── configuration │ │ └── RestSecurityConfiguration.java │ │ ├── controllers │ │ ├── BookmarksController.java │ │ └── HelloController.java │ │ ├── entities │ │ ├── Bookmark.java │ │ └── User.java │ │ ├── exception │ │ ├── BookmarkNotFoundException.java │ │ └── UserNotFoundException.java │ │ └── repositories │ │ ├── BookmarksRepository.java │ │ └── UsersRepository.java └── resources │ ├── application.properties │ └── db │ └── migration │ ├── V1_1__Create_users_table.sql │ ├── V1_2__Create_bookmarks_table.sql │ └── V1_3__Add_some_data.sql └── test └── java └── com └── javaeeeee ├── SpringBootBookmarksApplicationTests.java ├── controllers ├── BookmarksControllerTest.java └── HelloControllerTest.java ├── entities ├── BookmarkTest.java └── UserTest.java └── repositories ├── BookmarksRepositoryTest.java └── UsersRepositoryTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/maven,netbeans,eclipse,intellij,java 3 | 4 | ### Maven ### 5 | target/ 6 | pom.xml.tag 7 | pom.xml.releaseBackup 8 | pom.xml.versionsBackup 9 | pom.xml.next 10 | release.properties 11 | dependency-reduced-pom.xml 12 | buildNumber.properties 13 | .mvn/timing.properties 14 | 15 | 16 | ### NetBeans ### 17 | nbproject/private/ 18 | build/ 19 | nbbuild/ 20 | dist/ 21 | nbdist/ 22 | nbactions.xml 23 | nb-configuration.xml 24 | .nb-gradle/ 25 | 26 | 27 | ### Eclipse ### 28 | 29 | .metadata 30 | bin/ 31 | tmp/ 32 | *.tmp 33 | *.bak 34 | *.swp 35 | *~.nib 36 | local.properties 37 | .settings/ 38 | .loadpath 39 | .recommenders 40 | 41 | # Eclipse Core 42 | .project 43 | 44 | # External tool builders 45 | .externalToolBuilders/ 46 | 47 | # Locally stored "Eclipse launch configurations" 48 | *.launch 49 | 50 | # PyDev specific (Python IDE for Eclipse) 51 | *.pydevproject 52 | 53 | # CDT-specific (C/C++ Development Tooling) 54 | .cproject 55 | 56 | # JDT-specific (Eclipse Java Development Tools) 57 | .classpath 58 | 59 | # Java annotation processor (APT) 60 | .factorypath 61 | 62 | # PDT-specific (PHP Development Tools) 63 | .buildpath 64 | 65 | # sbteclipse plugin 66 | .target 67 | 68 | # Tern plugin 69 | .tern-project 70 | 71 | # TeXlipse plugin 72 | .texlipse 73 | 74 | # STS (Spring Tool Suite) 75 | .springBeans 76 | 77 | # Code Recommenders 78 | .recommenders/ 79 | 80 | 81 | ### Intellij ### 82 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 83 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 84 | 85 | # User-specific stuff: 86 | .idea/workspace.xml 87 | .idea/tasks.xml 88 | .idea/dictionaries 89 | .idea/vcs.xml 90 | .idea/jsLibraryMappings.xml 91 | 92 | # Sensitive or high-churn files: 93 | .idea/dataSources.ids 94 | .idea/dataSources.xml 95 | .idea/dataSources.local.xml 96 | .idea/sqlDataSources.xml 97 | .idea/dynamic.xml 98 | .idea/uiDesigner.xml 99 | 100 | # Gradle: 101 | .idea/gradle.xml 102 | .idea/libraries 103 | 104 | # Mongo Explorer plugin: 105 | .idea/mongoSettings.xml 106 | 107 | ## File-based project format: 108 | *.iws 109 | 110 | ## Plugin-specific files: 111 | 112 | # IntelliJ 113 | /out/ 114 | 115 | # mpeltonen/sbt-idea plugin 116 | .idea_modules/ 117 | 118 | # JIRA plugin 119 | atlassian-ide-plugin.xml 120 | 121 | # Crashlytics plugin (for Android Studio and IntelliJ) 122 | com_crashlytics_export_strings.xml 123 | crashlytics.properties 124 | crashlytics-build.properties 125 | fabric.properties 126 | 127 | ### Intellij Patch ### 128 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 129 | 130 | # *.iml 131 | # modules.xml 132 | # .idea/misc.xml 133 | # *.ipr 134 | 135 | 136 | ### Java ### 137 | *.class 138 | 139 | # Mobile Tools for Java (J2ME) 140 | .mtj.tmp/ 141 | 142 | # Package Files # 143 | *.jar 144 | *.war 145 | *.ear 146 | 147 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 148 | hs_err_pid* 149 | /nbproject/ -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | This is a simple application to store bookmarks exposing REST API. 2 | This application uses Spring Boot and MySql RDMS to store data. 3 | 4 | To connect the application to the database it is necessary that settings in 5 | src/main/resources/application.settings be changed. One should create a 6 | bookmarks database and provide connection credentials. The tables will be 7 | created automatically by Flyway migrations integrated into Spring Boot. 8 | 9 | ~~~~ 10 | spring.datasource.url=jdbc:mysql://localhost:3306/bookmarks 11 | spring.datasource.username= 12 | spring.datasource.password= 13 | ~~~~ 14 | 15 | A user with name *Phil* and password *1* will be created as well as several bookmarks. 16 | 17 | The API is secured with Basic Authentication, so the aforementioned credentials 18 | can be used to access the data. 19 | 20 | To get all the bookmarks stored by user Phil one should key in the following. 21 | 22 | ~~~~ 23 | curl -w "\n" 2>/dev/null localhost:8080/Phil/bookmarks -u Phil:1 24 | ~~~~ 25 | 26 | To extract data for a single particular bookmark one should type in a command: 27 | 28 | ~~~~ 29 | curl -w "\n" 2>/dev/null localhost:8080/Phil/bookmarks/1 -u Phil:1 30 | ~~~~ 31 | 32 | To edit a bookmark the HTTP PUT method is used. 33 | 34 | ~~~~ 35 | curl -X PUT -w "\n" 2>/dev/null localhost:8080/Phil/bookmarks/1 -u Phil:1 \ 36 | -H "Content-Type: application/json" -d '{"url":"github.com"}' 37 | ~~~~ 38 | 39 | To add a bookmark use the following. 40 | 41 | ~~~~ 42 | curl -X POST -w "\n" 2>/dev/null localhost:8080/Phil/bookmarks \ 43 | -u Phil:1 -H "Content-Type: application/json" \ 44 | -d '{"url":"http://github.com", "description":"A lot of great projects"}' 45 | ~~~~ 46 | 47 | To remove a bookmark the HTTP DELETE method is used. 48 | 49 | ~~~~ 50 | curl -X DELETE -w "\n" 2>/dev/null localhost:8080/Phil/bookmarks/3 \ 51 | -u Phil:1 52 | ~~~~ 53 | 54 | The project contains a lot of test examples based on Spring Boot Test Starter 55 | and Spring Security Test. There are examples of how to test repositories and 56 | resource methods including the case when the latter are secured with Basic 57 | Authentication. -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.javaeeeee 5 | springbootbookmarks 6 | 0.0.1-SNAPSHOT 7 | jar 8 | SpringBootBookmarks 9 | A simple Spring Boot project exposing REST API to store bookmarks 10 | 11 | org.springframework.boot 12 | spring-boot-starter-parent 13 | 1.4.0.RELEASE 14 | 15 | 16 | 17 | 18 | UTF-8 19 | UTF-8 20 | 1.8 21 | 22 | 23 | 24 | org.springframework.boot 25 | spring-boot-starter-web 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter-data-jpa 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-devtools 34 | true 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-starter-hateoas 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-starter-social-twitter 43 | 44 | 45 | org.springframework.boot 46 | spring-boot-starter-thymeleaf 47 | 48 | 49 | org.springframework.boot 50 | spring-boot-starter-validation 51 | 52 | 53 | com.h2database 54 | h2 55 | test 56 | 57 | 58 | mysql 59 | mysql-connector-java 60 | runtime 61 | 62 | 63 | org.springframework.boot 64 | spring-boot-starter-test 65 | test 66 | 67 | 68 | org.springframework.boot 69 | spring-boot-configuration-processor 70 | true 71 | 72 | 73 | 74 | commons-beanutils 75 | commons-beanutils 76 | 1.9.2 77 | 78 | 79 | org.flywaydb 80 | flyway-core 81 | 4.0.3 82 | 83 | 84 | org.springframework.boot 85 | spring-boot-starter-security 86 | 87 | 88 | org.springframework.security 89 | spring-security-test 90 | 91 | 92 | 93 | 94 | 95 | org.springframework.boot 96 | spring-boot-maven-plugin 97 | 98 | true 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /src/main/java/com/javaeeeee/SpringBootBookmarksApplication.java: -------------------------------------------------------------------------------- 1 | package com.javaeeeee; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootBookmarksApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootBookmarksApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/javaeeeee/components/JpaAuthenticationProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 Dmitry Noranovich . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.javaeeeee.components; 25 | 26 | import com.javaeeeee.entities.User; 27 | import com.javaeeeee.repositories.UsersRepository; 28 | import java.util.Optional; 29 | import org.springframework.beans.factory.annotation.Autowired; 30 | import org.springframework.context.annotation.Bean; 31 | import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; 32 | import org.springframework.security.authentication.AuthenticationProvider; 33 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 34 | import org.springframework.security.core.Authentication; 35 | import org.springframework.security.core.AuthenticationException; 36 | import org.springframework.stereotype.Component; 37 | 38 | /** 39 | * This class is used for basic authentication using credentials stored in a 40 | * database. http://www.baeldung.com/spring-security-authentication-provider 41 | * 42 | * @author Dmitry Noranovich 43 | */ 44 | @Component 45 | public class JpaAuthenticationProvider implements AuthenticationProvider { 46 | 47 | /** 48 | * A user repository. 49 | */ 50 | @Autowired 51 | private UsersRepository usersRepository; 52 | 53 | @Override 54 | public Authentication authenticate(Authentication authentication) 55 | throws AuthenticationException { 56 | Optional optional = usersRepository 57 | .findByUsernameAndPassword( 58 | authentication.getName(), 59 | authentication.getCredentials().toString() 60 | ); 61 | if (optional.isPresent()) { 62 | return new UsernamePasswordAuthenticationToken( 63 | authentication.getPrincipal(), 64 | authentication.getCredentials(), 65 | authentication.getAuthorities()); 66 | 67 | } else { 68 | throw new AuthenticationCredentialsNotFoundException( 69 | "Wrong credentials."); 70 | } 71 | } 72 | 73 | @Override 74 | public boolean supports(Class authentication) { 75 | return authentication.equals(UsernamePasswordAuthenticationToken.class); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/com/javaeeeee/configuration/RestSecurityConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 Dmitry Noranovich . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.javaeeeee.configuration; 25 | 26 | import com.javaeeeee.components.JpaAuthenticationProvider; 27 | import com.javaeeeee.repositories.UsersRepository; 28 | import org.springframework.beans.factory.annotation.Autowired; 29 | import org.springframework.context.annotation.Bean; 30 | import org.springframework.context.annotation.Configuration; 31 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 32 | import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter; 33 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 34 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 35 | import org.springframework.security.core.userdetails.UserDetails; 36 | import org.springframework.security.core.userdetails.UserDetailsService; 37 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 38 | 39 | /** 40 | * The class is used to configure security for the application. 41 | * http://www.baeldung.com/spring-security-authentication-provider 42 | * 43 | * @author Dmitry Noranovich 44 | */ 45 | @Configuration 46 | public class RestSecurityConfiguration extends WebSecurityConfigurerAdapter { 47 | 48 | /** 49 | * Custom authentication provider. 50 | */ 51 | @Autowired 52 | private JpaAuthenticationProvider authenticationProvider; 53 | 54 | @Override 55 | protected void configure(HttpSecurity http) throws Exception { 56 | http.authenticationProvider(authenticationProvider) 57 | .authorizeRequests() 58 | .anyRequest() 59 | .authenticated() 60 | .and() 61 | .httpBasic() 62 | .and() 63 | .cors() 64 | .and() 65 | .csrf().disable(); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/javaeeeee/controllers/BookmarksController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 Dmitry Noranovich . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.javaeeeee.controllers; 25 | 26 | import com.fasterxml.jackson.databind.ObjectMapper; 27 | import com.javaeeeee.entities.Bookmark; 28 | import com.javaeeeee.entities.User; 29 | import com.javaeeeee.exception.BookmarkNotFoundException; 30 | import com.javaeeeee.exception.UserNotFoundException; 31 | import com.javaeeeee.repositories.BookmarksRepository; 32 | import com.javaeeeee.repositories.UsersRepository; 33 | import java.io.IOException; 34 | import java.lang.reflect.InvocationTargetException; 35 | import java.util.HashMap; 36 | import java.util.Map; 37 | import java.util.Optional; 38 | import java.util.Set; 39 | import org.apache.commons.beanutils.BeanUtils; 40 | import org.springframework.beans.factory.annotation.Autowired; 41 | import org.springframework.http.HttpStatus; 42 | import org.springframework.http.ResponseEntity; 43 | import org.springframework.web.bind.annotation.PathVariable; 44 | import org.springframework.web.bind.annotation.RequestBody; 45 | import org.springframework.web.bind.annotation.RequestMapping; 46 | import org.springframework.web.bind.annotation.RequestMethod; 47 | import org.springframework.web.bind.annotation.RestController; 48 | 49 | /** 50 | * The controller that exposes resource methods to work with bookmarks for a 51 | * particular user. 52 | * 53 | * @author Dmitry Noranovich 54 | */ 55 | @RequestMapping("/{username}/bookmarks") 56 | @RestController 57 | public class BookmarksController { 58 | 59 | /** 60 | * The repository to work with bookmarks. 61 | */ 62 | private final BookmarksRepository bookmarksRepository; 63 | /** 64 | * The repository to work with users. 65 | */ 66 | private final UsersRepository usersRepository; 67 | 68 | /** 69 | * The constructor which allows to inject repositories. 70 | * 71 | * @param bookmarksRepository The repository to work with bookmarks. 72 | * @param usersRepository The repository to work with users. 73 | */ 74 | @Autowired 75 | public BookmarksController(BookmarksRepository bookmarksRepository, 76 | UsersRepository usersRepository) { 77 | this.bookmarksRepository = bookmarksRepository; 78 | this.usersRepository = usersRepository; 79 | } 80 | 81 | /** 82 | * A method to return bookmarks for a particular user. 83 | * 84 | * @param username the name of a user whose bookmarks are listed. 85 | * @return list of user's bookmarks. 86 | * @throws java.lang.Exception 87 | */ 88 | @RequestMapping(method = RequestMethod.GET) 89 | public Set getAllBookmarks( 90 | @PathVariable(value = "username") String username) 91 | throws Exception { 92 | validateUser(username); 93 | return bookmarksRepository.findByUserUsername(username); 94 | } 95 | 96 | /** 97 | * A method to find a bookmark by id. 98 | * 99 | * @param bookmarkId 100 | * @throws com.javaeeeee.exception.UserNotFoundException 101 | * @throws com.javaeeeee.exception.BookmarkNotFoundException 102 | */ 103 | @RequestMapping(value = "/{bookmarkId}", method = RequestMethod.GET) 104 | public Bookmark getBookmark( 105 | @PathVariable(value = "username") String username, 106 | @PathVariable(value = "bookmarkId") Integer bookmarkId) 107 | throws UserNotFoundException, BookmarkNotFoundException { 108 | validateUser(username); 109 | Optional optional 110 | = bookmarksRepository 111 | .findByIdAndUserUsername(bookmarkId, username); 112 | if (optional.isPresent()) { 113 | return optional.get(); 114 | } else { 115 | throw new BookmarkNotFoundException(bookmarkId.toString()); 116 | } 117 | } 118 | 119 | /** 120 | * A method to add a bookmark. 121 | */ 122 | @RequestMapping(method = RequestMethod.POST) 123 | ResponseEntity addBookmark( 124 | @PathVariable(value = "username") String username, 125 | @RequestBody Bookmark bookmark) throws UserNotFoundException { 126 | Optional optional = usersRepository.findByUsername(username); 127 | if (optional.isPresent()) { 128 | User user = optional.get(); 129 | user.addBookmark(bookmark); 130 | bookmark.setUser(user); 131 | bookmarksRepository.save(bookmark); 132 | return new ResponseEntity<>(bookmark, HttpStatus.CREATED); 133 | } else { 134 | throw new UserNotFoundException(username); 135 | } 136 | } 137 | 138 | /** 139 | * A method to edit a bookmark. 140 | * 141 | * @param username 142 | * @param bookmarkId 143 | * @param json 144 | * @return ResponseEntity containing the patched bookmark, if found, and 145 | * status code. 146 | * @throws java.io.IOException 147 | * @throws java.lang.reflect.InvocationTargetException 148 | * @throws com.javaeeeee.exception.BookmarkNotFoundException 149 | * @throws java.lang.IllegalAccessException 150 | */ 151 | @RequestMapping(value = "/{bookmarkId}", method = RequestMethod.PUT) 152 | public ResponseEntity editBookmark( 153 | @PathVariable(value = "username") String username, 154 | @PathVariable(value = "bookmarkId") int bookmarkId, 155 | @RequestBody String json) throws IOException, 156 | BookmarkNotFoundException, 157 | IllegalAccessException, 158 | InvocationTargetException { 159 | 160 | Optional optional = bookmarksRepository 161 | .findByIdAndUserUsername(bookmarkId, username); 162 | if (optional.isPresent()) { 163 | ObjectMapper mapper = new ObjectMapper(); 164 | Map changeMap 165 | = mapper.readValue(json, HashMap.class); 166 | Bookmark bookmark = optional.get(); 167 | BeanUtils.populate(bookmark, changeMap); 168 | bookmark = bookmarksRepository.save(bookmark); 169 | return new ResponseEntity<>(bookmark, HttpStatus.OK); 170 | } else { 171 | throw new BookmarkNotFoundException( 172 | "Bookmark not found id = " + bookmarkId); 173 | } 174 | 175 | } 176 | 177 | /** 178 | * A method to delete a bookmark identified by id. 179 | * 180 | * @param username user name 181 | * @param bookmarkId The id of the bookmark to be deleted. 182 | * @return ResponseEntity containing a deleted bookmark, if found, and 183 | * status code. 184 | */ 185 | @RequestMapping(value = "/{bookmarkId}", method = RequestMethod.DELETE) 186 | public ResponseEntity deleteBookmark( 187 | @PathVariable(value = "username") String username, 188 | @PathVariable(value = "bookmarkId") int bookmarkId) throws BookmarkNotFoundException { 189 | Optional optional 190 | = bookmarksRepository.findByIdAndUserUsername(bookmarkId, username); 191 | if (optional.isPresent()) { 192 | bookmarksRepository.delete(optional.get()); 193 | return new ResponseEntity<>(optional.get(), HttpStatus.OK); 194 | } else { 195 | throw new BookmarkNotFoundException("Bookmark not found. id = " + bookmarkId); 196 | } 197 | } 198 | 199 | /** 200 | * A method to check if a user exists. 201 | * 202 | * @param username username. 203 | * @throws UserNotFoundException thrown if user doesn't exist. 204 | */ 205 | private void validateUser(String username) throws UserNotFoundException { 206 | if (!usersRepository.findByUsername(username).isPresent()) { 207 | throw new UserNotFoundException(username); 208 | } 209 | } 210 | 211 | } 212 | -------------------------------------------------------------------------------- /src/main/java/com/javaeeeee/controllers/HelloController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 Dmitry Noranovich . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.javaeeeee.controllers; 25 | 26 | import org.springframework.web.bind.annotation.PathVariable; 27 | import org.springframework.web.bind.annotation.RequestMapping; 28 | import org.springframework.web.bind.annotation.RequestParam; 29 | import org.springframework.web.bind.annotation.RestController; 30 | 31 | /** 32 | * This class is a simple REST controller. It's method prints a simple "Hello 33 | * world" message. 34 | * 35 | * @author Dmitry Noranovich 36 | */ 37 | @RequestMapping("/hello") 38 | @RestController 39 | public class HelloController { 40 | 41 | /** 42 | * A simple greeting. 43 | */ 44 | public static final String GREETING = "Hello Spring Boot World"; 45 | 46 | /** 47 | * The resource method returns a greeting. 48 | * 49 | * @return a greeting. 50 | */ 51 | //@RequestMapping 52 | public String getGreeting() { 53 | return GREETING; 54 | } 55 | 56 | /** 57 | * The resource method with a path parameter to return customized greeting. 58 | * 59 | * @param name The name of a person to greet. 60 | * @return Customized greeting. 61 | */ 62 | @RequestMapping("/{name}") 63 | public String getPathParamGreeting(@PathVariable String name) { 64 | return "Hello " + name; 65 | } 66 | 67 | /** 68 | * The resource method with a query parameter to return customized greeting. 69 | * 70 | * @param name The name of a person to greet. 71 | * @return Customized greeting. 72 | */ 73 | @RequestMapping 74 | public String getQueryParamGreeting( 75 | @RequestParam(value = "name", required = false) String name) { 76 | if (name != null) { 77 | return "Hello " + name; 78 | } else { 79 | return GREETING; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/com/javaeeeee/entities/Bookmark.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 Dmitry Noranovich . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.javaeeeee.entities; 25 | 26 | import com.fasterxml.jackson.annotation.JsonIgnore; 27 | import java.io.Serializable; 28 | import javax.persistence.Basic; 29 | import javax.persistence.Column; 30 | import javax.persistence.Entity; 31 | import javax.persistence.GeneratedValue; 32 | import javax.persistence.GenerationType; 33 | import javax.persistence.Id; 34 | import javax.persistence.ManyToOne; 35 | import javax.persistence.Table; 36 | import javax.validation.constraints.NotNull; 37 | import javax.validation.constraints.Size; 38 | import org.springframework.util.Assert; 39 | 40 | /** 41 | * An entity to store bookmarks. 42 | * 43 | * @author Dmitry Noranovich 44 | */ 45 | @Entity 46 | @Table(name = "bookmarks") 47 | public class Bookmark implements Serializable { 48 | 49 | private static final long serialVersionUID = 1L; 50 | /** 51 | * The auto-generated id of a bookmark. 52 | */ 53 | @Id 54 | @GeneratedValue(strategy = GenerationType.IDENTITY) 55 | @Basic(optional = false) 56 | @Column(nullable = false) 57 | private Integer id; 58 | /** 59 | * The URL of a bookmark. 60 | */ 61 | @Basic(optional = false) 62 | @NotNull 63 | @Size(min = 1, max = 255) 64 | @Column(nullable = false, length = 255) 65 | private String url; 66 | /** 67 | * The description of a bookmark. 68 | */ 69 | @Size(max = 2048) 70 | @Column(length = 2048) 71 | private String description; 72 | /** 73 | * The owner of a bookmark. 74 | */ 75 | @JsonIgnore 76 | @Basic(optional = false) 77 | @NotNull 78 | @ManyToOne 79 | private User user; 80 | 81 | /** 82 | * The no-argument constructor. 83 | */ 84 | public Bookmark() { 85 | } 86 | 87 | /** 88 | * A constructor to create a bookmark. 89 | * 90 | * @param url bookmark URL. 91 | * @param description bookmark description. 92 | */ 93 | public Bookmark(String url, String description) { 94 | Assert.hasLength(url); 95 | this.url = url; 96 | this.description = description; 97 | } 98 | 99 | /** 100 | * ID getter. 101 | * 102 | * @return id 103 | */ 104 | public Integer getId() { 105 | return id; 106 | } 107 | 108 | /** 109 | * ID setter 110 | * 111 | * @param id id 112 | */ 113 | public void setId(Integer id) { 114 | this.id = id; 115 | } 116 | 117 | public String getUrl() { 118 | return url; 119 | } 120 | 121 | public void setUrl(String url) { 122 | Assert.hasLength(url); 123 | this.url = url; 124 | } 125 | 126 | public String getDescription() { 127 | return description; 128 | } 129 | 130 | public void setDescription(String description) { 131 | this.description = description; 132 | } 133 | 134 | public User getUser() { 135 | return user; 136 | } 137 | 138 | public void setUser(User user) { 139 | Assert.notNull(user); 140 | this.user = user; 141 | } 142 | 143 | @Override 144 | public int hashCode() { 145 | int hash = 0; 146 | hash += (id != null ? id.hashCode() : 0); 147 | return hash; 148 | } 149 | 150 | @Override 151 | public boolean equals(Object object) { 152 | // TODO: Warning - this method won't work in the case the id fields are not set 153 | if (!(object instanceof Bookmark)) { 154 | return false; 155 | } 156 | Bookmark other = (Bookmark) object; 157 | if ((this.id == null && other.id != null) 158 | || (this.id != null && !this.id.equals(other.id))) { 159 | return false; 160 | } 161 | return true; 162 | } 163 | 164 | @Override 165 | public String toString() { 166 | return "Bookmark{" + "id=" + id + ", url=" + url 167 | + ", description=" + description + ", user=" + user + '}'; 168 | } 169 | 170 | } 171 | -------------------------------------------------------------------------------- /src/main/java/com/javaeeeee/entities/User.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 Dmitry Noranovich . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.javaeeeee.entities; 25 | 26 | import java.io.Serializable; 27 | import java.util.HashSet; 28 | import java.util.Set; 29 | import javax.persistence.Basic; 30 | import javax.persistence.CascadeType; 31 | import javax.persistence.Column; 32 | import javax.persistence.Entity; 33 | import javax.persistence.GeneratedValue; 34 | import javax.persistence.GenerationType; 35 | import javax.persistence.Id; 36 | import javax.persistence.OneToMany; 37 | import javax.persistence.Table; 38 | import javax.validation.constraints.NotNull; 39 | import javax.validation.constraints.Size; 40 | import org.springframework.util.Assert; 41 | 42 | /** 43 | * A class to store application user data. 44 | * 45 | * @author Dmitry Noranovich 46 | */ 47 | @Entity 48 | @Table(name = "users") 49 | public class User implements Serializable { 50 | 51 | private static final long serialVersionUID = 1L; 52 | /** 53 | * The auto-generated id of a user. 54 | */ 55 | @Id 56 | @GeneratedValue(strategy = GenerationType.IDENTITY) 57 | @Basic(optional = false) 58 | @Column(nullable = false) 59 | private Integer id; 60 | /** 61 | * A username to login to the application. 62 | */ 63 | @Basic(optional = false) 64 | @NotNull 65 | @Size(min = 1, max = 255) 66 | @Column(nullable = false, length = 255, unique = true) 67 | private String username; 68 | /** 69 | * A password to login to the application. 70 | */ 71 | @Basic(optional = false) 72 | @NotNull 73 | @Size(min = 1, max = 255) 74 | @Column(nullable = false, length = 255) 75 | private String password; 76 | /** 77 | * Bookmark list of a user. 78 | */ 79 | @OneToMany(mappedBy = "user", cascade = CascadeType.ALL) 80 | private Set bookmarks = new HashSet<>(); 81 | 82 | /** 83 | * A no-argument constructor. 84 | */ 85 | public User() { 86 | } 87 | 88 | /** 89 | * A constructor used to create users. 90 | * 91 | * @param username 92 | * @param password 93 | */ 94 | public User(String username, String password) { 95 | Assert.hasLength(username); 96 | Assert.hasLength(password); 97 | this.username = username; 98 | this.password = password; 99 | } 100 | 101 | public Integer getId() { 102 | return id; 103 | } 104 | 105 | public void setId(Integer id) { 106 | this.id = id; 107 | } 108 | 109 | public String getUsername() { 110 | return username; 111 | } 112 | 113 | public void setUsername(String username) { 114 | Assert.hasLength(username); 115 | this.username = username; 116 | } 117 | 118 | public String getPassword() { 119 | return password; 120 | } 121 | 122 | public void setPassword(String password) { 123 | Assert.hasLength(password); 124 | this.password = password; 125 | } 126 | 127 | public Set getBookmarks() { 128 | return bookmarks; 129 | } 130 | 131 | /** 132 | * A method to add bookmarks to user's list. 133 | * 134 | * @param bookmark a bookmark to add. 135 | * @return the added bookmark. 136 | */ 137 | public Bookmark addBookmark(Bookmark bookmark) { 138 | Assert.notNull(bookmark); 139 | bookmarks.add(bookmark); 140 | bookmark.setUser(this); 141 | return bookmark; 142 | } 143 | 144 | @Override 145 | public int hashCode() { 146 | int hash = 0; 147 | hash += (id != null ? id.hashCode() : 0); 148 | return hash; 149 | } 150 | 151 | @Override 152 | public boolean equals(Object object) { 153 | // TODO: Warning - this method won't work in the case the id fields are not set 154 | if (!(object instanceof User)) { 155 | return false; 156 | } 157 | User other = (User) object; 158 | if ((this.id == null && other.id != null) 159 | || (this.id != null && !this.id.equals(other.id))) { 160 | return false; 161 | } 162 | return true; 163 | } 164 | 165 | @Override 166 | public String toString() { 167 | return "User{" + "id=" + id 168 | + ", username=" + username + ", password=" + password + '}'; 169 | } 170 | 171 | } 172 | -------------------------------------------------------------------------------- /src/main/java/com/javaeeeee/exception/BookmarkNotFoundException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 Dmitry Noranovich . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.javaeeeee.exception; 25 | 26 | import org.springframework.http.HttpStatus; 27 | import org.springframework.web.bind.annotation.ResponseStatus; 28 | 29 | /** 30 | * The exception thrown when a bookmark is not found. 31 | * 32 | * @author Dmitry Noranovich 33 | */ 34 | @ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "No such bookmark.") 35 | public class BookmarkNotFoundException extends Exception { 36 | 37 | public BookmarkNotFoundException() { 38 | } 39 | 40 | public BookmarkNotFoundException(String message) { 41 | super(message); 42 | } 43 | 44 | public BookmarkNotFoundException(String message, Throwable cause) { 45 | super(message, cause); 46 | } 47 | 48 | public BookmarkNotFoundException(Throwable cause) { 49 | super(cause); 50 | } 51 | 52 | public BookmarkNotFoundException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 53 | super(message, cause, enableSuppression, writableStackTrace); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/javaeeeee/exception/UserNotFoundException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 Dmitry Noranovich . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.javaeeeee.exception; 25 | 26 | import org.springframework.http.HttpStatus; 27 | import org.springframework.web.bind.annotation.ResponseStatus; 28 | 29 | /** 30 | * The exception thrown when user is not found. 31 | * 32 | * @author Dmitry Noranovich 33 | */ 34 | @ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "No such user.") 35 | public class UserNotFoundException extends Exception { 36 | 37 | public UserNotFoundException() { 38 | } 39 | 40 | public UserNotFoundException(String message) { 41 | super(message); 42 | } 43 | 44 | public UserNotFoundException(String message, Throwable cause) { 45 | super(message, cause); 46 | } 47 | 48 | public UserNotFoundException(Throwable cause) { 49 | super(cause); 50 | } 51 | 52 | public UserNotFoundException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 53 | super(message, cause, enableSuppression, writableStackTrace); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/javaeeeee/repositories/BookmarksRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 Dmitry Noranovich . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.javaeeeee.repositories; 25 | 26 | import com.javaeeeee.entities.Bookmark; 27 | import java.util.Optional; 28 | import java.util.Set; 29 | import org.springframework.data.repository.PagingAndSortingRepository; 30 | 31 | /** 32 | * Bookmarks repository. 33 | * 34 | * @author Dmitry Noranovich 35 | */ 36 | public interface BookmarksRepository 37 | extends PagingAndSortingRepository { 38 | 39 | /** 40 | * A method to find bookmarks stored by a particular user identified by the 41 | * username. 42 | * 43 | * @param username the username. 44 | * @return list of bookmarks stored by a particular user. 45 | */ 46 | Set findByUserUsername(String username); 47 | 48 | /** 49 | * A method to find a bookmark for a particular user with the id specified. 50 | */ 51 | Optional findByIdAndUserUsername(Integer id, String username); 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/javaeeeee/repositories/UsersRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 Dmitry Noranovich . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.javaeeeee.repositories; 25 | 26 | import com.javaeeeee.entities.User; 27 | import java.util.Optional; 28 | import org.springframework.data.repository.PagingAndSortingRepository; 29 | 30 | /** 31 | * Users repository. 32 | * 33 | * @author Dmitry Noranovich 34 | */ 35 | public interface UsersRepository 36 | extends PagingAndSortingRepository { 37 | 38 | /** 39 | * The method looks for a user by username. 40 | * 41 | * @param username the name of the user to find. 42 | * @return Optional of a user, empty if not found. 43 | */ 44 | Optional findByUsername(String username); 45 | 46 | /** 47 | * The method looks for a user by username and password for authentication 48 | * purposes. 49 | * 50 | * @param username 51 | * @param password 52 | * @return Optional of user if found and empty Optional otherwise. 53 | */ 54 | Optional findByUsernameAndPassword(String username, String password); 55 | } 56 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:mysql://localhost:3306/bookmarks 2 | spring.datasource.username=root 3 | spring.datasource.password=1234 4 | spring.datasource.driver-class-name=com.mysql.jdbc.Driver -------------------------------------------------------------------------------- /src/main/resources/db/migration/V1_1__Create_users_table.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 Dmitry Noranovich . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | /** 25 | * Author: Dmitry Noranovich 26 | * Created: 12-Aug-2016 27 | */ 28 | 29 | create table users ( 30 | id int auto_increment not null primary key, 31 | username varchar(255) unique not null, 32 | password varchar(255) not null 33 | ); 34 | -------------------------------------------------------------------------------- /src/main/resources/db/migration/V1_2__Create_bookmarks_table.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 Dmitry Noranovich . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | /** 25 | * Author: Dmitry Noranovich 26 | * Created: 12-Aug-2016 27 | */ 28 | 29 | create table bookmarks ( 30 | id int auto_increment not null primary key, 31 | url varchar(255) not null, 32 | description varchar(2048), 33 | user_id int not null references users(id) 34 | ); -------------------------------------------------------------------------------- /src/main/resources/db/migration/V1_3__Add_some_data.sql: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 Dmitry Noranovich . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | /** 25 | * Author: Dmitry Noranovich 26 | * Created: 12-Aug-2016 27 | */ 28 | 29 | insert into users values 30 | (null, 'Phil', '1'); 31 | 32 | set @u_id = (select id from users where username='Phil'); 33 | 34 | insert into bookmarks values 35 | (null, 'http://economist.com', 'Cool reading', @u_id), 36 | (null, 'http://time.com', 'Some news', @u_id); -------------------------------------------------------------------------------- /src/test/java/com/javaeeeee/SpringBootBookmarksApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.javaeeeee; 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 SpringBootBookmarksApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/com/javaeeeee/controllers/BookmarksControllerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 Dmitry Noranovich . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.javaeeeee.controllers; 25 | 26 | import com.fasterxml.jackson.databind.ObjectMapper; 27 | import com.javaeeeee.entities.Bookmark; 28 | import com.javaeeeee.entities.User; 29 | import com.javaeeeee.repositories.BookmarksRepository; 30 | import com.javaeeeee.repositories.UsersRepository; 31 | import com.sun.webkit.network.URLs; 32 | import java.util.Arrays; 33 | import java.util.HashSet; 34 | import java.util.Optional; 35 | import org.hamcrest.Matchers; 36 | import org.junit.Before; 37 | import org.junit.BeforeClass; 38 | import org.junit.Test; 39 | import org.junit.runner.RunWith; 40 | import org.mockito.BDDMockito; 41 | import org.springframework.beans.factory.annotation.Autowired; 42 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 43 | import org.springframework.boot.test.mock.mockito.MockBean; 44 | import org.springframework.http.MediaType; 45 | import org.springframework.security.test.context.support.WithMockUser; 46 | import org.springframework.test.context.junit4.SpringRunner; 47 | import org.springframework.test.web.servlet.MockMvc; 48 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; 49 | import org.springframework.test.web.servlet.result.MockMvcResultMatchers; 50 | 51 | /** 52 | * A class to test bookmarks controller. 53 | * 54 | * @author Dmitry Noranovich 55 | */ 56 | @RunWith(SpringRunner.class) 57 | @WebMvcTest(BookmarksController.class) 58 | @WithMockUser 59 | public class BookmarksControllerTest { 60 | 61 | /** 62 | * The Id of a test BOOKMARK. 63 | */ 64 | private static final int BOOKMARK_ID = 1; 65 | /** 66 | * The URL of a test BOOKMARK. 67 | */ 68 | private static final String URL = "http://economist.com"; 69 | /** 70 | * Bookmark description. 71 | */ 72 | private static final String BM_DESCRIPTION = "Cool reading."; 73 | /** 74 | * A test BOOKMARK. 75 | */ 76 | private static final Bookmark BOOKMARK = new Bookmark(URL, BM_DESCRIPTION); 77 | /** 78 | * The name of a test USER. 79 | */ 80 | private static final String USERNAME = "Phil"; 81 | /** 82 | * An id of a nonexistent bookmark. 83 | */ 84 | private static final int NONEXISTENT_BOOKMARK_ID = 10967876; 85 | /** 86 | * A username of a nonexistent user. 87 | */ 88 | private static final String NONEXISTENT_USERNAME = USERNAME + 10967876; 89 | /** 90 | * A test USER. 91 | */ 92 | private static final User USER = new User(USERNAME, "1"); 93 | /** 94 | * A URL to change in PUT method. 95 | */ 96 | private static final String NEW_URL = "http://time.com"; 97 | /** 98 | * A JSON string for PUT method test. 99 | */ 100 | private static final String JSON_DATA 101 | = String.format("{\"url\":\"%s\"}", NEW_URL); 102 | 103 | /** 104 | * Mock MVC. 105 | */ 106 | @Autowired 107 | private MockMvc mvc; 108 | 109 | /** 110 | * Mock bookmarks repository. 111 | */ 112 | @MockBean 113 | private BookmarksRepository bookmarksRepository; 114 | 115 | /** 116 | * Mock USER repository. 117 | */ 118 | @MockBean 119 | private UsersRepository usersRepository; 120 | 121 | /** 122 | * Initialization method. 123 | */ 124 | @BeforeClass 125 | public static void setUpClass() { 126 | BOOKMARK.setId(BOOKMARK_ID); 127 | BOOKMARK.setUser(USER); 128 | } 129 | 130 | /** 131 | * Method carries out initialization before each method. 132 | */ 133 | @Before 134 | public void setUp() { 135 | BDDMockito 136 | .given(usersRepository.findByUsername(USERNAME)) 137 | .willReturn(Optional.of(USER)); 138 | BDDMockito 139 | .given(usersRepository.findByUsername(NONEXISTENT_USERNAME)) 140 | .willReturn(Optional.empty()); 141 | } 142 | 143 | /** 144 | * Test of getAllBookmarks method, of class BookmarksController for an 145 | * existent user. 146 | * 147 | * @throws java.lang.Exception 148 | */ 149 | @Test 150 | public void testGetAllBookmarksShouldOk() throws Exception { 151 | BDDMockito.given(bookmarksRepository.findByUserUsername(USERNAME)) 152 | .willReturn(new HashSet<>(Arrays.asList(BOOKMARK))); 153 | 154 | mvc.perform(MockMvcRequestBuilders.get("/" + USERNAME + "/bookmarks/")) 155 | .andExpect(MockMvcResultMatchers.status().isOk()) 156 | .andExpect(MockMvcResultMatchers 157 | .jsonPath("$", Matchers.hasSize(1))) 158 | .andExpect(MockMvcResultMatchers.jsonPath("$[0].url", 159 | Matchers.is(URL))); 160 | 161 | BDDMockito.verify(usersRepository).findByUsername(USERNAME); 162 | BDDMockito.verifyNoMoreInteractions(usersRepository); 163 | BDDMockito.verify(bookmarksRepository).findByUserUsername(USERNAME); 164 | BDDMockito.verifyNoMoreInteractions(bookmarksRepository); 165 | } 166 | 167 | /** 168 | * Test of getAllBookmarks() method for a nonexistent user. 169 | * 170 | * @throws java.lang.Exception 171 | */ 172 | public void testGetAllBookmarksNoSuchUser() throws Exception { 173 | BDDMockito.given(bookmarksRepository 174 | .findByUserUsername(NONEXISTENT_USERNAME)) 175 | .willReturn(new HashSet<>()); 176 | 177 | mvc.perform(MockMvcRequestBuilders 178 | .get("/" + NONEXISTENT_USERNAME + "/bookmarks/")) 179 | .andExpect(MockMvcResultMatchers.status().isNotFound()); 180 | 181 | BDDMockito.verify(usersRepository).findByUsername(USERNAME); 182 | BDDMockito.verifyNoMoreInteractions(usersRepository); 183 | BDDMockito.verify(bookmarksRepository) 184 | .findByIdAndUserUsername(BOOKMARK_ID, USERNAME); 185 | BDDMockito.verifyNoMoreInteractions(bookmarksRepository); 186 | } 187 | 188 | /** 189 | * Test of getBookmark method, of class BookmarksController. 190 | * 191 | * @throws java.lang.Exception 192 | */ 193 | @Test 194 | public void testGetBookmarkFound() throws Exception { 195 | BDDMockito 196 | .given(bookmarksRepository 197 | .findByIdAndUserUsername(BOOKMARK_ID, USERNAME)) 198 | .willReturn(Optional.of(BOOKMARK)); 199 | 200 | mvc.perform(MockMvcRequestBuilders 201 | .get("/" + USERNAME + "/bookmarks/" + BOOKMARK_ID)) 202 | .andExpect(MockMvcResultMatchers.status().isOk()) 203 | .andExpect(MockMvcResultMatchers.jsonPath("$.id", 204 | Matchers.is(BOOKMARK_ID))) 205 | .andExpect(MockMvcResultMatchers.jsonPath("$.url", 206 | Matchers.is(URL))); 207 | 208 | BDDMockito.verify(bookmarksRepository) 209 | .findByIdAndUserUsername(BOOKMARK_ID, USERNAME); 210 | BDDMockito.verifyNoMoreInteractions(bookmarksRepository); 211 | 212 | } 213 | 214 | /** 215 | * Method tests the situation when we loo for a non-existent bookmark. 216 | * 217 | * @throws Exception 218 | */ 219 | @Test 220 | public void testGetBookmarkNotFound() throws Exception { 221 | BDDMockito 222 | .given(bookmarksRepository 223 | .findByIdAndUserUsername(NONEXISTENT_BOOKMARK_ID, 224 | USERNAME)) 225 | .willReturn(Optional.empty()); 226 | 227 | mvc.perform(MockMvcRequestBuilders 228 | .get("/" + USERNAME + "/bookmarks/" + NONEXISTENT_BOOKMARK_ID)) 229 | .andExpect(MockMvcResultMatchers.status().isNotFound()); 230 | 231 | BDDMockito.verify(bookmarksRepository) 232 | .findByIdAndUserUsername(NONEXISTENT_BOOKMARK_ID, USERNAME); 233 | BDDMockito.verifyNoMoreInteractions(bookmarksRepository); 234 | } 235 | 236 | /** 237 | * Method tests bookmark extraction for a nonexistent user. 238 | * 239 | * @throws Exception 240 | */ 241 | @Test 242 | public void testGetBookmarkNoSuchUser() throws Exception { 243 | BDDMockito 244 | .given(bookmarksRepository 245 | .findByIdAndUserUsername(BOOKMARK_ID, 246 | NONEXISTENT_USERNAME)) 247 | .willReturn(Optional.empty()); 248 | mvc.perform(MockMvcRequestBuilders 249 | .get("/" + NONEXISTENT_USERNAME + "/bookmarks/" + BOOKMARK_ID)) 250 | .andExpect(MockMvcResultMatchers.status().isNotFound()); 251 | 252 | BDDMockito.verify(usersRepository).findByUsername(NONEXISTENT_USERNAME); 253 | BDDMockito.verifyNoMoreInteractions(usersRepository); 254 | BDDMockito.verifyZeroInteractions(bookmarksRepository); 255 | } 256 | 257 | /** 258 | * Test of addBookmark method, of class BookmarksController. 259 | */ 260 | @Test 261 | public void testAddBookmark() throws Exception { 262 | ObjectMapper mapper = new ObjectMapper(); 263 | String jsonData = mapper.writeValueAsString(BOOKMARK); 264 | 265 | mvc.perform( 266 | MockMvcRequestBuilders.post("/" + USERNAME + "/bookmarks") 267 | .contentType(MediaType.APPLICATION_JSON) 268 | .content(jsonData)) 269 | .andExpect(MockMvcResultMatchers.status().isCreated()) 270 | .andExpect(MockMvcResultMatchers.jsonPath("$.id", 271 | Matchers.is(BOOKMARK_ID))) 272 | .andExpect(MockMvcResultMatchers.jsonPath("$.url", 273 | Matchers.is(URL))); 274 | 275 | BDDMockito.verify(usersRepository).findByUsername(USERNAME); 276 | BDDMockito.verifyNoMoreInteractions(usersRepository); 277 | BDDMockito.verify(bookmarksRepository).save(BOOKMARK); 278 | BDDMockito.verifyNoMoreInteractions(bookmarksRepository); 279 | } 280 | 281 | /** 282 | * Method testing editing a bookmark when a bookmark is not found. 283 | * 284 | * @throws java.lang.Exception 285 | */ 286 | @Test 287 | public void testEditBookmarkNotFound() throws Exception { 288 | BDDMockito 289 | .given(bookmarksRepository 290 | .findByIdAndUserUsername(NONEXISTENT_BOOKMARK_ID, 291 | USERNAME)) 292 | .willReturn(Optional.empty()); 293 | 294 | mvc.perform(MockMvcRequestBuilders 295 | .put("/" + USERNAME + "/bookmarks/" + NONEXISTENT_BOOKMARK_ID) 296 | .contentType(MediaType.APPLICATION_JSON) 297 | .content(JSON_DATA) 298 | ).andExpect(MockMvcResultMatchers.status().isNotFound()); 299 | 300 | BDDMockito.verify(bookmarksRepository) 301 | .findByIdAndUserUsername(NONEXISTENT_BOOKMARK_ID, USERNAME); 302 | BDDMockito.verifyNoMoreInteractions(bookmarksRepository); 303 | } 304 | 305 | /** 306 | * Method to test editing a bookmark, happy path. 307 | * 308 | * @throws java.lang.Exception 309 | */ 310 | @Test 311 | public void testEditBookmarkShouldOk() throws Exception { 312 | 313 | BDDMockito 314 | .given(bookmarksRepository 315 | .findByIdAndUserUsername(BOOKMARK_ID, USERNAME)) 316 | .willReturn(Optional.of(BOOKMARK)); 317 | 318 | Bookmark newBookmark 319 | = new Bookmark(NEW_URL, BOOKMARK.getDescription()); 320 | newBookmark.setId(BOOKMARK.getId()); 321 | newBookmark.setUser(BOOKMARK.getUser()); 322 | 323 | BDDMockito 324 | .given(bookmarksRepository.save(newBookmark)) 325 | .willReturn(newBookmark); 326 | 327 | mvc.perform(MockMvcRequestBuilders 328 | .put("/" + USERNAME + "/bookmarks/" + BOOKMARK_ID) 329 | .contentType(MediaType.APPLICATION_JSON) 330 | .content(JSON_DATA)) 331 | .andExpect( 332 | MockMvcResultMatchers.status().isOk()) 333 | .andExpect( 334 | MockMvcResultMatchers 335 | .jsonPath("$.id", Matchers.is(BOOKMARK_ID))) 336 | .andExpect(MockMvcResultMatchers 337 | .jsonPath("$.url", Matchers.is(NEW_URL))) 338 | .andExpect(MockMvcResultMatchers 339 | .jsonPath("$.description", 340 | Matchers.is(BM_DESCRIPTION))); 341 | 342 | BDDMockito 343 | .verify(bookmarksRepository) 344 | .findByIdAndUserUsername(BOOKMARK_ID, USERNAME); 345 | BDDMockito 346 | .verify(bookmarksRepository) 347 | .save(newBookmark); 348 | BDDMockito.verifyNoMoreInteractions(bookmarksRepository); 349 | 350 | BOOKMARK.setUrl(URL); 351 | } 352 | 353 | /** 354 | * Method tests Delete for a nonexistent bookmark. 355 | * 356 | * @throws java.lang.Exception 357 | */ 358 | @Test 359 | public void testDeleteBookmarkNotFound() throws Exception { 360 | BDDMockito 361 | .given(bookmarksRepository 362 | .findByIdAndUserUsername(NONEXISTENT_BOOKMARK_ID, 363 | USERNAME)) 364 | .willReturn(Optional.empty()); 365 | BDDMockito.doNothing().when(bookmarksRepository).delete(BOOKMARK); 366 | 367 | mvc.perform(MockMvcRequestBuilders 368 | .delete("/" + USERNAME + "/bookmarks/" + NONEXISTENT_BOOKMARK_ID)) 369 | .andExpect(MockMvcResultMatchers.status().isNotFound()); 370 | 371 | BDDMockito 372 | .verify(bookmarksRepository) 373 | .findByIdAndUserUsername(NONEXISTENT_BOOKMARK_ID, USERNAME); 374 | BDDMockito.verifyNoMoreInteractions(bookmarksRepository); 375 | } 376 | 377 | /** 378 | * Method tests successful delete. 379 | * 380 | * @throws java.lang.Exception 381 | */ 382 | @Test 383 | public void testDeleteBookmarkHappyPath() throws Exception { 384 | BDDMockito 385 | .given(bookmarksRepository 386 | .findByIdAndUserUsername(BOOKMARK_ID, USERNAME)) 387 | .willReturn(Optional.of(BOOKMARK)); 388 | BDDMockito.doNothing().when(bookmarksRepository).delete(BOOKMARK); 389 | 390 | mvc.perform(MockMvcRequestBuilders 391 | .delete("/" + USERNAME + "/bookmarks/" + BOOKMARK_ID)) 392 | .andExpect(MockMvcResultMatchers.status().isOk()); 393 | 394 | BDDMockito 395 | .verify(bookmarksRepository) 396 | .findByIdAndUserUsername(BOOKMARK_ID, USERNAME); 397 | BDDMockito 398 | .verify(bookmarksRepository).delete(BOOKMARK); 399 | BDDMockito.verifyNoMoreInteractions(bookmarksRepository); 400 | } 401 | } 402 | -------------------------------------------------------------------------------- /src/test/java/com/javaeeeee/controllers/HelloControllerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 Dmitry Noranovich . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.javaeeeee.controllers; 25 | 26 | import org.junit.Test; 27 | import org.junit.Before; 28 | import org.junit.runner.RunWith; 29 | import org.springframework.boot.test.context.SpringBootTest; 30 | import org.springframework.mock.web.MockServletContext; 31 | import org.springframework.test.context.junit4.SpringRunner; 32 | import org.springframework.test.context.web.WebAppConfiguration; 33 | import org.springframework.test.web.servlet.MockMvc; 34 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; 35 | import org.springframework.test.web.servlet.result.MockMvcResultMatchers; 36 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 37 | 38 | /** 39 | * A test class for a simple controller. 40 | * 41 | * @author Dmitry Noranovich 42 | */ 43 | //New in SB 1.4 44 | @RunWith(SpringRunner.class) 45 | //New in SB 1.4 46 | @SpringBootTest(classes = MockServletContext.class) 47 | @WebAppConfiguration 48 | public class HelloControllerTest { 49 | 50 | private static final String NAME = "Phil"; 51 | private MockMvc mvc; 52 | 53 | @Before 54 | public void setUp() { 55 | mvc = MockMvcBuilders 56 | .standaloneSetup(new HelloController()) 57 | .build(); 58 | } 59 | 60 | /** 61 | * Test of getGreeting method, of class HelloController. 62 | * 63 | * @throws java.lang.Exception 64 | */ 65 | @Test 66 | public void testGetGreeting() throws Exception { 67 | System.out.println("getGreeting"); 68 | mvc.perform(MockMvcRequestBuilders.get("/hello")) 69 | .andExpect(MockMvcResultMatchers.status().isOk()) 70 | .andExpect( 71 | MockMvcResultMatchers 72 | .content() 73 | .string(HelloController.GREETING)); 74 | } 75 | 76 | /** 77 | * Test for customized greeting method with path parameter. 78 | * 79 | * @throws java.lang.Exception 80 | */ 81 | @Test 82 | public void testGetPathParamGreeting() throws Exception { 83 | 84 | mvc.perform(MockMvcRequestBuilders.get("/hello/" + NAME)) 85 | .andExpect(MockMvcResultMatchers.status().isOk()) 86 | .andExpect(MockMvcResultMatchers 87 | .content() 88 | .string("Hello " + NAME)); 89 | } 90 | 91 | /** 92 | * Test for customized greeting method with path parameter. 93 | * 94 | * @throws java.lang.Exception 95 | */ 96 | public void testGetQueryParamGreeting() throws Exception { 97 | mvc.perform(MockMvcRequestBuilders.get("/hello?name=" + NAME)) 98 | .andExpect(MockMvcResultMatchers.status().isOk()) 99 | .andExpect(MockMvcResultMatchers 100 | .content() 101 | .string("Hello " + NAME)); 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /src/test/java/com/javaeeeee/entities/BookmarkTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 Dmitry Noranovich . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.javaeeeee.entities; 25 | 26 | import static com.javaeeeee.entities.UserTest.EMPTY_ERROR_MESSAGE; 27 | import org.junit.Assert; 28 | import org.junit.Rule; 29 | import org.junit.Test; 30 | import org.junit.rules.ExpectedException; 31 | import org.junit.runner.RunWith; 32 | import org.springframework.beans.factory.annotation.Autowired; 33 | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; 34 | import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; 35 | import org.springframework.test.context.junit4.SpringRunner; 36 | 37 | /** 38 | * Bookmark entity test. 39 | * 40 | * @author Dmitry Noranovich 41 | */ 42 | @RunWith(SpringRunner.class) 43 | @DataJpaTest 44 | public class BookmarkTest { 45 | 46 | /** 47 | * A user for testing. 48 | */ 49 | private static final User USER = new User("Phil", "1"); 50 | /** 51 | * A test bookmark URL. 52 | */ 53 | private static final String BM_URL = "http://github.com"; 54 | /** 55 | * Error message for incorrect a argument value. 56 | */ 57 | public static final String EMPTY_ERROR_MESSAGE 58 | = "[Assertion failed] - this String argument must have length; " 59 | + "it must not be null or empty"; 60 | /** 61 | * JUnit Rule. 62 | */ 63 | @Rule 64 | public ExpectedException expectedException = ExpectedException.none(); 65 | 66 | /** 67 | * Provide test implementation of EntityManager. 68 | */ 69 | @Autowired 70 | private TestEntityManager entityManager; 71 | 72 | /** 73 | * Test constructor URL is null. 74 | */ 75 | @Test 76 | public void createWhenUrlIsNullShouldThrowException() { 77 | expectException(); 78 | new Bookmark(null, ""); 79 | } 80 | 81 | /** 82 | * Test constructor URL is empty. 83 | */ 84 | @Test 85 | public void createWhenUrlIsEmptyShouldThrowException() { 86 | expectException(); 87 | new Bookmark("", null); 88 | } 89 | 90 | /** 91 | * Test setter URL is null. 92 | */ 93 | @Test 94 | public void modifyWhenUrlIsNullShouldThrowException() { 95 | expectException(); 96 | Bookmark bookmark = new Bookmark(BM_URL, ""); 97 | bookmark.setUrl(null); 98 | } 99 | 100 | /** 101 | * Test setter URL is empty. 102 | */ 103 | @Test 104 | public void modifyWhenUrlIsEmptyShouldThrowException() { 105 | expectException(); 106 | Bookmark bookmark = new Bookmark(BM_URL, ""); 107 | bookmark.setUrl(""); 108 | } 109 | 110 | /** 111 | * Test setter user is null. 112 | */ 113 | @Test 114 | public void modifyWhenUserIsNullShouldThrowException() { 115 | expectedException.expect(IllegalArgumentException.class); 116 | expectedException.expectMessage("[Assertion failed] - " 117 | + "this argument is required; it must not be null"); 118 | Bookmark bookmark = new Bookmark(BM_URL, ""); 119 | bookmark.setUser(null); 120 | } 121 | 122 | 123 | /** 124 | * Test, that entity is saved. 125 | */ 126 | @Test 127 | public void saveShouldPersistData() { 128 | entityManager.persist(USER); 129 | Bookmark bookmark = new Bookmark(BM_URL, ""); 130 | bookmark.setUser(USER); 131 | bookmark = entityManager.persistFlushFind(bookmark); 132 | Assert.assertEquals(BM_URL, bookmark.getUrl()); 133 | } 134 | 135 | /** 136 | * Method that provides exception expectation settings. 137 | */ 138 | private void expectException() { 139 | expectedException.expect(IllegalArgumentException.class); 140 | expectedException.expectMessage(EMPTY_ERROR_MESSAGE); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/test/java/com/javaeeeee/entities/UserTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 Dmitry Noranovich . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.javaeeeee.entities; 25 | 26 | import org.junit.Assert; 27 | import org.junit.Test; 28 | import org.junit.Rule; 29 | import org.junit.rules.ExpectedException; 30 | import org.junit.runner.RunWith; 31 | import org.springframework.beans.factory.annotation.Autowired; 32 | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; 33 | import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; 34 | import org.springframework.test.context.junit4.SpringRunner; 35 | 36 | /** 37 | * User entity test. 38 | * 39 | * @author Dmitry Noranovich 40 | */ 41 | @RunWith(SpringRunner.class) 42 | @DataJpaTest 43 | public class UserTest { 44 | 45 | /** 46 | * Test user name. 47 | */ 48 | public static final String USERNAME = "Phil"; 49 | /** 50 | * Test user password. 51 | */ 52 | public static final String PASSWORD = "1"; 53 | /** 54 | * JUnit Rule, no exceptions are expected. 55 | */ 56 | /** 57 | * Error message for incorrect a argument value. 58 | */ 59 | public static final String EMPTY_ERROR_MESSAGE 60 | = "[Assertion failed] - this String argument must have length; " 61 | + "it must not be null or empty"; 62 | @Rule 63 | public ExpectedException expectedException = ExpectedException.none(); 64 | 65 | /** 66 | * EntityManager provided by Spring for testing purposes. 67 | */ 68 | @Autowired 69 | private TestEntityManager entityManager; 70 | 71 | /** 72 | * Test how constructor treats null username values. 73 | */ 74 | @Test 75 | public void createWhenUsernameIsNullShouldThrowException() { 76 | expectException(); 77 | new User(null, PASSWORD); 78 | } 79 | 80 | /** 81 | * Test how constructor treats empty username values. 82 | */ 83 | @Test 84 | public void createWhenUsernameIsEmptyShouldThrowException() { 85 | expectException(); 86 | new User("", PASSWORD); 87 | } 88 | 89 | /** 90 | * Test how constructor treats null username values. 91 | */ 92 | @Test 93 | public void createWhenPasswordIsNullShouldThrowException() { 94 | expectException(); 95 | new User(USERNAME, null); 96 | } 97 | 98 | /** 99 | * Test how constructor treats empty password values. 100 | */ 101 | @Test 102 | public void createWhenPasswordIsEmptyShouldThrowException() { 103 | expectException(); 104 | new User(USERNAME, ""); 105 | } 106 | 107 | /** 108 | * Test modify username. 109 | */ 110 | @Test 111 | public void modifyWhenUsernameIsNullShouldThrowException() { 112 | expectException(); 113 | User user = new User(USERNAME, PASSWORD); 114 | user.setUsername(null); 115 | } 116 | 117 | /** 118 | * Test modify password. 119 | */ 120 | @Test 121 | public void modifyWhenUserPasswordIsEmptyShouldThrowException() { 122 | expectException(); 123 | User user = new User(USERNAME, PASSWORD); 124 | user.setPassword(""); 125 | } 126 | 127 | /** 128 | * Test add bookmark. 129 | */ 130 | @Test 131 | public void modifyWhenBookmarkIsNullShouldThrowException() { 132 | expectedException.expect(IllegalArgumentException.class); 133 | expectedException 134 | .expectMessage("[Assertion failed] - " 135 | + "this argument is required; it must not be null"); 136 | User user = new User(USERNAME, PASSWORD); 137 | user.addBookmark(null); 138 | } 139 | 140 | /** 141 | * Test save data. In more elaborate case should test that the password is 142 | * encrypted. 143 | */ 144 | @Test 145 | public void saveShouldPersist() { 146 | User user = entityManager 147 | .persistFlushFind(new User(USERNAME, PASSWORD)); 148 | Assert.assertEquals(USERNAME, user.getUsername()); 149 | Assert.assertEquals(PASSWORD, user.getPassword()); 150 | } 151 | 152 | /** 153 | * Method that provides exception expectation settings. 154 | */ 155 | private void expectException() { 156 | expectedException.expect(IllegalArgumentException.class); 157 | expectedException.expectMessage(EMPTY_ERROR_MESSAGE); 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /src/test/java/com/javaeeeee/repositories/BookmarksRepositoryTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 Dmitry Noranovich . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.javaeeeee.repositories; 25 | 26 | import com.javaeeeee.entities.Bookmark; 27 | import com.javaeeeee.entities.User; 28 | import java.util.Optional; 29 | import java.util.Set; 30 | import org.junit.After; 31 | import org.junit.Assert; 32 | import org.junit.Test; 33 | import org.junit.Before; 34 | import org.junit.BeforeClass; 35 | import org.junit.runner.RunWith; 36 | import org.springframework.beans.factory.annotation.Autowired; 37 | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; 38 | import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; 39 | import org.springframework.test.context.junit4.SpringRunner; 40 | 41 | /** 42 | * Test class to test BookmarksRepository interface. 43 | * 44 | * @author Dmitry Noranovich 45 | */ 46 | @RunWith(SpringRunner.class) 47 | @DataJpaTest 48 | public class BookmarksRepositoryTest { 49 | 50 | /** 51 | * Test user name. 52 | */ 53 | private static final String USER_NAME = "Phil"; 54 | 55 | /** 56 | * Some user for testing purposes. 57 | */ 58 | private User user; 59 | /** 60 | * The URL of the test bookmark. 61 | */ 62 | private static final String BM_URL = "http://url.com"; 63 | /** 64 | * The description of the test bookmark. 65 | */ 66 | private static final String BM_DESCRIPTION = "description"; 67 | /** 68 | * A bookmark for testing purposes. 69 | */ 70 | private Bookmark bookmark; 71 | /** 72 | * An entity manager provided by spring for testing. 73 | */ 74 | @Autowired 75 | private TestEntityManager entityManager; 76 | 77 | /** 78 | * System under test. 79 | */ 80 | @Autowired 81 | private BookmarksRepository bookmarksRepository; 82 | 83 | /** 84 | * A method to perform before class initialization. 85 | */ 86 | @BeforeClass 87 | public static void setUpClass() { 88 | } 89 | 90 | /** 91 | * A method used for before method initialization. 92 | */ 93 | @Before 94 | public void setUp() { 95 | user = new User(USER_NAME, "1"); 96 | bookmark = new Bookmark(BM_URL, BM_DESCRIPTION); 97 | user.addBookmark(bookmark); 98 | entityManager 99 | .persist(user); 100 | } 101 | 102 | /** 103 | * Do cleanup after each method. 104 | */ 105 | @After 106 | public void tearDown() { 107 | entityManager.remove(user); 108 | } 109 | 110 | /** 111 | * Test of findByUserUsername method, of class BookmarksRepository. 112 | */ 113 | @Test 114 | public void testFindByUserUsername() { 115 | Set bookmarks 116 | = bookmarksRepository.findByUserUsername(USER_NAME); 117 | 118 | Assert.assertNotNull(bookmarks); 119 | Assert.assertFalse(bookmarks.isEmpty()); 120 | Assert.assertEquals(1, bookmarks.size()); 121 | Assert.assertEquals(USER_NAME, 122 | bookmarks.iterator().next().getUser().getUsername()); 123 | 124 | } 125 | 126 | /** 127 | * Test of findByIdAndUserUsername method, of class BookmarksRepository. 128 | */ 129 | @Test 130 | public void testFindByIdAndUserUsername() { 131 | Optional optional 132 | = bookmarksRepository 133 | .findByIdAndUserUsername(bookmark.getId(), USER_NAME); 134 | Assert.assertNotNull(optional); 135 | Assert.assertTrue(optional.isPresent()); 136 | Bookmark bm = optional.get(); 137 | Assert.assertEquals(BM_URL, bm.getUrl()); 138 | } 139 | 140 | } 141 | -------------------------------------------------------------------------------- /src/test/java/com/javaeeeee/repositories/UsersRepositoryTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright 2016 Dmitry Noranovich . 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package com.javaeeeee.repositories; 25 | 26 | import com.javaeeeee.entities.User; 27 | import java.util.Optional; 28 | import org.junit.Assert; 29 | import org.junit.Before; 30 | import org.junit.Test; 31 | import org.junit.runner.RunWith; 32 | import org.springframework.beans.factory.annotation.Autowired; 33 | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; 34 | import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; 35 | import org.springframework.test.context.junit4.SpringRunner; 36 | 37 | /** 38 | * A class to test UsersRepository. 39 | * https://spring.io/blog/2016/04/15/testing-improvements-in-spring-boot-1-4#testing-the-jpa-slice 40 | * 41 | * @author Dmitry Noranovich 42 | */ 43 | @RunWith(SpringRunner.class) 44 | @DataJpaTest 45 | public class UsersRepositoryTest { 46 | 47 | /** 48 | * Test entity manager provided by Spring. 49 | */ 50 | @Autowired 51 | private TestEntityManager entityManager; 52 | /** 53 | * System under test. 54 | */ 55 | @Autowired 56 | private UsersRepository usersRepository; 57 | 58 | @Before 59 | public void setUpMethod() { 60 | //entityManager.getEntityManager().createQuery("delete from User u").executeUpdate(); 61 | } 62 | 63 | /** 64 | * A method to test that findByUsername returns a user. 65 | */ 66 | @Test 67 | public void findByUsernameShouldReturnAUser() { 68 | final String name = "Phil"; 69 | entityManager.persist(new User(name, "1")); 70 | Optional optional = usersRepository.findByUsername(name); 71 | 72 | Assert.assertTrue(optional.isPresent()); 73 | User user = optional.get(); 74 | 75 | Assert.assertEquals(name, user.getUsername()); 76 | } 77 | 78 | /** 79 | * A methods tests that empty optional is returned is user is nonexistent. 80 | */ 81 | @Test 82 | public void findByUsernameShouldReturnEmpty() { 83 | final String name = "Phil"; 84 | entityManager.persist(new User(name, "1")); 85 | Optional optional = usersRepository.findByUsername(name + "mmm"); 86 | 87 | Assert.assertFalse(optional.isPresent()); 88 | } 89 | 90 | /** 91 | * Method tests happy path. 92 | */ 93 | @Test 94 | public void findByUsernameAndPasswordShouldReturnUser() { 95 | final String name = "Phil"; 96 | final String password = "1"; 97 | entityManager.persist(new User(name, password)); 98 | Optional optional = usersRepository.findByUsernameAndPassword(name, password); 99 | 100 | Assert.assertTrue(optional.isPresent()); 101 | } 102 | 103 | /** 104 | * Method tests sad path. 105 | */ 106 | @Test 107 | public void findByUsernameAndPasswordShouldReturnEmpty() { 108 | final String name = "Phil"; 109 | final String password = "1"; 110 | entityManager.persist(new User(name, password)); 111 | Optional optional = usersRepository 112 | .findByUsernameAndPassword(name, password + "mmm"); 113 | 114 | Assert.assertFalse(optional.isPresent()); 115 | } 116 | } 117 | --------------------------------------------------------------------------------