Skip to content
This repository was archived by the owner on Jan 13, 2023. It is now read-only.

Completed solution #4

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package com.bobocode.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;

import javax.sql.DataSource;

Expand All @@ -17,24 +22,36 @@
* todo: 3. Configure {@link javax.persistence.EntityManagerFactory} bean with name "entityManagerFactory"
* todo: 4. Enable JPA repository, set appropriate package using annotation property "basePackages"
*/
@Configuration
@EnableJpaRepositories(basePackages = "com.bobocode.dao")
public class JpaConfig {

@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.build();
}

@Bean
public JpaVendorAdapter jpaVendorAdapter() {
// todo: create HibernateJpaVendorAdapter
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
// todo: set H2 database
adapter.setDatabase(Database.H2);
// todo: enable DDL generation
throw new UnsupportedOperationException("Application won't start until you provide configs");
adapter.setGenerateDdl(true);
return adapter;
}

public LocalContainerEntityManagerFactoryBean localContainerEMF() {
@Bean("entityManagerFactory")
public LocalContainerEntityManagerFactoryBean localContainerEMF(DataSource dataSource, JpaVendorAdapter jpaVendorAdapter) {
// todo: create and configure required bean
LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
emf.setDataSource(dataSource);
emf.setJpaVendorAdapter(jpaVendorAdapter);
// todo: set package "com.bobocode.model" to scan for JPA entities
throw new UnsupportedOperationException("Application won't start until you provide configs");
emf.setPackagesToScan("com.bobocode.model");// JPA entity classes will be loaded from this package
return emf;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
package com.bobocode.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.persistence.EntityManagerFactory;

/**
* This class is provides root Java config for Spring application.
Expand All @@ -10,6 +17,14 @@
* todo: 2. Configure {@link PlatformTransactionManager} bean with name "transactionManager"
* todo: 3. Enable transaction management
*/
@Configuration
@ComponentScan("com.bobocode")
@EnableTransactionManagement
public class RootConfig {

@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
* <p>
* todo: 1. Configure {@link UserRepository} as {@link JpaRepository} for class User
*/
public interface UserRepository extends JpaRepository {
public interface UserRepository extends JpaRepository<User, Long> {

}
29 changes: 28 additions & 1 deletion user-service/src/main/java/com/bobocode/config/JpaConfig.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
package com.bobocode.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;

import javax.sql.DataSource;

Expand All @@ -16,11 +22,32 @@
* todo: 3. Configure {@link javax.persistence.EntityManagerFactory} bean with name "entityManagerFactory"
* todo: 4. Enable JPA repository
*/
@Configuration
@EnableJpaRepositories(basePackages = "com.bobocode.dao")
public class JpaConfig {

@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.build();
}
}

@Bean
public JpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setDatabase(Database.H2);
vendorAdapter.setGenerateDdl(true);
vendorAdapter.setShowSql(true);
return vendorAdapter;
}

@Bean("entityManagerFactory")
public LocalContainerEntityManagerFactoryBean localContainerEMF() {
LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
emf.setDataSource(dataSource());
emf.setJpaVendorAdapter(jpaVendorAdapter());
emf.setPackagesToScan("com.bobocode.model");
return emf;
}
}
16 changes: 15 additions & 1 deletion user-service/src/main/java/com/bobocode/config/RootConfig.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
package com.bobocode.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.persistence.EntityManagerFactory;

/**
* This class is provides root Java config for Spring application.
Expand All @@ -10,6 +17,13 @@
* todo: 1. Configure {@link PlatformTransactionManager} bean with name "transactionManager"
* todo: 2. Enable transaction management
*/
@Configuration
@ComponentScan("com.bobocode")
@EnableTransactionManagement
public class RootConfig {
}

@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
10 changes: 9 additions & 1 deletion user-service/src/main/java/com/bobocode/dao/UserRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

import com.bobocode.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;
import java.util.Optional;

/**
* This interface represents a data access object (DAO) for {@link User}.
Expand All @@ -13,6 +18,9 @@
* todo: 3. Create method that finds optional user by email fetching its address and roles using {@link org.springframework.data.jpa.repository.Query}
* todo: 4. Add custom User repository interface
*/
public interface UserRepository extends JpaRepository{
public interface UserRepository extends JpaRepository<User, Long>, CustomUserRepository {
List<User> findAllByAddressCity(String city);

@Query("select u from User u left join fetch u.address left join fetch u.roles where u.email = :email")
Optional<User> findByEmailFetchRoles(@Param("email") String email);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.bobocode.dao.impl;

import com.bobocode.dao.CustomUserRepository;
import com.bobocode.model.Role;
import com.bobocode.model.RoleType;
import com.bobocode.model.User;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.List;

@Repository
@Transactional
public class CustomUserRepositoryImpl implements CustomUserRepository {

@PersistenceContext
private EntityManager entityManager;


@Override
public void addRoleToAllUsers(RoleType roleType) {
List<User> users = entityManager.createQuery("select u from User u left join fetch u.roles", User.class)
.getResultList();
users.stream()
.filter(user -> hasNoRole(user, roleType))
.forEach(user -> user.addRole(Role.valueOf(roleType)));
}

private boolean hasNoRole(User user, RoleType roleType) {
return user.getRoles()
.stream()
.map(Role::getRoleType)
.noneMatch(type -> type.equals(roleType));
}
}

19 changes: 16 additions & 3 deletions user-service/src/main/java/com/bobocode/service/UserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import com.bobocode.exception.EntityNotFoundException;
import com.bobocode.model.RoleType;
import com.bobocode.model.User;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

Expand All @@ -17,16 +19,27 @@
* todo: 3. In case user is not found by email, throw {@link EntityNotFoundException} with message "Cannot find user by email ${email}"
* todo: 4. Implement {@link UserService#addRoleToAllUsers(RoleType)} using {@link UserRepository}
*/
@Transactional
@Service
public class UserService {
private final UserRepository userRepository;

public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}

@Transactional(readOnly = true)
public List<User> findByCity(String city) {
throw new UnsupportedOperationException("Do your best and implement this method!");
return userRepository.findAllByAddressCity(city);
}

@Transactional(readOnly = true)
public User getByEmail(String email) {
throw new UnsupportedOperationException("Do your best and implement this method!");
return userRepository.findByEmailFetchRoles(email)
.orElseThrow(() -> new EntityNotFoundException(String.format("Cannot find user by email %s", email)));
}

public void addRoleToAllUsers(RoleType roleType) {
throw new UnsupportedOperationException("Do your best and implement this method!");
userRepository.addRoleToAllUsers(roleType);
}
}