diff --git a/src/main/java/org/springframework/samples/petclinic/configuration/SocketSecurityConfig.java b/src/main/java/org/springframework/samples/petclinic/configuration/SocketSecurityConfig.java index 64b071d4f..64146539a 100644 --- a/src/main/java/org/springframework/samples/petclinic/configuration/SocketSecurityConfig.java +++ b/src/main/java/org/springframework/samples/petclinic/configuration/SocketSecurityConfig.java @@ -1,7 +1,6 @@ package org.springframework.samples.petclinic.configuration; import org.springframework.context.annotation.Configuration; -import org.springframework.messaging.simp.SimpMessageType; import org.springframework.security.config.annotation.web.messaging.MessageSecurityMetadataSourceRegistry; import org.springframework.security.config.annotation.web.socket.AbstractSecurityWebSocketMessageBrokerConfigurer; @@ -28,4 +27,5 @@ public class SocketSecurityConfig extends AbstractSecurityWebSocketMessageBroker protected boolean sameOriginDisabled() { return true; } + } diff --git a/src/main/java/org/springframework/samples/petclinic/configuration/WebSecurityConfig.java b/src/main/java/org/springframework/samples/petclinic/configuration/WebSecurityConfig.java index 8c8492d56..8bc422f6e 100644 --- a/src/main/java/org/springframework/samples/petclinic/configuration/WebSecurityConfig.java +++ b/src/main/java/org/springframework/samples/petclinic/configuration/WebSecurityConfig.java @@ -20,6 +20,8 @@ import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; import org.springframework.security.oauth2.client.registration.ClientRegistration; import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; import javax.annotation.Resource; import java.util.Arrays; @@ -125,10 +127,6 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { return CommonOAuth2Provider.GITHUB.getBuilder(client).clientId(clientId).clientSecret(clientSecret).build(); } - if (client.equals("twitter")) { - return ClientRegistration.withRegistrationId("twitter").clientId(clientId).clientSecret(clientSecret).build(); - } - return null; } diff --git a/src/main/java/org/springframework/samples/petclinic/configuration/WebSocketConfig.java b/src/main/java/org/springframework/samples/petclinic/configuration/WebSocketConfig.java index 43fe18d44..6d4f04c0f 100644 --- a/src/main/java/org/springframework/samples/petclinic/configuration/WebSocketConfig.java +++ b/src/main/java/org/springframework/samples/petclinic/configuration/WebSocketConfig.java @@ -30,7 +30,7 @@ public class WebSocketConfig extends AbstractSecurityWebSocketMessageBrokerConfi @Override public void configureMessageBroker(MessageBrokerRegistry config) { - config.enableSimpleBroker("/topic/public"); + config.enableSimpleBroker("/topic"); config.setApplicationDestinationPrefixes("/app"); } @@ -39,8 +39,6 @@ public class WebSocketConfig extends AbstractSecurityWebSocketMessageBrokerConfi registry.addEndpoint("/websocket").setAllowedOrigins("*").withSockJS(); } - - @Override protected boolean sameOriginDisabled() { return true; diff --git a/src/main/java/org/springframework/samples/petclinic/controller/OwnerController.java b/src/main/java/org/springframework/samples/petclinic/controller/OwnerController.java index e26f377ab..8f5bfef83 100644 --- a/src/main/java/org/springframework/samples/petclinic/controller/OwnerController.java +++ b/src/main/java/org/springframework/samples/petclinic/controller/OwnerController.java @@ -16,7 +16,6 @@ package org.springframework.samples.petclinic.controller; import org.springframework.samples.petclinic.common.*; -import org.springframework.samples.petclinic.controller.common.WebSocketSender; import org.springframework.samples.petclinic.dto.business.OwnerDTO; import org.springframework.samples.petclinic.dto.business.PetDTO; import org.springframework.samples.petclinic.service.business.OwnerService; diff --git a/src/main/java/org/springframework/samples/petclinic/controller/PetController.java b/src/main/java/org/springframework/samples/petclinic/controller/PetController.java index 97277fe64..d325bfee1 100644 --- a/src/main/java/org/springframework/samples/petclinic/controller/PetController.java +++ b/src/main/java/org/springframework/samples/petclinic/controller/PetController.java @@ -17,7 +17,6 @@ package org.springframework.samples.petclinic.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.samples.petclinic.common.*; -import org.springframework.samples.petclinic.controller.common.WebSocketSender; import org.springframework.samples.petclinic.dto.business.OwnerDTO; import org.springframework.samples.petclinic.dto.business.PetDTO; import org.springframework.samples.petclinic.dto.business.PetTypeDTO; @@ -84,8 +83,8 @@ class PetController extends WebSocketSender { } @PostMapping(CommonEndPoint.PETS_NEW) - public String processCreationForm(@ModelAttribute("owner") OwnerDTO owner, @Valid PetDTO pet, BindingResult result, - ModelMap model) { + public String processCreationForm(@ModelAttribute("owner") OwnerDTO owner, @ModelAttribute("pet") @Valid PetDTO pet, + BindingResult result, ModelMap model) { if (owner == null) { sendErrorMessage(CommonWebSocket.PET_CREATION_ERROR); result.rejectValue(CommonAttribute.OWNER, CommonError.NOT_FOUND_ARGS, CommonError.NOT_FOUND_MESSAGE); @@ -118,8 +117,8 @@ class PetController extends WebSocketSender { } @PostMapping("/pets/{petId}/edit") - public String processUpdateForm(@Valid PetDTO pet, BindingResult result, @ModelAttribute("owner") OwnerDTO owner, - ModelMap model) { + public String processUpdateForm(@ModelAttribute("pet") @Valid PetDTO pet, BindingResult result, + @ModelAttribute("owner") OwnerDTO owner, ModelMap model) { if (result.hasErrors()) { pet.setOwner(owner); model.put(CommonAttribute.PET, pet); diff --git a/src/main/java/org/springframework/samples/petclinic/controller/UserController.java b/src/main/java/org/springframework/samples/petclinic/controller/UserController.java index 018391547..47c2358fc 100644 --- a/src/main/java/org/springframework/samples/petclinic/controller/UserController.java +++ b/src/main/java/org/springframework/samples/petclinic/controller/UserController.java @@ -5,7 +5,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.ResolvableType; import org.springframework.data.repository.query.Param; import org.springframework.samples.petclinic.common.*; -import org.springframework.samples.petclinic.controller.common.WebSocketSender; import org.springframework.samples.petclinic.dto.common.CredentialDTO; import org.springframework.samples.petclinic.dto.common.MessageDTO; import org.springframework.samples.petclinic.dto.common.UserDTO; diff --git a/src/main/java/org/springframework/samples/petclinic/controller/VetController.java b/src/main/java/org/springframework/samples/petclinic/controller/VetController.java index 9ffc0819d..b75960553 100644 --- a/src/main/java/org/springframework/samples/petclinic/controller/VetController.java +++ b/src/main/java/org/springframework/samples/petclinic/controller/VetController.java @@ -19,7 +19,6 @@ import org.springframework.samples.petclinic.common.CommonAttribute; import org.springframework.samples.petclinic.common.CommonEndPoint; import org.springframework.samples.petclinic.common.CommonView; import org.springframework.samples.petclinic.common.CommonWebSocket; -import org.springframework.samples.petclinic.controller.common.WebSocketSender; import org.springframework.samples.petclinic.dto.business.VetsDTO; import org.springframework.samples.petclinic.service.business.VetService; import org.springframework.stereotype.Controller; diff --git a/src/main/java/org/springframework/samples/petclinic/controller/VisitController.java b/src/main/java/org/springframework/samples/petclinic/controller/VisitController.java index f06fd65aa..02bf901c1 100644 --- a/src/main/java/org/springframework/samples/petclinic/controller/VisitController.java +++ b/src/main/java/org/springframework/samples/petclinic/controller/VisitController.java @@ -23,7 +23,6 @@ import org.springframework.samples.petclinic.common.CommonAttribute; import org.springframework.samples.petclinic.common.CommonEndPoint; import org.springframework.samples.petclinic.common.CommonView; import org.springframework.samples.petclinic.common.CommonWebSocket; -import org.springframework.samples.petclinic.controller.common.WebSocketSender; import org.springframework.samples.petclinic.dto.business.PetDTO; import org.springframework.samples.petclinic.dto.business.VisitDTO; import org.springframework.samples.petclinic.service.business.PetService; diff --git a/src/main/java/org/springframework/samples/petclinic/controller/common/WebSocketSender.java b/src/main/java/org/springframework/samples/petclinic/controller/WebSocketSender.java similarity index 95% rename from src/main/java/org/springframework/samples/petclinic/controller/common/WebSocketSender.java rename to src/main/java/org/springframework/samples/petclinic/controller/WebSocketSender.java index ae528d212..394fea208 100644 --- a/src/main/java/org/springframework/samples/petclinic/controller/common/WebSocketSender.java +++ b/src/main/java/org/springframework/samples/petclinic/controller/WebSocketSender.java @@ -1,4 +1,4 @@ -package org.springframework.samples.petclinic.controller.common; +package org.springframework.samples.petclinic.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.messaging.simp.SimpMessagingTemplate; @@ -16,7 +16,6 @@ public class WebSocketSender { @Autowired SimpMessagingTemplate simpMessagingTemplate; - public void sendMessage(String message, String type) { // Send message asynchronously new Thread(new Runnable() { diff --git a/src/main/java/org/springframework/samples/petclinic/dto/business/PetDTO.java b/src/main/java/org/springframework/samples/petclinic/dto/business/PetDTO.java index 78a9e5264..070c09091 100644 --- a/src/main/java/org/springframework/samples/petclinic/dto/business/PetDTO.java +++ b/src/main/java/org/springframework/samples/petclinic/dto/business/PetDTO.java @@ -85,6 +85,12 @@ public class PetDTO extends NamedDTO { visit.setPetId(this.getId()); } + @Override + public String toString() { + return "PetDTO{" + "birthDate=" + birthDate + ", type=" + type + ", owner=" + owner + ", visits=" + visits + + '}'; + } + @Override public boolean equals(Object o) { if (this == o) diff --git a/src/main/java/org/springframework/samples/petclinic/model/business/Owner.java b/src/main/java/org/springframework/samples/petclinic/model/business/Owner.java index 7b65cd175..ff6b660f7 100644 --- a/src/main/java/org/springframework/samples/petclinic/model/business/Owner.java +++ b/src/main/java/org/springframework/samples/petclinic/model/business/Owner.java @@ -105,22 +105,20 @@ public class Owner extends Person { } public void addPet(Pet pet) { - - if (this.pets == null) { - this.pets = new HashSet<>(); + if (pet.isNew()) { + getPetsInternal().add(pet); } - try { - if (!this.getPets().contains(pet)) { - getPetsInternal().add(pet); - } - } - catch (Exception exception) { - this.pets = new HashSet<>(); - this.pets.add(pet); - } - pet.setOwner(this); } + /* + * public void addPet(Pet pet) { + * + * if (this.pets == null) { this.pets = new HashSet<>(); } try { if + * (!this.getPets().contains(pet)) { getPetsInternal().add(pet); } } catch (Exception + * exception) { this.pets = new HashSet<>(); this.pets.add(pet); } + * + * pet.setOwner(this); } + */ /** * Return the Pet with the given name, or null if none found for this Owner. diff --git a/src/main/java/org/springframework/samples/petclinic/model/common/User.java b/src/main/java/org/springframework/samples/petclinic/model/common/User.java index 467d0e9ac..3bbf40f89 100644 --- a/src/main/java/org/springframework/samples/petclinic/model/common/User.java +++ b/src/main/java/org/springframework/samples/petclinic/model/common/User.java @@ -54,14 +54,6 @@ public class User extends Person implements Serializable, UserDetails { @Column(name = "credential_unexpired") private boolean credentialsNonExpired; - /* - * @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) - * - * @JoinTable(name = "users_roles", joinColumns = @JoinColumn(name = "user_id", - * referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "role_id", - * referencedColumnName = "id")) private Set roles; - */ - @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) @JoinTable(name = "users_roles", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id")) diff --git a/src/main/java/org/springframework/samples/petclinic/repository/OwnerRepository.java b/src/main/java/org/springframework/samples/petclinic/repository/OwnerRepository.java index abd3b16ba..65f4e4e10 100644 --- a/src/main/java/org/springframework/samples/petclinic/repository/OwnerRepository.java +++ b/src/main/java/org/springframework/samples/petclinic/repository/OwnerRepository.java @@ -54,7 +54,7 @@ public interface OwnerRepository extends Repository { * @param id the id to search for * @return the {@link Owner} if found */ - @Query("SELECT owner FROM Owner owner left join fetch owner.pets WHERE owner.id =:id") + @Query("SELECT DISTINCT owner FROM Owner owner left join fetch owner.pets WHERE owner.id =:id") @Transactional(readOnly = true) Owner findById(@Param("id") Integer id); @@ -62,6 +62,8 @@ public interface OwnerRepository extends Repository { * Retrieve all {@link Owner}s from the data store * @return a Collection of {@link Owner}s (or an empty Collection if none */ + @Query("SELECT DISTINCT owner FROM Owner owner left join fetch owner.pets") + @Transactional(readOnly = true) List findAll(); /** diff --git a/src/main/java/org/springframework/samples/petclinic/service/business/OwnerService.java b/src/main/java/org/springframework/samples/petclinic/service/business/OwnerService.java index 96b00093a..169935789 100644 --- a/src/main/java/org/springframework/samples/petclinic/service/business/OwnerService.java +++ b/src/main/java/org/springframework/samples/petclinic/service/business/OwnerService.java @@ -100,20 +100,6 @@ public class OwnerService implements BaseService { public List findAll() { List owners = ownerRepository.findAll(); - // Add pets for each owners - owners.forEach(owner -> { - - // Find owner pets - List pets = petRepository.findByOwnerId(owner.getId()); - - pets.forEach(pet -> { - // Add pet to the owner - owner.addPet(pet); - // Add owner to the pet - pet.setOwner(owner); - }); - }); - return entitiesToDTOS(owners); } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 58265a9b7..3433086c8 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -26,11 +26,10 @@ spring.resources.cache.cachecontrol.max-age=12h ########################################################################## DEBUG #logging.level.root=DEBUG -#logging.level.org.springframework.web: DEBUG #logging.level.org.hibernate: DEBUG #logging.level.org.springframework.context.annotation=TRACE -logging.level.org.springframework.security=TRACE -logging.level.org.springframework.web=TRACE +#logging.level.org.springframework.security=TRACE +#logging.level.org.springframework.web=TRACE spring.datasource.hikari.connectionTimeout=20000 spring.datasource.hikari.maximumPoolSize=5 diff --git a/src/main/resources/static/resources/js/notification.js b/src/main/resources/static/resources/js/notification.js index 6074f25f7..681ee9fa1 100644 --- a/src/main/resources/static/resources/js/notification.js +++ b/src/main/resources/static/resources/js/notification.js @@ -1,8 +1,7 @@ -var stompClient = null; function displayMessage() { var socket = new SockJS('/websocket'); - stompClient = Stomp.over(socket); + var stompClient = Stomp.over(socket); stompClient.connect({}, function (frame) { stompClient.subscribe('/topic/public', function (socketMessage) { diff --git a/src/test/java/org/springframework/samples/petclinic/controller/OwnerControllerTest.java b/src/test/java/org/springframework/samples/petclinic/controller/OwnerControllerTest.java index afedaf6af..ce0a19e4e 100644 --- a/src/test/java/org/springframework/samples/petclinic/controller/OwnerControllerTest.java +++ b/src/test/java/org/springframework/samples/petclinic/controller/OwnerControllerTest.java @@ -36,7 +36,6 @@ import org.springframework.samples.petclinic.common.CommonAttribute; import org.springframework.samples.petclinic.common.CommonEndPoint; import org.springframework.samples.petclinic.common.CommonError; import org.springframework.samples.petclinic.common.CommonView; -import org.springframework.samples.petclinic.controller.common.WebSocketSender; import org.springframework.samples.petclinic.dto.business.OwnerDTO; import org.springframework.samples.petclinic.dto.business.PetDTO; import org.springframework.samples.petclinic.dto.business.PetTypeDTO; diff --git a/src/test/java/org/springframework/samples/petclinic/controller/PetControllerTest.java b/src/test/java/org/springframework/samples/petclinic/controller/PetControllerTest.java index af0f10ce6..978b43da4 100644 --- a/src/test/java/org/springframework/samples/petclinic/controller/PetControllerTest.java +++ b/src/test/java/org/springframework/samples/petclinic/controller/PetControllerTest.java @@ -28,7 +28,9 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.junit.runner.RunWith; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; @@ -47,9 +49,12 @@ import org.springframework.samples.petclinic.service.business.OwnerService; import org.springframework.samples.petclinic.service.business.PetService; import org.springframework.samples.petclinic.service.business.PetTypeService; import org.springframework.samples.petclinic.service.common.UserDetailsServiceImpl; +import org.springframework.samples.petclinic.validator.PetDTOValidator; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; +import org.springframework.web.bind.WebDataBinder; +import org.springframework.web.bind.annotation.InitBinder; /** * Test class for the {@link PetController} @@ -60,6 +65,7 @@ import org.springframework.test.web.servlet.MockMvc; @WebMvcTest(value = PetController.class, includeFilters = @ComponentScan.Filter(value = PetTypeFormatter.class, type = FilterType.ASSIGNABLE_TYPE)) @RunWith(SpringRunner.class) +@ExtendWith(MockitoExtension.class) class PetControllerTest { private static final int TEST_OWNER_ID = 1; @@ -136,6 +142,7 @@ class PetControllerTest { @Tag("processCreationForm") @DisplayName("Verify that return to Pet creation form when pet has no type") void givenNewPetWithoutType_whenPostNewPet_thenRedirectToPetUpdate() throws Exception { + mockMvc.perform(post(CommonEndPoint.OWNERS_ID + CommonEndPoint.PETS_NEW, TEST_OWNER_ID) .param(CommonAttribute.PET_NAME, "Betty").param(CommonAttribute.PET_BIRTH_DATE, "2015-02-12")) .andExpect(model().attributeHasNoErrors(CommonAttribute.OWNER)) diff --git a/src/test/java/org/springframework/samples/petclinic/validator/ValidatorTest.java b/src/test/java/org/springframework/samples/petclinic/validator/ValidatorTest.java index 577255c1f..029b88ec5 100644 --- a/src/test/java/org/springframework/samples/petclinic/validator/ValidatorTest.java +++ b/src/test/java/org/springframework/samples/petclinic/validator/ValidatorTest.java @@ -16,6 +16,7 @@ package org.springframework.samples.petclinic.validator; +import java.util.Arrays; import java.util.Locale; import java.util.Set; @@ -55,7 +56,9 @@ class ValidatorTest { assertThat(constraintViolations).hasSize(2); ConstraintViolation violation = constraintViolations.iterator().next(); assertThat(violation.getPropertyPath().toString()).isEqualTo("firstName"); - assertThat(violation.getMessage()).isEqualTo("must not be empty"); + + assertThat(Arrays.asList("Length should be between : 2 AND 50 !", "must not be empty")) + .contains(violation.getMessage()); } }