commit
						13ce413ed2
					
				
							
								
								
									
										4
									
								
								algorithms-miscellaneous-6/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								algorithms-miscellaneous-6/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,4 @@ | |||||||
|  | ### Relevant Articles: | ||||||
|  | 
 | ||||||
|  | - [Boruvka’s Algorithm for Minimum Spanning Trees](https://www.baeldung.com/java-boruvka-algorithm) | ||||||
|  | - [Gradient Descent in Java](https://www.baeldung.com/java-gradient-descent) | ||||||
							
								
								
									
										7
									
								
								atomikos/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								atomikos/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | |||||||
|  | ## Atomikos | ||||||
|  | 
 | ||||||
|  | This module contains articles about Atomikos | ||||||
|  | 
 | ||||||
|  | ### Relevant Articles:  | ||||||
|  | 
 | ||||||
|  | - [Guide Transactions Using Atomikos]() | ||||||
							
								
								
									
										119
									
								
								atomikos/pom.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								atomikos/pom.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,119 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <project xmlns="http://maven.apache.org/POM/4.0.0" | ||||||
|  | 	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||
|  | 	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||||||
|  | 	<modelVersion>4.0.0</modelVersion> | ||||||
|  | 	<artifactId>atomikos</artifactId> | ||||||
|  | 	<name>atomikos</name> | ||||||
|  | 
 | ||||||
|  | 	<parent> | ||||||
|  | 		<groupId>com.baeldung</groupId> | ||||||
|  | 		<artifactId>parent-modules</artifactId> | ||||||
|  | 		<version>1.0.0-SNAPSHOT</version> | ||||||
|  | 	</parent> | ||||||
|  | 
 | ||||||
|  | 	<dependencies> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>com.atomikos</groupId> | ||||||
|  | 			<artifactId>transactions-jdbc</artifactId> | ||||||
|  | 			<version>${atomikos-version}</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>com.atomikos</groupId> | ||||||
|  | 			<artifactId>transactions-jms</artifactId> | ||||||
|  | 			<version>${atomikos-version}</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>com.atomikos</groupId> | ||||||
|  | 			<artifactId>transactions-hibernate4</artifactId> | ||||||
|  | 			<version>${atomikos-version}</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>org.springframework</groupId> | ||||||
|  | 			<artifactId>spring-context</artifactId> | ||||||
|  | 			<version>${spring-version}</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>org.springframework</groupId> | ||||||
|  | 			<artifactId>spring-tx</artifactId> | ||||||
|  | 			<version>${spring-version}</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>org.springframework.data</groupId> | ||||||
|  | 			<artifactId>spring-data-jpa</artifactId> | ||||||
|  | 			<version>1.11.23.RELEASE</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>org.springframework</groupId> | ||||||
|  | 			<artifactId>spring-test</artifactId> | ||||||
|  | 			<version>${spring-version}</version> | ||||||
|  | 			<scope>test</scope> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>org.hibernate</groupId> | ||||||
|  | 			<artifactId>hibernate-entitymanager</artifactId> | ||||||
|  | 			<version>${hibernate.version}</version> | ||||||
|  | 			<scope>provided</scope> | ||||||
|  | 			<exclusions> | ||||||
|  | 				<exclusion> | ||||||
|  | 					<groupId>javax.transaction</groupId> | ||||||
|  | 					<artifactId>jta</artifactId> | ||||||
|  | 				</exclusion> | ||||||
|  | 			</exclusions> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>org.apache.activemq</groupId> | ||||||
|  | 			<artifactId>activemq-core</artifactId> | ||||||
|  | 			<version>5.7.0</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>org.apache.derby</groupId> | ||||||
|  | 			<artifactId>derby</artifactId> | ||||||
|  | 			<version>10.8.1.2</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>junit</groupId> | ||||||
|  | 			<artifactId>junit</artifactId> | ||||||
|  | 			<version>4.12</version> | ||||||
|  | 			<scope>test</scope> | ||||||
|  | 		</dependency> | ||||||
|  | 		<!-- the JTA API --> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>javax.transaction</groupId> | ||||||
|  | 			<artifactId>jta</artifactId> | ||||||
|  | 			<version>1.1</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>org.apache.geronimo.specs</groupId> | ||||||
|  | 			<artifactId>geronimo-jta_1.0.1B_spec</artifactId> | ||||||
|  | 			<version>1.0</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>javax.validation</groupId> | ||||||
|  | 			<artifactId>validation-api</artifactId> | ||||||
|  | 			<version>2.0.1.Final</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>org.hibernate.validator</groupId> | ||||||
|  | 			<artifactId>hibernate-validator</artifactId> | ||||||
|  | 			<version>6.1.2.Final</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>javax.el</groupId> | ||||||
|  | 			<artifactId>javax.el-api</artifactId> | ||||||
|  | 			<version>3.0.0</version> | ||||||
|  | 		</dependency> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>org.glassfish.web</groupId> | ||||||
|  | 			<artifactId>javax.el</artifactId> | ||||||
|  | 			<version>2.2.4</version> | ||||||
|  | 		</dependency> | ||||||
|  | 	</dependencies> | ||||||
|  | 
 | ||||||
|  | 	<properties> | ||||||
|  | 		<atomikos-version>5.0.6</atomikos-version> | ||||||
|  | 		<spring-version>5.1.6.RELEASE</spring-version> | ||||||
|  | 		<hibernate.version>5.4.3.Final</hibernate.version> | ||||||
|  | 	</properties> | ||||||
|  | 
 | ||||||
|  | </project> | ||||||
| @ -0,0 +1,53 @@ | |||||||
|  | package com.baeldung.atomikos.direct; | ||||||
|  | 
 | ||||||
|  | import java.sql.Connection; | ||||||
|  | import java.sql.Statement; | ||||||
|  | import java.util.UUID; | ||||||
|  | 
 | ||||||
|  | import javax.sql.DataSource; | ||||||
|  | 
 | ||||||
|  | import com.atomikos.icatch.jta.UserTransactionImp; | ||||||
|  | 
 | ||||||
|  | public class Application { | ||||||
|  | 
 | ||||||
|  |     private DataSource inventoryDataSource; | ||||||
|  |     private DataSource orderDataSource; | ||||||
|  | 
 | ||||||
|  |     public Application(DataSource inventoryDataSource, DataSource orderDataSource) { | ||||||
|  |         this.inventoryDataSource = inventoryDataSource; | ||||||
|  |         this.orderDataSource = orderDataSource; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void placeOrder(String productId, int amount) throws Exception { | ||||||
|  | 
 | ||||||
|  |         UserTransactionImp utx = new UserTransactionImp(); | ||||||
|  |         String orderId = UUID.randomUUID() | ||||||
|  |             .toString(); | ||||||
|  |         boolean rollback = false; | ||||||
|  |         try { | ||||||
|  |             utx.begin(); | ||||||
|  |             Connection inventoryConnection = inventoryDataSource.getConnection(); | ||||||
|  |             Connection orderConnection = orderDataSource.getConnection(); | ||||||
|  |             Statement s1 = inventoryConnection.createStatement(); | ||||||
|  |             String q1 = "update Inventory set balance = balance - " + amount + " where productId ='" + productId + "'"; | ||||||
|  |             s1.executeUpdate(q1); | ||||||
|  |             s1.close(); | ||||||
|  |             Statement s2 = orderConnection.createStatement(); | ||||||
|  |             String q2 = "insert into Orders values ( '" + orderId + "', '" + productId + "', " + amount + " )"; | ||||||
|  |             s2.executeUpdate(q2); | ||||||
|  |             s2.close(); | ||||||
|  |             inventoryConnection.close(); | ||||||
|  |             orderConnection.close(); | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             System.out.println(e.getMessage()); | ||||||
|  |             rollback = true; | ||||||
|  |         } finally { | ||||||
|  |             if (!rollback) | ||||||
|  |                 utx.commit(); | ||||||
|  |             else | ||||||
|  |                 utx.rollback(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,41 @@ | |||||||
|  | package com.baeldung.atomikos.spring; | ||||||
|  | 
 | ||||||
|  | import java.sql.Connection; | ||||||
|  | import java.sql.Statement; | ||||||
|  | import java.util.UUID; | ||||||
|  | 
 | ||||||
|  | import javax.sql.DataSource; | ||||||
|  | 
 | ||||||
|  | import org.springframework.transaction.annotation.Transactional; | ||||||
|  | 
 | ||||||
|  | public class Application { | ||||||
|  | 
 | ||||||
|  |     private DataSource inventoryDataSource; | ||||||
|  |     private DataSource orderDataSource; | ||||||
|  | 
 | ||||||
|  |     public Application(DataSource inventoryDataSource, DataSource orderDataSource) { | ||||||
|  |         this.inventoryDataSource = inventoryDataSource; | ||||||
|  |         this.orderDataSource = orderDataSource; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Transactional(rollbackFor = Exception.class) | ||||||
|  |     public void placeOrder(String productId, int amount) throws Exception { | ||||||
|  | 
 | ||||||
|  |         String orderId = UUID.randomUUID() | ||||||
|  |             .toString(); | ||||||
|  |         Connection inventoryConnection = inventoryDataSource.getConnection(); | ||||||
|  |         Connection orderConnection = orderDataSource.getConnection(); | ||||||
|  |         Statement s1 = inventoryConnection.createStatement(); | ||||||
|  |         String q1 = "update Inventory set balance = balance - " + amount + " where productId ='" + productId + "'"; | ||||||
|  |         s1.executeUpdate(q1); | ||||||
|  |         s1.close(); | ||||||
|  |         Statement s2 = orderConnection.createStatement(); | ||||||
|  |         String q2 = "insert into Orders values ( '" + orderId + "', '" + productId + "', " + amount + " )"; | ||||||
|  |         s2.executeUpdate(q2); | ||||||
|  |         s2.close(); | ||||||
|  |         inventoryConnection.close(); | ||||||
|  |         orderConnection.close(); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,68 @@ | |||||||
|  | package com.baeldung.atomikos.spring.config; | ||||||
|  | 
 | ||||||
|  | import java.util.Properties; | ||||||
|  | 
 | ||||||
|  | import javax.transaction.SystemException; | ||||||
|  | 
 | ||||||
|  | import org.springframework.context.annotation.Bean; | ||||||
|  | import org.springframework.context.annotation.Configuration; | ||||||
|  | import org.springframework.transaction.annotation.EnableTransactionManagement; | ||||||
|  | import org.springframework.transaction.jta.JtaTransactionManager; | ||||||
|  | 
 | ||||||
|  | import com.atomikos.icatch.jta.UserTransactionManager; | ||||||
|  | import com.atomikos.jdbc.AtomikosDataSourceBean; | ||||||
|  | import com.baeldung.atomikos.spring.Application; | ||||||
|  | 
 | ||||||
|  | @Configuration | ||||||
|  | @EnableTransactionManagement | ||||||
|  | public class Config { | ||||||
|  | 
 | ||||||
|  |     @Bean(initMethod = "init", destroyMethod = "close") | ||||||
|  |     public AtomikosDataSourceBean inventoryDataSource() { | ||||||
|  |         AtomikosDataSourceBean dataSource = new AtomikosDataSourceBean(); | ||||||
|  |         dataSource.setLocalTransactionMode(true); | ||||||
|  |         dataSource.setUniqueResourceName("db1"); | ||||||
|  |         dataSource.setXaDataSourceClassName("org.apache.derby.jdbc.EmbeddedXADataSource"); | ||||||
|  |         Properties xaProperties = new Properties(); | ||||||
|  |         xaProperties.put("databaseName", "db1"); | ||||||
|  |         xaProperties.put("createDatabase", "create"); | ||||||
|  |         dataSource.setXaProperties(xaProperties); | ||||||
|  |         dataSource.setPoolSize(10); | ||||||
|  |         return dataSource; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Bean(initMethod = "init", destroyMethod = "close") | ||||||
|  |     public AtomikosDataSourceBean orderDataSource() { | ||||||
|  |         AtomikosDataSourceBean dataSource = new AtomikosDataSourceBean(); | ||||||
|  |         dataSource.setLocalTransactionMode(true); | ||||||
|  |         dataSource.setUniqueResourceName("db2"); | ||||||
|  |         dataSource.setXaDataSourceClassName("org.apache.derby.jdbc.EmbeddedXADataSource"); | ||||||
|  |         Properties xaProperties = new Properties(); | ||||||
|  |         xaProperties.put("databaseName", "db2"); | ||||||
|  |         xaProperties.put("createDatabase", "create"); | ||||||
|  |         dataSource.setXaProperties(xaProperties); | ||||||
|  |         dataSource.setPoolSize(10); | ||||||
|  |         return dataSource; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Bean(initMethod = "init", destroyMethod = "close") | ||||||
|  |     public UserTransactionManager userTransactionManager() throws SystemException { | ||||||
|  |         UserTransactionManager userTransactionManager = new UserTransactionManager(); | ||||||
|  |         userTransactionManager.setTransactionTimeout(300); | ||||||
|  |         userTransactionManager.setForceShutdown(true); | ||||||
|  |         return userTransactionManager; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Bean | ||||||
|  |     public JtaTransactionManager jtaTransactionManager() throws SystemException { | ||||||
|  |         JtaTransactionManager jtaTransactionManager = new JtaTransactionManager(); | ||||||
|  |         jtaTransactionManager.setTransactionManager(userTransactionManager()); | ||||||
|  |         jtaTransactionManager.setUserTransaction(userTransactionManager()); | ||||||
|  |         return jtaTransactionManager; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Bean | ||||||
|  |     public Application application() { | ||||||
|  |         return new Application(inventoryDataSource(), orderDataSource()); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,48 @@ | |||||||
|  | package com.baeldung.atomikos.spring.jpa; | ||||||
|  | 
 | ||||||
|  | import java.util.Set; | ||||||
|  | import java.util.UUID; | ||||||
|  | 
 | ||||||
|  | import javax.validation.ConstraintViolation; | ||||||
|  | import javax.validation.Validation; | ||||||
|  | import javax.validation.Validator; | ||||||
|  | import javax.validation.ValidatorFactory; | ||||||
|  | 
 | ||||||
|  | import org.springframework.beans.factory.annotation.Autowired; | ||||||
|  | import org.springframework.transaction.annotation.Transactional; | ||||||
|  | 
 | ||||||
|  | import com.baeldung.atomikos.spring.jpa.inventory.Inventory; | ||||||
|  | import com.baeldung.atomikos.spring.jpa.inventory.InventoryRepository; | ||||||
|  | import com.baeldung.atomikos.spring.jpa.order.Order; | ||||||
|  | import com.baeldung.atomikos.spring.jpa.order.OrderRepository; | ||||||
|  | 
 | ||||||
|  | public class Application { | ||||||
|  | 
 | ||||||
|  |     @Autowired | ||||||
|  |     private InventoryRepository inventoryRepository; | ||||||
|  | 
 | ||||||
|  |     @Autowired | ||||||
|  |     private OrderRepository orderRepository; | ||||||
|  | 
 | ||||||
|  |     @Transactional(rollbackFor = Exception.class) | ||||||
|  |     public void placeOrder(String productId, int amount) throws Exception { | ||||||
|  | 
 | ||||||
|  |         String orderId = UUID.randomUUID() | ||||||
|  |             .toString(); | ||||||
|  |         Inventory inventory = inventoryRepository.findOne(productId); | ||||||
|  |         inventory.setBalance(inventory.getBalance() - amount); | ||||||
|  |         inventoryRepository.save(inventory); | ||||||
|  |         Order order = new Order(); | ||||||
|  |         order.setOrderId(orderId); | ||||||
|  |         order.setProductId(productId); | ||||||
|  |         order.setAmount(new Long(amount)); | ||||||
|  |         ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); | ||||||
|  |         Validator validator = factory.getValidator(); | ||||||
|  |         Set<ConstraintViolation<Order>> violations = validator.validate(order); | ||||||
|  |         if (violations.size() > 0) | ||||||
|  |             throw new Exception("Invalid instance of an order."); | ||||||
|  |         orderRepository.save(order); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,38 @@ | |||||||
|  | package com.baeldung.atomikos.spring.jpa.config; | ||||||
|  | 
 | ||||||
|  | import javax.transaction.SystemException; | ||||||
|  | 
 | ||||||
|  | import org.springframework.context.annotation.Bean; | ||||||
|  | import org.springframework.context.annotation.Configuration; | ||||||
|  | import org.springframework.transaction.annotation.EnableTransactionManagement; | ||||||
|  | import org.springframework.transaction.jta.JtaTransactionManager; | ||||||
|  | 
 | ||||||
|  | import com.atomikos.icatch.jta.UserTransactionManager; | ||||||
|  | import com.baeldung.atomikos.spring.jpa.Application; | ||||||
|  | 
 | ||||||
|  | @Configuration | ||||||
|  | @EnableTransactionManagement | ||||||
|  | public class Config { | ||||||
|  | 
 | ||||||
|  |     @Bean(initMethod = "init", destroyMethod = "close") | ||||||
|  |     public UserTransactionManager userTransactionManager() throws SystemException { | ||||||
|  |         UserTransactionManager userTransactionManager = new UserTransactionManager(); | ||||||
|  |         userTransactionManager.setTransactionTimeout(300); | ||||||
|  |         userTransactionManager.setForceShutdown(true); | ||||||
|  |         return userTransactionManager; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Bean | ||||||
|  |     public JtaTransactionManager transactionManager() throws SystemException { | ||||||
|  |         JtaTransactionManager jtaTransactionManager = new JtaTransactionManager(); | ||||||
|  |         jtaTransactionManager.setTransactionManager(userTransactionManager()); | ||||||
|  |         jtaTransactionManager.setUserTransaction(userTransactionManager()); | ||||||
|  |         return jtaTransactionManager; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Bean | ||||||
|  |     public Application application() { | ||||||
|  |         return new Application(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,31 @@ | |||||||
|  | package com.baeldung.atomikos.spring.jpa.inventory; | ||||||
|  | 
 | ||||||
|  | import javax.persistence.Entity; | ||||||
|  | import javax.persistence.Id; | ||||||
|  | import javax.persistence.Table; | ||||||
|  | 
 | ||||||
|  | @Entity | ||||||
|  | @Table(name = "INVENTORY") | ||||||
|  | public class Inventory { | ||||||
|  | 
 | ||||||
|  |     @Id | ||||||
|  |     private String productId; | ||||||
|  |     private Long balance; | ||||||
|  | 
 | ||||||
|  |     public String getProductId() { | ||||||
|  |         return productId; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setProductId(String productId) { | ||||||
|  |         this.productId = productId; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Long getBalance() { | ||||||
|  |         return balance; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setBalance(Long balance) { | ||||||
|  |         this.balance = balance; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,53 @@ | |||||||
|  | package com.baeldung.atomikos.spring.jpa.inventory; | ||||||
|  | 
 | ||||||
|  | import java.util.Properties; | ||||||
|  | 
 | ||||||
|  | import javax.persistence.EntityManagerFactory; | ||||||
|  | 
 | ||||||
|  | import org.springframework.context.annotation.Bean; | ||||||
|  | import org.springframework.context.annotation.Configuration; | ||||||
|  | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; | ||||||
|  | import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; | ||||||
|  | import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; | ||||||
|  | 
 | ||||||
|  | import com.atomikos.jdbc.AtomikosDataSourceBean; | ||||||
|  | 
 | ||||||
|  | @Configuration | ||||||
|  | @EnableJpaRepositories(basePackages = "com.baeldung.atomikos.spring.jpa.inventory", entityManagerFactoryRef = "inventoryEntityManager", transactionManagerRef = "transactionManager") | ||||||
|  | public class InventoryConfig { | ||||||
|  | 
 | ||||||
|  |     @Bean(initMethod = "init", destroyMethod = "close") | ||||||
|  |     public AtomikosDataSourceBean inventoryDataSource() { | ||||||
|  |         AtomikosDataSourceBean dataSource = new AtomikosDataSourceBean(); | ||||||
|  |         dataSource.setLocalTransactionMode(true); | ||||||
|  |         dataSource.setUniqueResourceName("db1"); | ||||||
|  |         dataSource.setXaDataSourceClassName("org.apache.derby.jdbc.EmbeddedXADataSource"); | ||||||
|  |         Properties xaProperties = new Properties(); | ||||||
|  |         xaProperties.put("databaseName", "db1"); | ||||||
|  |         xaProperties.put("createDatabase", "create"); | ||||||
|  |         dataSource.setXaProperties(xaProperties); | ||||||
|  |         dataSource.setPoolSize(10); | ||||||
|  |         return dataSource; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Bean | ||||||
|  |     public EntityManagerFactory inventoryEntityManager() { | ||||||
|  |         HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); | ||||||
|  |         LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); | ||||||
|  |         factory.setJpaVendorAdapter(vendorAdapter); | ||||||
|  |         factory.setPackagesToScan("com.baeldung.atomikos.spring.jpa.inventory"); | ||||||
|  |         factory.setDataSource(inventoryDataSource()); | ||||||
|  |         Properties jpaProperties = new Properties(); | ||||||
|  |         //jpaProperties.put("hibernate.show_sql", "true"); | ||||||
|  |         //jpaProperties.put("hibernate.format_sql", "true"); | ||||||
|  |         jpaProperties.put("hibernate.dialect", "org.hibernate.dialect.DerbyDialect"); | ||||||
|  |         jpaProperties.put("hibernate.current_session_context_class", "jta"); | ||||||
|  |         jpaProperties.put("javax.persistence.transactionType", "jta"); | ||||||
|  |         jpaProperties.put("hibernate.transaction.manager_lookup_class", "com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup"); | ||||||
|  |         jpaProperties.put("hibernate.hbm2ddl.auto", "create-drop"); | ||||||
|  |         factory.setJpaProperties(jpaProperties); | ||||||
|  |         factory.afterPropertiesSet(); | ||||||
|  |         return factory.getObject(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,9 @@ | |||||||
|  | package com.baeldung.atomikos.spring.jpa.inventory; | ||||||
|  | 
 | ||||||
|  | import org.springframework.data.jpa.repository.JpaRepository; | ||||||
|  | import org.springframework.stereotype.Repository; | ||||||
|  | 
 | ||||||
|  | @Repository | ||||||
|  | public interface InventoryRepository extends JpaRepository<Inventory, String> { | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,42 @@ | |||||||
|  | package com.baeldung.atomikos.spring.jpa.order; | ||||||
|  | 
 | ||||||
|  | import javax.persistence.Entity; | ||||||
|  | import javax.persistence.Id; | ||||||
|  | import javax.persistence.Table; | ||||||
|  | import javax.validation.constraints.Max; | ||||||
|  | 
 | ||||||
|  | @Entity | ||||||
|  | @Table(name = "ORDERS") | ||||||
|  | public class Order { | ||||||
|  | 
 | ||||||
|  |     @Id | ||||||
|  |     private String orderId; | ||||||
|  |     private String productId; | ||||||
|  |     @Max(5) | ||||||
|  |     private Long amount; | ||||||
|  | 
 | ||||||
|  |     public String getOrderId() { | ||||||
|  |         return orderId; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setOrderId(String orderId) { | ||||||
|  |         this.orderId = orderId; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public String getProductId() { | ||||||
|  |         return productId; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setProductId(String productId) { | ||||||
|  |         this.productId = productId; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Long getAmount() { | ||||||
|  |         return amount; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setAmount(Long amount) { | ||||||
|  |         this.amount = amount; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,53 @@ | |||||||
|  | package com.baeldung.atomikos.spring.jpa.order; | ||||||
|  | 
 | ||||||
|  | import java.util.Properties; | ||||||
|  | 
 | ||||||
|  | import javax.persistence.EntityManagerFactory; | ||||||
|  | 
 | ||||||
|  | import org.springframework.context.annotation.Bean; | ||||||
|  | import org.springframework.context.annotation.Configuration; | ||||||
|  | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; | ||||||
|  | import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; | ||||||
|  | import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; | ||||||
|  | 
 | ||||||
|  | import com.atomikos.jdbc.AtomikosDataSourceBean; | ||||||
|  | 
 | ||||||
|  | @Configuration | ||||||
|  | @EnableJpaRepositories(basePackages = "com.baeldung.atomikos.spring.jpa.order", entityManagerFactoryRef = "orderEntityManager", transactionManagerRef = "transactionManager") | ||||||
|  | public class OrderConfig { | ||||||
|  | 
 | ||||||
|  |     @Bean(initMethod = "init", destroyMethod = "close") | ||||||
|  |     public AtomikosDataSourceBean orderDataSource() { | ||||||
|  |         AtomikosDataSourceBean dataSource = new AtomikosDataSourceBean(); | ||||||
|  |         dataSource.setLocalTransactionMode(true); | ||||||
|  |         dataSource.setUniqueResourceName("db2"); | ||||||
|  |         dataSource.setXaDataSourceClassName("org.apache.derby.jdbc.EmbeddedXADataSource"); | ||||||
|  |         Properties xaProperties = new Properties(); | ||||||
|  |         xaProperties.put("databaseName", "db2"); | ||||||
|  |         xaProperties.put("createDatabase", "create"); | ||||||
|  |         dataSource.setXaProperties(xaProperties); | ||||||
|  |         dataSource.setPoolSize(10); | ||||||
|  |         return dataSource; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Bean | ||||||
|  |     public EntityManagerFactory orderEntityManager() { | ||||||
|  |         HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); | ||||||
|  |         LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); | ||||||
|  |         factory.setJpaVendorAdapter(vendorAdapter); | ||||||
|  |         factory.setPackagesToScan("com.baeldung.atomikos.spring.jpa.order"); | ||||||
|  |         factory.setDataSource(orderDataSource()); | ||||||
|  |         Properties jpaProperties = new Properties(); | ||||||
|  |         //jpaProperties.put("hibernate.show_sql", "true"); | ||||||
|  |         //jpaProperties.put("hibernate.format_sql", "true"); | ||||||
|  |         jpaProperties.put("hibernate.dialect", "org.hibernate.dialect.DerbyDialect"); | ||||||
|  |         jpaProperties.put("hibernate.current_session_context_class", "jta"); | ||||||
|  |         jpaProperties.put("javax.persistence.transactionType", "jta"); | ||||||
|  |         jpaProperties.put("hibernate.transaction.manager_lookup_class", "com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup"); | ||||||
|  |         jpaProperties.put("hibernate.hbm2ddl.auto", "create-drop"); | ||||||
|  |         factory.setJpaProperties(jpaProperties); | ||||||
|  |         factory.afterPropertiesSet(); | ||||||
|  |         return factory.getObject(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,9 @@ | |||||||
|  | package com.baeldung.atomikos.spring.jpa.order; | ||||||
|  | 
 | ||||||
|  | import org.springframework.data.jpa.repository.JpaRepository; | ||||||
|  | import org.springframework.stereotype.Repository; | ||||||
|  | 
 | ||||||
|  | @Repository | ||||||
|  | public interface OrderRepository extends JpaRepository<Order, String> { | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										13
									
								
								atomikos/src/main/resources/logback.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								atomikos/src/main/resources/logback.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <configuration> | ||||||
|  |     <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> | ||||||
|  |         <encoder> | ||||||
|  |             <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n | ||||||
|  |             </pattern> | ||||||
|  |         </encoder> | ||||||
|  |     </appender> | ||||||
|  | 
 | ||||||
|  |     <root level="INFO"> | ||||||
|  |         <appender-ref ref="STDOUT" /> | ||||||
|  |     </root> | ||||||
|  | </configuration> | ||||||
							
								
								
									
										10
									
								
								atomikos/src/main/resources/schema.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								atomikos/src/main/resources/schema.sql
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | |||||||
|  | CREATE TABLE INVENTORY ( | ||||||
|  |     productId VARCHAR PRIMARY KEY, | ||||||
|  |     balance INT | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | CREATE TABLE ORDERS ( | ||||||
|  |     orderId VARCHAR PRIMARY KEY, | ||||||
|  |     productId VARCHAR, | ||||||
|  |     amount INT NOT NULL CHECK (amount <= 5) | ||||||
|  | ); | ||||||
							
								
								
									
										1
									
								
								atomikos/src/main/resources/transactions.properties
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								atomikos/src/main/resources/transactions.properties
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | com.atomikos.icatch.file=logs | ||||||
| @ -0,0 +1,118 @@ | |||||||
|  | package com.baeldung.atomikos.direct; | ||||||
|  | 
 | ||||||
|  | import static org.junit.jupiter.api.Assertions.assertEquals; | ||||||
|  | 
 | ||||||
|  | import java.sql.Connection; | ||||||
|  | import java.sql.ResultSet; | ||||||
|  | import java.sql.SQLException; | ||||||
|  | import java.sql.Statement; | ||||||
|  | import java.util.Properties; | ||||||
|  | import java.util.UUID; | ||||||
|  | 
 | ||||||
|  | import javax.sql.DataSource; | ||||||
|  | 
 | ||||||
|  | import org.junit.BeforeClass; | ||||||
|  | import org.junit.Ignore; | ||||||
|  | import org.junit.Test; | ||||||
|  | 
 | ||||||
|  | import com.atomikos.icatch.jta.UserTransactionImp; | ||||||
|  | import com.atomikos.jdbc.AtomikosDataSourceBean; | ||||||
|  | 
 | ||||||
|  | public class ApplicationUnitTest { | ||||||
|  | 
 | ||||||
|  |     private static DataSource inventoryDataSource; | ||||||
|  |     private static DataSource orderDataSource; | ||||||
|  | 
 | ||||||
|  |     private static String productId = UUID.randomUUID() | ||||||
|  |         .toString(); | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @Ignore | ||||||
|  |     public void testPlaceOrderSuccess() throws Exception { | ||||||
|  |         int amount = 1; | ||||||
|  |         long initialBalance = getBalance(inventoryDataSource, productId); | ||||||
|  |         Application application = new Application(inventoryDataSource, orderDataSource); | ||||||
|  |         application.placeOrder(productId, amount); | ||||||
|  |         long finalBalance = getBalance(inventoryDataSource, productId); | ||||||
|  |         assertEquals(initialBalance - amount, finalBalance); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @Ignore | ||||||
|  |     public void testPlaceOrderFailure() throws Exception { | ||||||
|  |         int amount = 10; | ||||||
|  |         long initialBalance = getBalance(inventoryDataSource, productId); | ||||||
|  |         Application application = new Application(inventoryDataSource, orderDataSource); | ||||||
|  |         application.placeOrder(productId, amount); | ||||||
|  |         long finalBalance = getBalance(inventoryDataSource, productId); | ||||||
|  |         assertEquals(initialBalance, finalBalance); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @BeforeClass | ||||||
|  |     public static void setUp() throws SQLException { | ||||||
|  | 
 | ||||||
|  |         inventoryDataSource = getDataSource("db1"); | ||||||
|  |         orderDataSource = getDataSource("db2"); | ||||||
|  |         Connection inventoryConnection = inventoryDataSource.getConnection(); | ||||||
|  |         Connection orderConnection = orderDataSource.getConnection(); | ||||||
|  |         String createInventoryTable = "create table Inventory ( " + " productId VARCHAR ( 100 ) PRIMARY KEY, balance INT )"; | ||||||
|  |         String createInventoryRow = "insert into Inventory values ( '" + productId + "', 10000 )"; | ||||||
|  |         Statement s1 = inventoryConnection.createStatement(); | ||||||
|  |         try { | ||||||
|  |             s1.executeUpdate(createInventoryTable); | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             System.out.println("Inventory table exists"); | ||||||
|  |         } | ||||||
|  |         try { | ||||||
|  |             s1.executeUpdate(createInventoryRow); | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             System.out.println("Product row exists"); | ||||||
|  |         } | ||||||
|  |         s1.close(); | ||||||
|  |         String createOrderTable = "create table Orders ( orderId VARCHAR ( 100 ) PRIMARY KEY, productId VARCHAR ( 100 ), amount INT NOT NULL CHECK (amount <= 5) )"; | ||||||
|  |         Statement s2 = orderConnection.createStatement(); | ||||||
|  |         try { | ||||||
|  |             s2.executeUpdate(createOrderTable); | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             System.out.println("Orders table exists"); | ||||||
|  |         } | ||||||
|  |         s2.close(); | ||||||
|  |         inventoryConnection.close(); | ||||||
|  |         orderConnection.close(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private static DataSource getDataSource(String db) { | ||||||
|  | 
 | ||||||
|  |         DataSource ds; | ||||||
|  |         AtomikosDataSourceBean ads = new AtomikosDataSourceBean(); | ||||||
|  |         ads.setXaDataSourceClassName("org.apache.derby.jdbc.EmbeddedXADataSource"); | ||||||
|  |         Properties properties = new Properties(); | ||||||
|  |         properties.put("databaseName", db); | ||||||
|  |         properties.put("createDatabase", "create"); | ||||||
|  |         ads.setXaProperties(properties); | ||||||
|  |         ads.setUniqueResourceName(db); | ||||||
|  |         ads.setPoolSize(10); // optional | ||||||
|  |         ads.setBorrowConnectionTimeout(10); // optional | ||||||
|  |         ds = ads; | ||||||
|  |         return ds; | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private static long getBalance(DataSource inventoryDataSource, String productId) throws Exception { | ||||||
|  | 
 | ||||||
|  |         UserTransactionImp utx = new UserTransactionImp(); | ||||||
|  |         utx.begin(); | ||||||
|  |         Connection inventoryConnection = inventoryDataSource.getConnection(); | ||||||
|  |         Statement s1 = inventoryConnection.createStatement(); | ||||||
|  |         String q1 = "select balance from Inventory where productId='" + productId + "'"; | ||||||
|  |         ResultSet rs1 = s1.executeQuery(q1); | ||||||
|  |         if (rs1 == null || !rs1.next()) | ||||||
|  |             throw new Exception("Product not found: " + productId); | ||||||
|  |         long balance = rs1.getLong(1); | ||||||
|  |         inventoryConnection.close(); | ||||||
|  |         utx.commit(); | ||||||
|  |         return balance; | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,108 @@ | |||||||
|  | package com.baeldung.atomikos.spring; | ||||||
|  | 
 | ||||||
|  | import static org.junit.jupiter.api.Assertions.assertEquals; | ||||||
|  | 
 | ||||||
|  | import java.sql.Connection; | ||||||
|  | import java.sql.ResultSet; | ||||||
|  | import java.sql.SQLException; | ||||||
|  | import java.sql.Statement; | ||||||
|  | import java.util.UUID; | ||||||
|  | 
 | ||||||
|  | import javax.sql.DataSource; | ||||||
|  | 
 | ||||||
|  | import org.junit.Before; | ||||||
|  | import org.junit.Ignore; | ||||||
|  | import org.junit.Test; | ||||||
|  | import org.junit.runner.RunWith; | ||||||
|  | import org.springframework.beans.factory.annotation.Autowired; | ||||||
|  | import org.springframework.test.context.ContextConfiguration; | ||||||
|  | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; | ||||||
|  | 
 | ||||||
|  | import com.baeldung.atomikos.spring.config.Config; | ||||||
|  | 
 | ||||||
|  | @RunWith(SpringJUnit4ClassRunner.class) | ||||||
|  | @ContextConfiguration(classes = { Config.class }) | ||||||
|  | public class ApplicationUnitTest { | ||||||
|  | 
 | ||||||
|  |     private static String productId = UUID.randomUUID() | ||||||
|  |         .toString(); | ||||||
|  | 
 | ||||||
|  |     @Autowired | ||||||
|  |     Application application; | ||||||
|  | 
 | ||||||
|  |     @Autowired | ||||||
|  |     DataSource inventoryDataSource; | ||||||
|  | 
 | ||||||
|  |     @Autowired | ||||||
|  |     DataSource orderDataSource; | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @Ignore | ||||||
|  |     public void testPlaceOrderSuccess() throws Exception { | ||||||
|  |         int amount = 1; | ||||||
|  |         long initialBalance = getBalance(inventoryDataSource, productId); | ||||||
|  |         application.placeOrder(productId, amount); | ||||||
|  |         long finalBalance = getBalance(inventoryDataSource, productId); | ||||||
|  |         assertEquals(initialBalance - amount, finalBalance); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @Ignore | ||||||
|  |     public void testPlaceOrderFailure() throws Exception { | ||||||
|  |         int amount = 10; | ||||||
|  |         long initialBalance = getBalance(inventoryDataSource, productId); | ||||||
|  |         try { | ||||||
|  |             application.placeOrder(productId, amount); | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             System.out.println(e.getMessage()); | ||||||
|  |         } | ||||||
|  |         long finalBalance = getBalance(inventoryDataSource, productId); | ||||||
|  |         assertEquals(initialBalance, finalBalance); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Before | ||||||
|  |     public void setUp() throws SQLException { | ||||||
|  | 
 | ||||||
|  |         Connection inventoryConnection = inventoryDataSource.getConnection(); | ||||||
|  |         Connection orderConnection = orderDataSource.getConnection(); | ||||||
|  |         String createInventoryTable = "create table Inventory ( " + " productId VARCHAR ( 100 ) PRIMARY KEY, balance INT )"; | ||||||
|  |         String createInventoryRow = "insert into Inventory values ( '" + productId + "', 10000 )"; | ||||||
|  |         Statement s1 = inventoryConnection.createStatement(); | ||||||
|  |         try { | ||||||
|  |             s1.executeUpdate(createInventoryTable); | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             System.out.println("Inventory table exists"); | ||||||
|  |         } | ||||||
|  |         try { | ||||||
|  |             s1.executeUpdate(createInventoryRow); | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             System.out.println("Product row exists"); | ||||||
|  |         } | ||||||
|  |         s1.close(); | ||||||
|  |         String createOrderTable = "create table Orders ( orderId VARCHAR ( 100 ) PRIMARY KEY, productId VARCHAR ( 100 ), amount INT NOT NULL CHECK (amount <= 5) )"; | ||||||
|  |         Statement s2 = orderConnection.createStatement(); | ||||||
|  |         try { | ||||||
|  |             s2.executeUpdate(createOrderTable); | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             System.out.println("Orders table exists"); | ||||||
|  |         } | ||||||
|  |         s2.close(); | ||||||
|  |         inventoryConnection.close(); | ||||||
|  |         orderConnection.close(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private static long getBalance(DataSource inventoryDataSource, String productId) throws Exception { | ||||||
|  | 
 | ||||||
|  |         Connection inventoryConnection = inventoryDataSource.getConnection(); | ||||||
|  |         Statement s1 = inventoryConnection.createStatement(); | ||||||
|  |         String q1 = "select balance from Inventory where productId='" + productId + "'"; | ||||||
|  |         ResultSet rs1 = s1.executeQuery(q1); | ||||||
|  |         if (rs1 == null || !rs1.next()) | ||||||
|  |             throw new Exception("Product not found: " + productId); | ||||||
|  |         long balance = rs1.getLong(1); | ||||||
|  |         inventoryConnection.close(); | ||||||
|  |         return balance; | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,80 @@ | |||||||
|  | package com.baeldung.atomikos.spring.jpa; | ||||||
|  | 
 | ||||||
|  | import static org.junit.jupiter.api.Assertions.assertEquals; | ||||||
|  | 
 | ||||||
|  | import java.sql.SQLException; | ||||||
|  | import java.util.UUID; | ||||||
|  | 
 | ||||||
|  | import org.junit.Before; | ||||||
|  | import org.junit.Ignore; | ||||||
|  | import org.junit.Test; | ||||||
|  | import org.junit.runner.RunWith; | ||||||
|  | import org.springframework.beans.factory.annotation.Autowired; | ||||||
|  | import org.springframework.test.context.ContextConfiguration; | ||||||
|  | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; | ||||||
|  | 
 | ||||||
|  | import com.baeldung.atomikos.spring.jpa.config.Config; | ||||||
|  | import com.baeldung.atomikos.spring.jpa.inventory.Inventory; | ||||||
|  | import com.baeldung.atomikos.spring.jpa.inventory.InventoryConfig; | ||||||
|  | import com.baeldung.atomikos.spring.jpa.inventory.InventoryRepository; | ||||||
|  | import com.baeldung.atomikos.spring.jpa.order.OrderConfig; | ||||||
|  | import com.baeldung.atomikos.spring.jpa.order.OrderRepository; | ||||||
|  | 
 | ||||||
|  | @RunWith(SpringJUnit4ClassRunner.class) | ||||||
|  | @ContextConfiguration(classes = { Config.class, InventoryConfig.class, OrderConfig.class }) | ||||||
|  | public class ApplicationUnitTest { | ||||||
|  | 
 | ||||||
|  |     private static String productId = UUID.randomUUID() | ||||||
|  |         .toString(); | ||||||
|  | 
 | ||||||
|  |     @Autowired | ||||||
|  |     Application application; | ||||||
|  | 
 | ||||||
|  |     @Autowired | ||||||
|  |     InventoryRepository inventoryRepository; | ||||||
|  | 
 | ||||||
|  |     @Autowired | ||||||
|  |     OrderRepository orderRepository; | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @Ignore | ||||||
|  |     public void testPlaceOrderSuccess() throws Exception { | ||||||
|  |         int amount = 1; | ||||||
|  |         long initialBalance = getBalance(inventoryRepository, productId); | ||||||
|  |         application.placeOrder(productId, amount); | ||||||
|  |         long finalBalance = getBalance(inventoryRepository, productId); | ||||||
|  |         assertEquals(initialBalance - amount, finalBalance); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     @Ignore | ||||||
|  |     public void testPlaceOrderFailure() throws Exception { | ||||||
|  |         int amount = 10; | ||||||
|  |         long initialBalance = getBalance(inventoryRepository, productId); | ||||||
|  |         try { | ||||||
|  |             application.placeOrder(productId, amount); | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             System.out.println(e.getMessage()); | ||||||
|  |         } | ||||||
|  |         long finalBalance = getBalance(inventoryRepository, productId); | ||||||
|  |         assertEquals(initialBalance, finalBalance); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Before | ||||||
|  |     public void setUp() throws SQLException { | ||||||
|  | 
 | ||||||
|  |         Inventory inventory = new Inventory(); | ||||||
|  |         inventory.setProductId(productId); | ||||||
|  |         inventory.setBalance(new Long(10000)); | ||||||
|  |         inventoryRepository.save(inventory); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private static long getBalance(InventoryRepository inventoryRepository, String productId) throws Exception { | ||||||
|  | 
 | ||||||
|  |         return inventoryRepository.findOne(productId) | ||||||
|  |             .getBalance(); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										13
									
								
								atomikos/src/test/resources/logback.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								atomikos/src/test/resources/logback.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <configuration> | ||||||
|  |     <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> | ||||||
|  |         <encoder> | ||||||
|  |             <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n | ||||||
|  |             </pattern> | ||||||
|  |         </encoder> | ||||||
|  |     </appender> | ||||||
|  | 
 | ||||||
|  |     <root level="INFO"> | ||||||
|  |         <appender-ref ref="STDOUT" /> | ||||||
|  |     </root> | ||||||
|  | </configuration> | ||||||
							
								
								
									
										1
									
								
								atomikos/src/test/resources/transactions.properties
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								atomikos/src/test/resources/transactions.properties
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | com.atomikos.icatch.file=logs | ||||||
| @ -0,0 +1,110 @@ | |||||||
|  | package com.baeldung.stringtoint | ||||||
|  | 
 | ||||||
|  | import org.junit.Test | ||||||
|  | 
 | ||||||
|  | import java.text.DecimalFormat | ||||||
|  | 
 | ||||||
|  | import static org.junit.Assert.assertEquals | ||||||
|  | import static org.junit.Assert.assertNull | ||||||
|  | 
 | ||||||
|  | class ConvertStringToInt { | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenString_whenUsingAsInteger_thenConvertToInteger() { | ||||||
|  |         def stringNum = "123" | ||||||
|  |         def invalidString = "123a" | ||||||
|  |         Integer expectedInteger = 123 | ||||||
|  |         Integer integerNum = stringNum as Integer | ||||||
|  |         def intNum = invalidString?.isInteger() ? invalidString as Integer : null | ||||||
|  | 
 | ||||||
|  |         assertNull(null, intNum) | ||||||
|  |         assertEquals(integerNum, expectedInteger) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenString_whenUsingAsInt_thenConvertToInt() { | ||||||
|  |         def stringNum = "123" | ||||||
|  |         int expectedInt = 123 | ||||||
|  |         int intNum = stringNum as int | ||||||
|  | 
 | ||||||
|  |         assertEquals(intNum, expectedInt) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenString_whenUsingToInteger_thenConvertToInteger() { | ||||||
|  |         def stringNum = "123" | ||||||
|  |         int expectedInt = 123 | ||||||
|  |         int intNum = stringNum.toInteger() | ||||||
|  | 
 | ||||||
|  |         assertEquals(intNum, expectedInt) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenString_whenUsingParseInt_thenConvertToInteger() { | ||||||
|  |         def stringNum = "123" | ||||||
|  |         int expectedInt = 123 | ||||||
|  |         int intNum = Integer.parseInt(stringNum) | ||||||
|  | 
 | ||||||
|  |         assertEquals(intNum, expectedInt) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenString_whenUsingValueOf_thenConvertToInteger() { | ||||||
|  |         def stringNum = "123" | ||||||
|  |         int expectedInt = 123 | ||||||
|  |         int intNum = Integer.valueOf(stringNum) | ||||||
|  | 
 | ||||||
|  |         assertEquals(intNum, expectedInt) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenString_whenUsingIntValue_thenConvertToInteger() { | ||||||
|  |         def stringNum = "123" | ||||||
|  |         int expectedInt = 123 | ||||||
|  |         int intNum = new Integer(stringNum).intValue() | ||||||
|  | 
 | ||||||
|  |         assertEquals(intNum, expectedInt) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenString_whenUsingNewInteger_thenConvertToInteger() { | ||||||
|  |         def stringNum = "123" | ||||||
|  |         int expectedInt = 123 | ||||||
|  |         int intNum = new Integer(stringNum) | ||||||
|  | 
 | ||||||
|  |         assertEquals(intNum, expectedInt) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenString_whenUsingDecimalFormat_thenConvertToInteger() { | ||||||
|  |         def stringNum = "123" | ||||||
|  |         int expectedInt = 123 | ||||||
|  |         DecimalFormat decimalFormat = new DecimalFormat("#") | ||||||
|  |         int intNum = decimalFormat.parse(stringNum).intValue() | ||||||
|  | 
 | ||||||
|  |         assertEquals(intNum, expectedInt) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test(expected = NumberFormatException.class) | ||||||
|  |     void givenInvalidString_whenUsingAs_thenThrowNumberFormatException() { | ||||||
|  |         def invalidString = "123a" | ||||||
|  |         invalidString as Integer | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test(expected = NullPointerException.class) | ||||||
|  |     void givenNullString_whenUsingToInteger_thenThrowNullPointerException() { | ||||||
|  |         def invalidString = null | ||||||
|  |         invalidString.toInteger() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenString_whenUsingIsInteger_thenCheckIfCorrectValue() { | ||||||
|  |         def invalidString = "123a" | ||||||
|  |         def validString = "123" | ||||||
|  |         def invalidNum = invalidString?.isInteger() ? invalidString as Integer : false | ||||||
|  |         def correctNum = validString?.isInteger() ? validString as Integer : false | ||||||
|  | 
 | ||||||
|  |         assertEquals(false, invalidNum) | ||||||
|  |         assertEquals(123, correctNum) | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -7,3 +7,4 @@ This module contains articles about Java 14. | |||||||
| - [Guide to the @Serial Annotation in Java 14](https://www.baeldung.com/java-14-serial-annotation) | - [Guide to the @Serial Annotation in Java 14](https://www.baeldung.com/java-14-serial-annotation) | ||||||
| - [Java Text Blocks](https://www.baeldung.com/java-text-blocks) | - [Java Text Blocks](https://www.baeldung.com/java-text-blocks) | ||||||
| - [Pattern Matching for instanceof in Java 14](https://www.baeldung.com/java-pattern-matching-instanceof) | - [Pattern Matching for instanceof in Java 14](https://www.baeldung.com/java-pattern-matching-instanceof) | ||||||
|  | - [Helpful NullPointerExceptions in Java 14](https://www.baeldung.com/java-14-nullpointerexception) | ||||||
|  | |||||||
| @ -4,7 +4,6 @@ This module contains articles about Map data structures in Java. | |||||||
| 
 | 
 | ||||||
| ### Relevant Articles:  | ### Relevant Articles:  | ||||||
| - [Guide to the Guava BiMap](https://www.baeldung.com/guava-bimap) | - [Guide to the Guava BiMap](https://www.baeldung.com/guava-bimap) | ||||||
| - [A Guide to Java HashMap](https://www.baeldung.com/java-hashmap) |  | ||||||
| - [A Guide to LinkedHashMap in Java](https://www.baeldung.com/java-linked-hashmap) | - [A Guide to LinkedHashMap in Java](https://www.baeldung.com/java-linked-hashmap) | ||||||
| - [A Guide to TreeMap in Java](https://www.baeldung.com/java-treemap) | - [A Guide to TreeMap in Java](https://www.baeldung.com/java-treemap) | ||||||
| - [How to Store Duplicate Keys in a Map in Java?](https://www.baeldung.com/java-map-duplicate-keys) | - [How to Store Duplicate Keys in a Map in Java?](https://www.baeldung.com/java-map-duplicate-keys) | ||||||
|  | |||||||
| @ -10,4 +10,5 @@ This module contains articles about advanced topics about multithreading with co | |||||||
| - [Guide to RejectedExecutionHandler](https://www.baeldung.com/java-rejectedexecutionhandler) | - [Guide to RejectedExecutionHandler](https://www.baeldung.com/java-rejectedexecutionhandler) | ||||||
| - [Guide to Work Stealing in Java](https://www.baeldung.com/java-work-stealing) | - [Guide to Work Stealing in Java](https://www.baeldung.com/java-work-stealing) | ||||||
| - [Asynchronous Programming in Java](https://www.baeldung.com/java-asynchronous-programming) | - [Asynchronous Programming in Java](https://www.baeldung.com/java-asynchronous-programming) | ||||||
|  | - [Java Thread Deadlock and Livelock](https://www.baeldung.com/java-deadlock-livelock) | ||||||
| - [[<-- previous]](/core-java-modules/core-java-concurrency-advanced-2) | - [[<-- previous]](/core-java-modules/core-java-concurrency-advanced-2) | ||||||
|  | |||||||
| @ -8,4 +8,5 @@ This module contains articles about basic Java concurrency | |||||||
| - [Difference Between Wait and Sleep in Java](https://www.baeldung.com/java-wait-and-sleep) | - [Difference Between Wait and Sleep in Java](https://www.baeldung.com/java-wait-and-sleep) | ||||||
| - [Guide to the Synchronized Keyword in Java](https://www.baeldung.com/java-synchronized) | - [Guide to the Synchronized Keyword in Java](https://www.baeldung.com/java-synchronized) | ||||||
| - [Life Cycle of a Thread in Java](https://www.baeldung.com/java-thread-lifecycle) | - [Life Cycle of a Thread in Java](https://www.baeldung.com/java-thread-lifecycle) | ||||||
| - [[<-- Prev]](/core-java-modules/core-java-concurrency-basic) | - [Guide to AtomicMarkableReference](https://www.baeldung.com/java-atomicmarkablereference) | ||||||
|  | - [[<-- Prev]](/core-java-modules/core-java-concurrency-basic) | ||||||
|  | |||||||
| @ -1,26 +0,0 @@ | |||||||
| *.class |  | ||||||
| 
 |  | ||||||
| 0.* |  | ||||||
| 
 |  | ||||||
| #folders# |  | ||||||
| /target |  | ||||||
| /neoDb* |  | ||||||
| /data |  | ||||||
| /src/main/webapp/WEB-INF/classes |  | ||||||
| */META-INF/* |  | ||||||
| .resourceCache |  | ||||||
| 
 |  | ||||||
| # Packaged files # |  | ||||||
| *.jar |  | ||||||
| *.war |  | ||||||
| *.ear |  | ||||||
| 
 |  | ||||||
| # Files generated by integration tests |  | ||||||
| *.txt |  | ||||||
| backup-pom.xml |  | ||||||
| /bin/ |  | ||||||
| /temp |  | ||||||
| 
 |  | ||||||
| #IntelliJ specific |  | ||||||
| .idea/ |  | ||||||
| *.iml |  | ||||||
| @ -1,93 +1,93 @@ | |||||||
| <?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||||||
| <project xmlns="http://maven.apache.org/POM/4.0.0" | <project xmlns="http://maven.apache.org/POM/4.0.0" | ||||||
| 	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||
| 	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||||||
| 	<modelVersion>4.0.0</modelVersion> |     <modelVersion>4.0.0</modelVersion> | ||||||
| 	<artifactId>core-java-concurrency-testing</artifactId> |     <artifactId>core-java-concurrency-testing</artifactId> | ||||||
| 	<version>0.1.0-SNAPSHOT</version> |     <version>0.1.0-SNAPSHOT</version> | ||||||
| 	<name>core-java-concurrency-testing</name> |     <name>core-java-concurrency-testing</name> | ||||||
| 	<packaging>jar</packaging> |     <packaging>jar</packaging> | ||||||
| 
 | 
 | ||||||
| 	<parent> |     <parent> | ||||||
| 		<groupId>com.baeldung</groupId> |         <groupId>com.baeldung</groupId> | ||||||
| 		<artifactId>parent-java</artifactId> |         <artifactId>parent-java</artifactId> | ||||||
| 		<version>0.0.1-SNAPSHOT</version> |         <version>0.0.1-SNAPSHOT</version> | ||||||
| 		<relativePath>../../parent-java</relativePath> |         <relativePath>../../parent-java</relativePath> | ||||||
| 	</parent> |     </parent> | ||||||
| 	 | 	 | ||||||
| 	<dependencies> |     <dependencies> | ||||||
| 		<dependency> |         <dependency> | ||||||
| 			<groupId>junit</groupId> |             <groupId>junit</groupId> | ||||||
| 			<artifactId>junit</artifactId> |             <artifactId>junit</artifactId> | ||||||
| 			<version>4.13</version> |             <version>4.13</version> | ||||||
| 			<scope>test</scope> |             <scope>test</scope> | ||||||
| 		</dependency> |         </dependency> | ||||||
| 		<dependency> |         <dependency> | ||||||
| 			<groupId>com.googlecode.thread-weaver</groupId> |             <groupId>com.googlecode.thread-weaver</groupId> | ||||||
| 			<artifactId>threadweaver</artifactId> |             <artifactId>threadweaver</artifactId> | ||||||
| 			<version>0.2</version> |             <version>0.2</version> | ||||||
| 			<scope>test</scope> |             <scope>test</scope> | ||||||
| 		</dependency> |         </dependency> | ||||||
| 		<dependency> |         <dependency> | ||||||
| 			<groupId>com.google.code.tempus-fugit</groupId> |             <groupId>com.google.code.tempus-fugit</groupId> | ||||||
| 			<artifactId>tempus-fugit</artifactId> |             <artifactId>tempus-fugit</artifactId> | ||||||
| 			<version>1.1</version> |             <version>1.1</version> | ||||||
| 			<scope>test</scope> |             <scope>test</scope> | ||||||
| 		</dependency> |         </dependency> | ||||||
| 		<dependency> |         <dependency> | ||||||
| 			<groupId>com.googlecode.multithreadedtc</groupId> |             <groupId>com.googlecode.multithreadedtc</groupId> | ||||||
| 			<artifactId>multithreadedtc</artifactId> |             <artifactId>multithreadedtc</artifactId> | ||||||
| 			<version>1.01</version> |             <version>1.01</version> | ||||||
| 			<scope>test</scope> |             <scope>test</scope> | ||||||
| 		</dependency> |         </dependency> | ||||||
| 		<dependency> |         <dependency> | ||||||
| 			<groupId>org.openjdk.jcstress</groupId> |             <groupId>org.openjdk.jcstress</groupId> | ||||||
| 			<artifactId>jcstress-core</artifactId> |             <artifactId>jcstress-core</artifactId> | ||||||
| 			<version>0.5</version> |             <version>0.5</version> | ||||||
| 		</dependency> |         </dependency> | ||||||
| 	</dependencies> |     </dependencies> | ||||||
| 
 | 
 | ||||||
| 	<build> |     <build> | ||||||
| 		<plugins> |         <plugins> | ||||||
| 			<plugin> |             <plugin> | ||||||
| 				<groupId>org.apache.maven.plugins</groupId> |                 <groupId>org.apache.maven.plugins</groupId> | ||||||
| 				<artifactId>maven-compiler-plugin</artifactId> |                 <artifactId>maven-compiler-plugin</artifactId> | ||||||
| 				<version>3.1</version> |                 <version>3.1</version> | ||||||
| 				<configuration> |                 <configuration> | ||||||
| 					<compilerVersion>${javac.target}</compilerVersion> |                     <compilerVersion>${javac.target}</compilerVersion> | ||||||
| 					<source>${javac.target}</source> |                     <source>${javac.target}</source> | ||||||
| 					<target>${javac.target}</target> |                     <target>${javac.target}</target> | ||||||
| 				</configuration> |                 </configuration> | ||||||
| 			</plugin> |             </plugin> | ||||||
| 
 | 
 | ||||||
| 			<plugin> |             <plugin> | ||||||
| 				<groupId>org.apache.maven.plugins</groupId> |                 <groupId>org.apache.maven.plugins</groupId> | ||||||
| 				<artifactId>maven-shade-plugin</artifactId> |                 <artifactId>maven-shade-plugin</artifactId> | ||||||
| 				<version>2.2</version> |                 <version>2.2</version> | ||||||
| 				<executions> |                 <executions> | ||||||
| 					<execution> |                     <execution> | ||||||
| 						<id>main</id> |                         <id>main</id> | ||||||
| 						<phase>package</phase> |                         <phase>package</phase> | ||||||
| 						<goals> |                         <goals> | ||||||
| 							<goal>shade</goal> |                             <goal>shade</goal> | ||||||
| 						</goals> |                         </goals> | ||||||
| 						<configuration> |                         <configuration> | ||||||
| 							<finalName>jcstress</finalName> |                             <finalName>jcstress</finalName> | ||||||
| 							<transformers> |                             <transformers> | ||||||
| 								<transformer |                                 <transformer | ||||||
| 									implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> |                                     implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> | ||||||
| 									<mainClass>org.openjdk.jcstress.Main</mainClass> |                                     <mainClass>org.openjdk.jcstress.Main</mainClass> | ||||||
| 								</transformer> |                                 </transformer> | ||||||
| 								<transformer |                                 <transformer | ||||||
| 									implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> |                                     implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> | ||||||
| 									<resource>META-INF/TestList</resource> |                                     <resource>META-INF/TestList</resource> | ||||||
| 								</transformer> |                                 </transformer> | ||||||
| 							</transformers> |                             </transformers> | ||||||
| 						</configuration> |                         </configuration> | ||||||
| 					</execution> |                     </execution> | ||||||
| 				</executions> |                 </executions> | ||||||
| 			</plugin> |             </plugin> | ||||||
| 		</plugins> |         </plugins> | ||||||
| 	</build> |     </build> | ||||||
| 
 | 
 | ||||||
| </project> | </project> | ||||||
|  | |||||||
| @ -7,4 +7,5 @@ This module contains articles about date operations in Java. | |||||||
| - [Checking If Two Java Dates Are on the Same Day](https://www.baeldung.com/java-check-two-dates-on-same-day) | - [Checking If Two Java Dates Are on the Same Day](https://www.baeldung.com/java-check-two-dates-on-same-day) | ||||||
| - [Converting Java Date to OffsetDateTime](https://www.baeldung.com/java-convert-date-to-offsetdatetime) | - [Converting Java Date to OffsetDateTime](https://www.baeldung.com/java-convert-date-to-offsetdatetime) | ||||||
| - [How to Set the JVM Time Zone](https://www.baeldung.com/java-jvm-time-zone) | - [How to Set the JVM Time Zone](https://www.baeldung.com/java-jvm-time-zone) | ||||||
|  | - [How to determine day of week by passing specific date in Java?](https://www.baeldung.com/java-get-day-of-week) | ||||||
| - [[<-- Prev]](/core-java-modules/core-java-date-operations-1) | - [[<-- Prev]](/core-java-modules/core-java-date-operations-1) | ||||||
|  | |||||||
| @ -10,4 +10,5 @@ This module contains articles about core features in the Java language | |||||||
| - [How to Return Multiple Values From a Java Method](https://www.baeldung.com/java-method-return-multiple-values) | - [How to Return Multiple Values From a Java Method](https://www.baeldung.com/java-method-return-multiple-values) | ||||||
| - [Guide to the Java finally Keyword](https://www.baeldung.com/java-finally-keyword) | - [Guide to the Java finally Keyword](https://www.baeldung.com/java-finally-keyword) | ||||||
| - [The Java Headless Mode](https://www.baeldung.com/java-headless-mode) | - [The Java Headless Mode](https://www.baeldung.com/java-headless-mode) | ||||||
|  | - [Comparing Long Values in Java](https://www.baeldung.com/java-compare-long-values) | ||||||
| - [[<-- Prev]](/core-java-modules/core-java-lang) | - [[<-- Prev]](/core-java-modules/core-java-lang) | ||||||
|  | |||||||
| @ -0,0 +1,21 @@ | |||||||
|  | package com.baeldung.orelseoptional; | ||||||
|  | 
 | ||||||
|  | import java.util.Optional; | ||||||
|  | 
 | ||||||
|  | public class ItemsProvider { | ||||||
|  | 
 | ||||||
|  |     Optional<String> getEmptyItem() { | ||||||
|  |         System.out.println("Returning an empty item"); | ||||||
|  |         return Optional.empty(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Optional<String> getNail() { | ||||||
|  |         System.out.println("Returning a nail"); | ||||||
|  |         return Optional.of("nail"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Optional<String> getHammer() { | ||||||
|  |         System.out.println("Returning a hammer"); | ||||||
|  |         return Optional.of("hammer"); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -1,10 +1,10 @@ | |||||||
| package com.baeldung.orelseoptional; | package com.baeldung.orelseoptional; | ||||||
| 
 | 
 | ||||||
| import static org.junit.Assert.assertEquals; | import org.junit.Test; | ||||||
| 
 | 
 | ||||||
| import java.util.Optional; | import java.util.Optional; | ||||||
| 
 | 
 | ||||||
| import org.junit.Test; | import static org.junit.Assert.assertEquals; | ||||||
| 
 | 
 | ||||||
| public class OrElseOptionalUnitTest { | public class OrElseOptionalUnitTest { | ||||||
| 
 | 
 | ||||||
| @ -25,6 +25,28 @@ public class OrElseOptionalUnitTest { | |||||||
|         assertEquals(fallbackOptionalString, OptionalUtils.or(optionalString, fallbackOptionalString)); |         assertEquals(fallbackOptionalString, OptionalUtils.or(optionalString, fallbackOptionalString)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenTwoOptionalMethods_whenFirstEmpty_thenSecondEvaluated() { | ||||||
|  |         ItemsProvider itemsProvider = new ItemsProvider(); | ||||||
|  | 
 | ||||||
|  |         Optional<String> item = itemsProvider.getEmptyItem() | ||||||
|  |                 .map(Optional::of) | ||||||
|  |                 .orElseGet(itemsProvider::getNail); | ||||||
|  | 
 | ||||||
|  |         assertEquals(Optional.of("nail"), item); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenTwoOptionalMethods_whenFirstNonEmpty_thenSecondNotEvaluated() { | ||||||
|  |         ItemsProvider itemsProvider = new ItemsProvider(); | ||||||
|  | 
 | ||||||
|  |         Optional<String> item = itemsProvider.getNail() | ||||||
|  |                 .map(Optional::of) | ||||||
|  |                 .orElseGet(itemsProvider::getHammer); | ||||||
|  | 
 | ||||||
|  |         assertEquals(Optional.of("nail"), item); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| //    Uncomment code when code base is compatible with Java 9 | //    Uncomment code when code base is compatible with Java 9 | ||||||
| //    @Test | //    @Test | ||||||
| //    public void givenOptional_whenEmptyValue_thenCustomMessage() { | //    public void givenOptional_whenEmptyValue_thenCustomMessage() { | ||||||
|  | |||||||
| @ -9,3 +9,4 @@ | |||||||
| - [Pre-compile Regex Patterns Into Pattern Objects](https://www.baeldung.com/java-regex-pre-compile) | - [Pre-compile Regex Patterns Into Pattern Objects](https://www.baeldung.com/java-regex-pre-compile) | ||||||
| - [Difference Between Java Matcher find() and matches()](https://www.baeldung.com/java-matcher-find-vs-matches) | - [Difference Between Java Matcher find() and matches()](https://www.baeldung.com/java-matcher-find-vs-matches) | ||||||
| - [How to Use Regular Expressions to Replace Tokens in Strings](https://www.baeldung.com/java-regex-token-replacement) | - [How to Use Regular Expressions to Replace Tokens in Strings](https://www.baeldung.com/java-regex-token-replacement) | ||||||
|  | - [Regular Expressions \s and \s+ in Java](https://www.baeldung.com/java-regex-s-splus) | ||||||
|  | |||||||
| @ -8,4 +8,5 @@ This module contains articles about core Java Security | |||||||
| - [MD5 Hashing in Java](http://www.baeldung.com/java-md5) | - [MD5 Hashing in Java](http://www.baeldung.com/java-md5) | ||||||
| - [Hashing a Password in Java](https://www.baeldung.com/java-password-hashing) | - [Hashing a Password in Java](https://www.baeldung.com/java-password-hashing) | ||||||
| - [SHA-256 and SHA3-256 Hashing in Java](https://www.baeldung.com/sha-256-hashing-java) | - [SHA-256 and SHA3-256 Hashing in Java](https://www.baeldung.com/sha-256-hashing-java) | ||||||
|  | - [Checksums in Java](https://www.baeldung.com/java-checksums) | ||||||
| - More articles: [[<-- prev]](/core-java-modules/core-java-security) | - More articles: [[<-- prev]](/core-java-modules/core-java-security) | ||||||
|  | |||||||
| @ -9,4 +9,5 @@ This module contains articles about the Stream API in Java. | |||||||
| - [Guide to Java 8’s Collectors](https://www.baeldung.com/java-8-collectors) | - [Guide to Java 8’s Collectors](https://www.baeldung.com/java-8-collectors) | ||||||
| - [Primitive Type Streams in Java 8](https://www.baeldung.com/java-8-primitive-streams) | - [Primitive Type Streams in Java 8](https://www.baeldung.com/java-8-primitive-streams) | ||||||
| - [Debugging Java 8 Streams with IntelliJ](https://www.baeldung.com/intellij-debugging-java-streams) | - [Debugging Java 8 Streams with IntelliJ](https://www.baeldung.com/intellij-debugging-java-streams) | ||||||
|  | - [Add BigDecimals using the Stream API](https://www.baeldung.com/java-stream-add-bigdecimals) | ||||||
| - More articles: [[<-- prev>]](/../core-java-streams-2) | - More articles: [[<-- prev>]](/../core-java-streams-2) | ||||||
|  | |||||||
| @ -11,4 +11,5 @@ This module contains articles about string operations. | |||||||
| - [Case-Insensitive String Matching in Java](https://www.baeldung.com/java-case-insensitive-string-matching) | - [Case-Insensitive String Matching in Java](https://www.baeldung.com/java-case-insensitive-string-matching) | ||||||
| - [L-Trim and R-Trim in Java](https://www.baeldung.com/l-trim-and-r-trim-in-java) | - [L-Trim and R-Trim in Java](https://www.baeldung.com/l-trim-and-r-trim-in-java) | ||||||
| - [L-Trim and R-Trim Alternatives in Java](https://www.baeldung.com/java-trim-alternatives) | - [L-Trim and R-Trim Alternatives in Java](https://www.baeldung.com/java-trim-alternatives) | ||||||
|  | - [Java Convert PDF to Base64](https://www.baeldung.com/java-convert-pdf-to-base64) | ||||||
| - More articles: [[<-- prev]](../core-java-string-operations) | - More articles: [[<-- prev]](../core-java-string-operations) | ||||||
|  | |||||||
| @ -12,3 +12,4 @@ This module contains articles about strings in Java. | |||||||
| - [Java String Interview Questions and Answers](https://www.baeldung.com/java-string-interview-questions) | - [Java String Interview Questions and Answers](https://www.baeldung.com/java-string-interview-questions) | ||||||
| - [Java Multi-line String](https://www.baeldung.com/java-multiline-string) | - [Java Multi-line String](https://www.baeldung.com/java-multiline-string) | ||||||
| - [Guide to Java String Pool](https://www.baeldung.com/java-string-pool) | - [Guide to Java String Pool](https://www.baeldung.com/java-string-pool) | ||||||
|  | - [Fixing “constant string too long” Build Error](https://www.baeldung.com/java-constant-string-too-long-error) | ||||||
|  | |||||||
| @ -8,3 +8,4 @@ This module contains articles about core Kotlin collections. | |||||||
| - [Overview of Kotlin Collections API](https://www.baeldung.com/kotlin-collections-api) | - [Overview of Kotlin Collections API](https://www.baeldung.com/kotlin-collections-api) | ||||||
| - [Converting a List to Map in Kotlin](https://www.baeldung.com/kotlin-list-to-map) | - [Converting a List to Map in Kotlin](https://www.baeldung.com/kotlin-list-to-map) | ||||||
| - [Filtering Kotlin Collections](https://www.baeldung.com/kotlin-filter-collection) | - [Filtering Kotlin Collections](https://www.baeldung.com/kotlin-filter-collection) | ||||||
|  | - [Collection Transformations in Kotlin](https://www.baeldung.com/kotlin-collection-transformations) | ||||||
|  | |||||||
| @ -142,7 +142,7 @@ public class BinaryTree { | |||||||
|                 nodes.add(node.left); |                 nodes.add(node.left); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (node.left != null) { |             if (node.right != null) { | ||||||
|                 nodes.add(node.right); |                 nodes.add(node.right); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -9,4 +9,5 @@ This module contains articles about map collections in Guava | |||||||
| - [Guide to Guava Multimap](https://www.baeldung.com/guava-multimap) | - [Guide to Guava Multimap](https://www.baeldung.com/guava-multimap) | ||||||
| - [Guide to Guava RangeMap](https://www.baeldung.com/guava-rangemap) | - [Guide to Guava RangeMap](https://www.baeldung.com/guava-rangemap) | ||||||
| - [Initialize a HashMap in Java](https://www.baeldung.com/java-initialize-hashmap) | - [Initialize a HashMap in Java](https://www.baeldung.com/java-initialize-hashmap) | ||||||
| - [Guide to Guava ClassToInstanceMap](https://www.baeldung.com/guava-class-to-instance-map) | - [Guide to Guava ClassToInstanceMap](https://www.baeldung.com/guava-class-to-instance-map) | ||||||
|  | - [Using Guava’s MapMaker](https://www.baeldung.com/guava-mapmaker) | ||||||
|  | |||||||
| @ -12,4 +12,4 @@ This module contains articles a Google Guava | |||||||
| - [Guide to Mathematical Utilities in Guava](https://www.baeldung.com/guava-math) | - [Guide to Mathematical Utilities in Guava](https://www.baeldung.com/guava-math) | ||||||
| - [Bloom Filter in Java using Guava](https://www.baeldung.com/guava-bloom-filter) | - [Bloom Filter in Java using Guava](https://www.baeldung.com/guava-bloom-filter) | ||||||
| - [Quick Guide to the Guava RateLimiter](https://www.baeldung.com/guava-rate-limiter) | - [Quick Guide to the Guava RateLimiter](https://www.baeldung.com/guava-rate-limiter) | ||||||
| 
 | - [Introduction to Guava Throwables](https://www.baeldung.com/guava-throwables) | ||||||
|  | |||||||
							
								
								
									
										8
									
								
								java-collections-maps-3/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								java-collections-maps-3/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | |||||||
|  | ## Java Collections Cookbooks and Examples | ||||||
|  | 
 | ||||||
|  | This module contains articles about Map data structures in Java. | ||||||
|  | 
 | ||||||
|  | ### Relevant Articles:  | ||||||
|  | 
 | ||||||
|  | - More articles: [[<-- prev>]](/../java-collections-maps) | ||||||
|  | - More articles: [[<-- prev>]](/../java-collections-maps-2) | ||||||
							
								
								
									
										43
									
								
								java-collections-maps-3/pom.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								java-collections-maps-3/pom.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,43 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <project xmlns="http://maven.apache.org/POM/4.0.0" | ||||||
|  |          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||
|  |          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||||||
|  |     <parent> | ||||||
|  |         <groupId>com.baeldung</groupId> | ||||||
|  |         <artifactId>parent-java</artifactId> | ||||||
|  |         <version>0.0.1-SNAPSHOT</version> | ||||||
|  |         <relativePath>../parent-java</relativePath> | ||||||
|  |     </parent> | ||||||
|  | 
 | ||||||
|  |     <modelVersion>4.0.0</modelVersion> | ||||||
|  |     <artifactId>java-collections-maps-3</artifactId> | ||||||
|  |     <version>0.1.0-SNAPSHOT</version> | ||||||
|  |     <name>java-collections-maps-3</name> | ||||||
|  |     <packaging>jar</packaging> | ||||||
|  | 
 | ||||||
|  |     <dependencies> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.springframework</groupId> | ||||||
|  |             <artifactId>spring-core</artifactId> | ||||||
|  |             <version>${spring.version}</version> | ||||||
|  |             <scope>test</scope> | ||||||
|  |         </dependency> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.assertj</groupId> | ||||||
|  |             <artifactId>assertj-core</artifactId> | ||||||
|  |             <version>${assertj.version}</version> | ||||||
|  |             <scope>test</scope> | ||||||
|  |         </dependency> | ||||||
|  |     <dependency> | ||||||
|  |         <groupId>org.apache.commons</groupId> | ||||||
|  |         <artifactId>commons-collections4</artifactId> | ||||||
|  |         <version>${commons-collections4.version}</version> | ||||||
|  |     </dependency> | ||||||
|  |     </dependencies> | ||||||
|  | 
 | ||||||
|  |     <properties> | ||||||
|  |         <commons-collections4.version>4.1</commons-collections4.version> | ||||||
|  |         <assertj.version>3.6.1</assertj.version> | ||||||
|  |         <spring.version>5.2.5.RELEASE</spring.version> | ||||||
|  |     </properties> | ||||||
|  | </project> | ||||||
| @ -0,0 +1,94 @@ | |||||||
|  | package com.baeldung.map.caseinsensitivekeys; | ||||||
|  | 
 | ||||||
|  | import org.apache.commons.collections4.map.CaseInsensitiveMap; | ||||||
|  | import org.junit.Test; | ||||||
|  | import org.springframework.util.LinkedCaseInsensitiveMap; | ||||||
|  | import java.util.Map; | ||||||
|  | import java.util.TreeMap; | ||||||
|  | import static org.junit.Assert.*; | ||||||
|  | 
 | ||||||
|  | public class CaseInsensitiveMapUnitTest { | ||||||
|  |     @Test | ||||||
|  |     public void givenCaseInsensitiveTreeMap_whenTwoEntriesAdded_thenSizeIsOne(){ | ||||||
|  |         Map<String, Integer> treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); | ||||||
|  |         treeMap.put("abc", 1); | ||||||
|  |         treeMap.put("ABC", 2); | ||||||
|  | 
 | ||||||
|  |         assertEquals(1, treeMap.size()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenCommonsCaseInsensitiveMap_whenTwoEntriesAdded_thenSizeIsOne(){ | ||||||
|  |         Map<String, Integer> commonsHashMap = new CaseInsensitiveMap<>(); | ||||||
|  |         commonsHashMap.put("abc", 1); | ||||||
|  |         commonsHashMap.put("ABC", 2); | ||||||
|  | 
 | ||||||
|  |         assertEquals(1, commonsHashMap.size()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenLinkedCaseInsensitiveMap_whenTwoEntriesAdded_thenSizeIsOne(){ | ||||||
|  |         Map<String, Integer> linkedHashMap = new LinkedCaseInsensitiveMap<>(); | ||||||
|  |         linkedHashMap.put("abc", 1); | ||||||
|  |         linkedHashMap.put("ABC", 2); | ||||||
|  | 
 | ||||||
|  |         assertEquals(1, linkedHashMap.size()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenCaseInsensitiveTreeMap_whenSameEntryAdded_thenValueUpdated(){ | ||||||
|  |         Map<String, Integer> treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); | ||||||
|  |         treeMap.put("abc", 1); | ||||||
|  |         treeMap.put("ABC", 2); | ||||||
|  | 
 | ||||||
|  |         assertEquals(2, treeMap.get("aBc").intValue()); | ||||||
|  |         assertEquals(2, treeMap.get("ABc").intValue()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenCommonsCaseInsensitiveMap_whenSameEntryAdded_thenValueUpdated(){ | ||||||
|  |         Map<String, Integer> commonsHashMap = new CaseInsensitiveMap<>(); | ||||||
|  |         commonsHashMap.put("abc", 1); | ||||||
|  |         commonsHashMap.put("ABC", 2); | ||||||
|  | 
 | ||||||
|  |         assertEquals(2, commonsHashMap.get("aBc").intValue()); | ||||||
|  |         assertEquals(2, commonsHashMap.get("ABc").intValue()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenLinkedCaseInsensitiveMap_whenSameEntryAdded_thenValueUpdated(){ | ||||||
|  |         Map<String, Integer> linkedHashMap = new LinkedCaseInsensitiveMap<>(); | ||||||
|  |         linkedHashMap.put("abc", 1); | ||||||
|  |         linkedHashMap.put("ABC", 2); | ||||||
|  | 
 | ||||||
|  |         assertEquals(2, linkedHashMap.get("aBc").intValue()); | ||||||
|  |         assertEquals(2, linkedHashMap.get("ABc").intValue()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenCaseInsensitiveTreeMap_whenEntryRemoved_thenSizeIsZero(){ | ||||||
|  |         Map<String, Integer> treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); | ||||||
|  |         treeMap.put("abc", 3); | ||||||
|  |         treeMap.remove("aBC"); | ||||||
|  | 
 | ||||||
|  |         assertEquals(0, treeMap.size()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenCommonsCaseInsensitiveMap_whenEntryRemoved_thenSizeIsZero(){ | ||||||
|  |         Map<String, Integer> commonsHashMap = new CaseInsensitiveMap<>(); | ||||||
|  |         commonsHashMap.put("abc", 3); | ||||||
|  |         commonsHashMap.remove("aBC"); | ||||||
|  | 
 | ||||||
|  |         assertEquals(0, commonsHashMap.size()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenLinkedCaseInsensitiveMap_whenEntryRemoved_thenSizeIsZero(){ | ||||||
|  |         Map<String, Integer> linkedHashMap = new LinkedCaseInsensitiveMap<>(); | ||||||
|  |         linkedHashMap.put("abc", 3); | ||||||
|  |         linkedHashMap.remove("aBC"); | ||||||
|  | 
 | ||||||
|  |         assertEquals(0, linkedHashMap.size()); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -10,4 +10,5 @@ This module contains articles about numbers in Java. | |||||||
| - [Generating Random Numbers in a Range in Java](https://www.baeldung.com/java-generating-random-numbers-in-range) | - [Generating Random Numbers in a Range in Java](https://www.baeldung.com/java-generating-random-numbers-in-range) | ||||||
| - [Listing Numbers Within a Range in Java](https://www.baeldung.com/java-listing-numbers-within-a-range) | - [Listing Numbers Within a Range in Java](https://www.baeldung.com/java-listing-numbers-within-a-range) | ||||||
| - [Fibonacci Series in Java](https://www.baeldung.com/java-fibonacci) | - [Fibonacci Series in Java](https://www.baeldung.com/java-fibonacci) | ||||||
|  | - [Guide to the Number Class in Java](https://www.baeldung.com/java-number-class) | ||||||
| - More articles: [[<-- prev]](/java-numbers-2) | - More articles: [[<-- prev]](/java-numbers-2) | ||||||
|  | |||||||
| @ -7,7 +7,7 @@ | |||||||
|     <version>0.0.1-SNAPSHOT</version> |     <version>0.0.1-SNAPSHOT</version> | ||||||
|     <packaging>war</packaging> |     <packaging>war</packaging> | ||||||
|     <name>Bookstore</name> |     <name>Bookstore</name> | ||||||
|      | 
 | ||||||
|     <parent> |     <parent> | ||||||
|         <artifactId>jhipster-5</artifactId> |         <artifactId>jhipster-5</artifactId> | ||||||
|         <groupId>com.baeldung.jhipster</groupId> |         <groupId>com.baeldung.jhipster</groupId> | ||||||
| @ -982,7 +982,7 @@ | |||||||
|                                         <pluginExecution> |                                         <pluginExecution> | ||||||
|                                             <pluginExecutionFilter> |                                             <pluginExecutionFilter> | ||||||
|                                                 <groupId>com.github.eirslett</groupId> |                                                 <groupId>com.github.eirslett</groupId> | ||||||
|                                         <artifactId>frontend-maven-plugin</artifactId> |                                                 <artifactId>frontend-maven-plugin</artifactId> | ||||||
|                                                 <versionRange>${frontend-maven-plugin.version}</versionRange> |                                                 <versionRange>${frontend-maven-plugin.version}</versionRange> | ||||||
|                                                 <goals> |                                                 <goals> | ||||||
|                                                     <goal>install-node-and-npm</goal> |                                                     <goal>install-node-and-npm</goal> | ||||||
|  | |||||||
| @ -26,7 +26,7 @@ import static org.assertj.core.api.Assertions.assertThat; | |||||||
|  */ |  */ | ||||||
| @RunWith(SpringRunner.class) | @RunWith(SpringRunner.class) | ||||||
| @SpringBootTest(classes = BookstoreApp.class) | @SpringBootTest(classes = BookstoreApp.class) | ||||||
| public class UserMapperUnitTest { | public class UserMapperIntegrationTest { | ||||||
| 
 | 
 | ||||||
|     private static final String DEFAULT_LOGIN = "johndoe"; |     private static final String DEFAULT_LOGIN = "johndoe"; | ||||||
| 
 | 
 | ||||||
| @ -16,3 +16,4 @@ Remember, for advanced libraries like [Jackson](/jackson) and [JUnit](/testing-m | |||||||
| - [Introduction to Takes](https://www.baeldung.com/java-takes) | - [Introduction to Takes](https://www.baeldung.com/java-takes) | ||||||
| - [Using NullAway to Avoid NullPointerExceptions](https://www.baeldung.com/java-nullaway) | - [Using NullAway to Avoid NullPointerExceptions](https://www.baeldung.com/java-nullaway) | ||||||
| - [Introduction to Alibaba Arthas](https://www.baeldung.com/java-alibaba-arthas-intro) | - [Introduction to Alibaba Arthas](https://www.baeldung.com/java-alibaba-arthas-intro) | ||||||
|  | - [Quick Guide to Spring Cloud Circuit Breaker](https://www.baeldung.com/spring-cloud-circuit-breaker) | ||||||
|  | |||||||
							
								
								
									
										3
									
								
								libraries-concurrency/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								libraries-concurrency/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | ### Relevant Articles: | ||||||
|  | 
 | ||||||
|  | - [Intro to Coroutines with Quasar](https://www.baeldung.com/java-quasar-coroutines) | ||||||
| @ -11,3 +11,4 @@ This module contains articles about test libraries. | |||||||
| - [Introduction to Awaitlity](https://www.baeldung.com/awaitlity-testing) | - [Introduction to Awaitlity](https://www.baeldung.com/awaitlity-testing) | ||||||
| - [Introduction to Hoverfly in Java](https://www.baeldung.com/hoverfly) | - [Introduction to Hoverfly in Java](https://www.baeldung.com/hoverfly) | ||||||
| - [Testing with Hamcrest](https://www.baeldung.com/java-junit-hamcrest-guide) | - [Testing with Hamcrest](https://www.baeldung.com/java-junit-hamcrest-guide) | ||||||
|  | - [Introduction To DBUnit](https://www.baeldung.com/dbunit) | ||||||
|  | |||||||
| @ -130,6 +130,27 @@ | |||||||
|             <version>${asciidoctor.version}</version> |             <version>${asciidoctor.version}</version> | ||||||
|         </dependency> |         </dependency> | ||||||
| 
 | 
 | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.dbunit</groupId> | ||||||
|  |             <artifactId>dbunit</artifactId> | ||||||
|  |             <version>${dbunit.version}</version> | ||||||
|  |             <scope>test</scope> | ||||||
|  |         </dependency> | ||||||
|  | 
 | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>com.h2database</groupId> | ||||||
|  |             <artifactId>h2</artifactId> | ||||||
|  |             <version>${h2.version}</version> | ||||||
|  |             <scope>test</scope> | ||||||
|  |         </dependency> | ||||||
|  | 
 | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.assertj</groupId> | ||||||
|  |             <artifactId>assertj-core</artifactId> | ||||||
|  |             <version>${assertj-core.version}</version> | ||||||
|  |             <scope>test</scope> | ||||||
|  |         </dependency> | ||||||
|  | 
 | ||||||
|     </dependencies> |     </dependencies> | ||||||
| 
 | 
 | ||||||
|     <build> |     <build> | ||||||
| @ -150,6 +171,16 @@ | |||||||
|                 </executions> |                 </executions> | ||||||
|             </plugin> |             </plugin> | ||||||
| 
 | 
 | ||||||
|  |             <plugin> | ||||||
|  |                 <groupId>org.apache.maven.plugins</groupId> | ||||||
|  |                 <artifactId>maven-compiler-plugin</artifactId> | ||||||
|  |                 <version>${maven-compiler-plugin.version}</version> | ||||||
|  |                 <configuration> | ||||||
|  |                     <source>${maven-compiler-plugin.source}</source> | ||||||
|  |                     <target>${maven-compiler-plugin.target}</target> | ||||||
|  |                 </configuration> | ||||||
|  |             </plugin> | ||||||
|  | 
 | ||||||
|         </plugins> |         </plugins> | ||||||
|     </build> |     </build> | ||||||
| 
 | 
 | ||||||
| @ -166,6 +197,12 @@ | |||||||
|         <spring-mock-mvc.version>4.1.1</spring-mock-mvc.version> |         <spring-mock-mvc.version>4.1.1</spring-mock-mvc.version> | ||||||
|         <assertj.version>3.6.2</assertj.version> |         <assertj.version>3.6.2</assertj.version> | ||||||
|         <java-hamcrest.version>2.0.0.0</java-hamcrest.version> |         <java-hamcrest.version>2.0.0.0</java-hamcrest.version> | ||||||
|  |         <h2.version>1.4.200</h2.version> | ||||||
|  |         <dbunit.version>2.7.0</dbunit.version> | ||||||
|  |         <assertj-core.version>3.14.0</assertj-core.version> | ||||||
|  |         <maven-compiler-plugin.target>1.8</maven-compiler-plugin.target> | ||||||
|  |         <maven-compiler-plugin.source>1.8</maven-compiler-plugin.source> | ||||||
|  |         <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version> | ||||||
|     </properties> |     </properties> | ||||||
| 
 | 
 | ||||||
| </project> | </project> | ||||||
|  | |||||||
| @ -0,0 +1,8 @@ | |||||||
|  | package com.baeldung.dbunit; | ||||||
|  | 
 | ||||||
|  | public class ConnectionSettings { | ||||||
|  |     public static final String JDBC_DRIVER = org.h2.Driver.class.getName(); | ||||||
|  |     public static final String JDBC_URL = "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;init=runscript from 'classpath:dbunit/schema.sql'"; | ||||||
|  |     public static final String USER = "sa"; | ||||||
|  |     public static final String PASSWORD = ""; | ||||||
|  | } | ||||||
| @ -0,0 +1,168 @@ | |||||||
|  | package com.baeldung.dbunit; | ||||||
|  | 
 | ||||||
|  | import org.dbunit.Assertion; | ||||||
|  | import org.dbunit.DataSourceBasedDBTestCase; | ||||||
|  | import org.dbunit.assertion.DiffCollectingFailureHandler; | ||||||
|  | import org.dbunit.assertion.Difference; | ||||||
|  | import org.dbunit.dataset.IDataSet; | ||||||
|  | import org.dbunit.dataset.ITable; | ||||||
|  | import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; | ||||||
|  | import org.dbunit.operation.DatabaseOperation; | ||||||
|  | import org.h2.jdbcx.JdbcDataSource; | ||||||
|  | import org.junit.After; | ||||||
|  | import org.junit.Before; | ||||||
|  | import org.junit.Test; | ||||||
|  | import org.junit.platform.commons.logging.Logger; | ||||||
|  | import org.junit.platform.commons.logging.LoggerFactory; | ||||||
|  | import org.junit.runner.RunWith; | ||||||
|  | import org.junit.runners.JUnit4; | ||||||
|  | 
 | ||||||
|  | import javax.sql.DataSource; | ||||||
|  | import java.io.InputStream; | ||||||
|  | import java.sql.Connection; | ||||||
|  | import java.sql.ResultSet; | ||||||
|  | import java.sql.SQLException; | ||||||
|  | 
 | ||||||
|  | import static com.baeldung.dbunit.ConnectionSettings.JDBC_URL; | ||||||
|  | import static java.util.stream.Collectors.joining; | ||||||
|  | import static org.assertj.core.api.Assertions.assertThat; | ||||||
|  | import static org.dbunit.Assertion.assertEqualsIgnoreCols; | ||||||
|  | 
 | ||||||
|  | @RunWith(JUnit4.class) | ||||||
|  | public class DataSourceDBUnitTest extends DataSourceBasedDBTestCase { | ||||||
|  | 
 | ||||||
|  |     private static final Logger logger = LoggerFactory.getLogger(DataSourceDBUnitTest.class); | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     protected DataSource getDataSource() { | ||||||
|  |         JdbcDataSource dataSource = new JdbcDataSource(); | ||||||
|  |         dataSource.setURL(JDBC_URL); | ||||||
|  |         dataSource.setUser("sa"); | ||||||
|  |         dataSource.setPassword(""); | ||||||
|  |         return dataSource; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     protected IDataSet getDataSet() throws Exception { | ||||||
|  |         try (InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream("dbunit/data.xml")) { | ||||||
|  |             return new FlatXmlDataSetBuilder().build(resourceAsStream); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     protected DatabaseOperation getSetUpOperation() { | ||||||
|  |         return DatabaseOperation.REFRESH; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     protected DatabaseOperation getTearDownOperation() { | ||||||
|  |         return DatabaseOperation.DELETE_ALL; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Before | ||||||
|  |     public void setUp() throws Exception { | ||||||
|  |         super.setUp(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @After | ||||||
|  |     public void tearDown() throws Exception { | ||||||
|  |         super.tearDown(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenDataSet_whenSelect_thenFirstTitleIsGreyTShirt() throws SQLException { | ||||||
|  |         final Connection connection = getDataSource().getConnection(); | ||||||
|  | 
 | ||||||
|  |         final ResultSet rs = connection.createStatement().executeQuery("select * from ITEMS where id = 1"); | ||||||
|  | 
 | ||||||
|  |         assertThat(rs.next()).isTrue(); | ||||||
|  |         assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenDataSetEmptySchema_whenDataSetCreated_thenTablesAreEqual() throws Exception { | ||||||
|  |         final IDataSet expectedDataSet = getDataSet(); | ||||||
|  |         final ITable expectedTable = expectedDataSet.getTable("CLIENTS"); | ||||||
|  |         final IDataSet databaseDataSet = getConnection().createDataSet(); | ||||||
|  |         final ITable actualTable = databaseDataSet.getTable("CLIENTS"); | ||||||
|  |         Assertion.assertEquals(expectedTable, actualTable); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenDataSet_whenInsert_thenTableHasNewClient() throws Exception { | ||||||
|  |         try (final InputStream is = getClass().getClassLoader().getResourceAsStream("dbunit/expected-user.xml")) { | ||||||
|  |             final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); | ||||||
|  |             final ITable expectedTable = expectedDataSet.getTable("CLIENTS"); | ||||||
|  |             final Connection conn = getDataSource().getConnection(); | ||||||
|  | 
 | ||||||
|  |             conn.createStatement() | ||||||
|  |                 .executeUpdate( | ||||||
|  |                 "INSERT INTO CLIENTS (first_name, last_name) VALUES ('John', 'Jansen')"); | ||||||
|  |             final ITable actualData = getConnection() | ||||||
|  |                 .createQueryTable( | ||||||
|  |                     "result_name", | ||||||
|  |                     "SELECT * FROM CLIENTS WHERE last_name='Jansen'"); | ||||||
|  | 
 | ||||||
|  |             assertEqualsIgnoreCols(expectedTable, actualData, new String[] { "id" }); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenDataSet_whenDelete_thenItemIsDeleted() throws Exception { | ||||||
|  |         final Connection connection = getConnection().getConnection(); | ||||||
|  | 
 | ||||||
|  |         try (final InputStream is = DataSourceDBUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_delete.xml")) { | ||||||
|  |             ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("ITEMS"); | ||||||
|  | 
 | ||||||
|  |             connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); | ||||||
|  | 
 | ||||||
|  |             final IDataSet databaseDataSet = getConnection().createDataSet(); | ||||||
|  |             ITable actualTable = databaseDataSet.getTable("ITEMS"); | ||||||
|  | 
 | ||||||
|  |             Assertion.assertEquals(expectedTable, actualTable); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenDataSet_whenUpdate_thenItemHasNewName() throws Exception { | ||||||
|  |         final Connection connection = getConnection().getConnection(); | ||||||
|  | 
 | ||||||
|  |         try (final InputStream is = DataSourceDBUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_rename.xml")) { | ||||||
|  |             ITable expectedTable = (new FlatXmlDataSetBuilder().build(is)).getTable("ITEMS"); | ||||||
|  | 
 | ||||||
|  |             connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); | ||||||
|  | 
 | ||||||
|  |             final IDataSet databaseDataSet = getConnection().createDataSet(); | ||||||
|  |             ITable actualTable = databaseDataSet.getTable("ITEMS"); | ||||||
|  | 
 | ||||||
|  |             Assertion.assertEquals(expectedTable, actualTable); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenDataSet_whenInsertUnexpectedData_thenFailOnAllUnexpectedValues() throws Exception { | ||||||
|  |         try (final InputStream is = getClass().getClassLoader().getResourceAsStream("dbunit/expected-multiple-failures.xml")) { | ||||||
|  |             final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); | ||||||
|  |             final ITable expectedTable = expectedDataSet.getTable("ITEMS"); | ||||||
|  |             final Connection conn = getDataSource().getConnection(); | ||||||
|  |             final DiffCollectingFailureHandler collectingHandler = new DiffCollectingFailureHandler(); | ||||||
|  | 
 | ||||||
|  |             conn.createStatement().executeUpdate( | ||||||
|  |                 "INSERT INTO ITEMS (title, price) VALUES ('Battery', '1000000')"); | ||||||
|  |             final ITable actualData = getConnection().createDataSet().getTable("ITEMS"); | ||||||
|  | 
 | ||||||
|  |             Assertion.assertEquals(expectedTable, actualData, collectingHandler); | ||||||
|  |             if (!collectingHandler.getDiffList().isEmpty()) { | ||||||
|  |                 String message = (String) collectingHandler | ||||||
|  |                     .getDiffList() | ||||||
|  |                     .stream() | ||||||
|  |                     .map(d -> formatDifference((Difference) d)).collect(joining("\n")); | ||||||
|  |                 logger.error(() -> message); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private static String formatDifference(Difference diff) { | ||||||
|  |         return "expected value in " + diff.getExpectedTable().getTableMetaData().getTableName() + "." + diff.getColumnName() + " row " + diff.getRowIndex() + ":" + diff.getExpectedValue() + ", but was: " + diff.getActualValue(); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,159 @@ | |||||||
|  | package com.baeldung.dbunit; | ||||||
|  | 
 | ||||||
|  | import org.dbunit.Assertion; | ||||||
|  | import org.dbunit.IDatabaseTester; | ||||||
|  | import org.dbunit.JdbcDatabaseTester; | ||||||
|  | import org.dbunit.dataset.IDataSet; | ||||||
|  | import org.dbunit.dataset.ITable; | ||||||
|  | import org.dbunit.dataset.filter.DefaultColumnFilter; | ||||||
|  | import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; | ||||||
|  | import org.dbunit.operation.DatabaseOperation; | ||||||
|  | import org.junit.After; | ||||||
|  | import org.junit.Before; | ||||||
|  | import org.junit.BeforeClass; | ||||||
|  | import org.junit.Test; | ||||||
|  | import org.junit.runner.RunWith; | ||||||
|  | import org.junit.runners.JUnit4; | ||||||
|  | 
 | ||||||
|  | import java.io.InputStream; | ||||||
|  | import java.sql.Connection; | ||||||
|  | import java.sql.ResultSet; | ||||||
|  | 
 | ||||||
|  | import static com.baeldung.dbunit.ConnectionSettings.JDBC_DRIVER; | ||||||
|  | import static com.baeldung.dbunit.ConnectionSettings.JDBC_URL; | ||||||
|  | import static com.baeldung.dbunit.ConnectionSettings.PASSWORD; | ||||||
|  | import static com.baeldung.dbunit.ConnectionSettings.USER; | ||||||
|  | import static org.assertj.core.api.Assertions.assertThat; | ||||||
|  | import static org.dbunit.Assertion.assertEquals; | ||||||
|  | 
 | ||||||
|  | @RunWith(JUnit4.class) | ||||||
|  | public class OldSchoolDbUnitTest { | ||||||
|  | 
 | ||||||
|  |     private static IDatabaseTester tester = null; | ||||||
|  | 
 | ||||||
|  |     @BeforeClass | ||||||
|  |     public static void setUp() throws Exception { | ||||||
|  |         tester = initDatabaseTester(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private static IDatabaseTester initDatabaseTester() throws Exception { | ||||||
|  |         final JdbcDatabaseTester tester = new JdbcDatabaseTester(JDBC_DRIVER, JDBC_URL, USER, PASSWORD); | ||||||
|  |         tester.setDataSet(initDataSet()); | ||||||
|  |         tester.setSetUpOperation(DatabaseOperation.REFRESH); | ||||||
|  |         tester.setTearDownOperation(DatabaseOperation.DELETE_ALL); | ||||||
|  |         return tester; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private static IDataSet initDataSet() throws Exception { | ||||||
|  |         try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/data.xml")) { | ||||||
|  |             return new FlatXmlDataSetBuilder().build(is); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Before | ||||||
|  |     public void setup() throws Exception { | ||||||
|  |         tester.onSetup(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @After | ||||||
|  |     public void tearDown() throws Exception { | ||||||
|  |         tester.onTearDown(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenDataSet_whenSelect_thenFirstTitleIsGreyTShirt() throws Exception { | ||||||
|  |         final Connection connection = tester.getConnection().getConnection(); | ||||||
|  | 
 | ||||||
|  |         final ResultSet rs = connection.createStatement().executeQuery("select * from ITEMS where id = 1"); | ||||||
|  | 
 | ||||||
|  |         assertThat(rs.next()).isTrue(); | ||||||
|  |         assertThat(rs.getString("title")).isEqualTo("Grey T-Shirt"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenDataSet_whenInsert_thenGetResultsAreStillEqualIfIgnoringColumnsWithDifferentProduced() throws Exception { | ||||||
|  |         final Connection connection = tester.getConnection().getConnection(); | ||||||
|  |         final String[] excludedColumns = { "id", "produced" }; | ||||||
|  |         try (final InputStream is = getClass().getClassLoader().getResourceAsStream("dbunit/expected-ignoring-registered_at.xml")) { | ||||||
|  |             final IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(is); | ||||||
|  |             final ITable expectedTable = DefaultColumnFilter.excludedColumnsTable( | ||||||
|  |                 expectedDataSet.getTable("ITEMS"), excludedColumns); | ||||||
|  | 
 | ||||||
|  |             connection.createStatement().executeUpdate( | ||||||
|  |                 "INSERT INTO ITEMS (title, price, produced)  VALUES('Necklace', 199.99, now())"); | ||||||
|  | 
 | ||||||
|  |             final IDataSet databaseDataSet = tester.getConnection().createDataSet(); | ||||||
|  |             final ITable actualTable = DefaultColumnFilter.excludedColumnsTable( | ||||||
|  |                 databaseDataSet.getTable("ITEMS"), excludedColumns); | ||||||
|  | 
 | ||||||
|  |             Assertion.assertEquals(expectedTable, actualTable); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenDataSet_whenDelete_thenItemIsRemoved() throws Exception { | ||||||
|  |         final Connection connection = tester.getConnection().getConnection(); | ||||||
|  | 
 | ||||||
|  |         try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_delete.xml")) { | ||||||
|  |             ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("ITEMS"); | ||||||
|  | 
 | ||||||
|  |             connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); | ||||||
|  | 
 | ||||||
|  |             final IDataSet databaseDataSet = tester.getConnection().createDataSet(); | ||||||
|  |             ITable actualTable = databaseDataSet.getTable("ITEMS"); | ||||||
|  | 
 | ||||||
|  |             assertEquals(expectedTable, actualTable); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenDataSet_whenDelete_thenItemIsRemovedAndResultsEqualIfProducedIsIgnored() throws Exception { | ||||||
|  |         final Connection connection = tester.getConnection().getConnection(); | ||||||
|  | 
 | ||||||
|  |         try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_delete_no_produced.xml")) { | ||||||
|  |             final ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("ITEMS"); | ||||||
|  | 
 | ||||||
|  |             connection.createStatement().executeUpdate("delete from ITEMS where id = 2"); | ||||||
|  | 
 | ||||||
|  |             final IDataSet databaseDataSet = tester.getConnection().createDataSet(); | ||||||
|  |             ITable actualTable = databaseDataSet.getTable("ITEMS"); | ||||||
|  |             actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[] { "produced" }); | ||||||
|  | 
 | ||||||
|  |             assertEquals(expectedTable, actualTable); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenDataSet_whenUpdate_thenItemHasNewName() throws Exception { | ||||||
|  |         final Connection connection = tester.getConnection().getConnection(); | ||||||
|  | 
 | ||||||
|  |         try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_rename.xml")) { | ||||||
|  |             final ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("ITEMS"); | ||||||
|  | 
 | ||||||
|  |             connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); | ||||||
|  | 
 | ||||||
|  |             final IDataSet databaseDataSet = tester.getConnection().createDataSet(); | ||||||
|  |             ITable actualTable = databaseDataSet.getTable("ITEMS"); | ||||||
|  | 
 | ||||||
|  |             assertEquals(expectedTable, actualTable); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenDataSet_whenUpdateWithNoProduced_thenItemHasNewName() throws Exception { | ||||||
|  |         final Connection connection = tester.getConnection().getConnection(); | ||||||
|  | 
 | ||||||
|  |         try (final InputStream is = OldSchoolDbUnitTest.class.getClassLoader().getResourceAsStream("dbunit/items_exp_rename_no_produced.xml")) { | ||||||
|  |             ITable expectedTable = new FlatXmlDataSetBuilder().build(is).getTable("ITEMS"); | ||||||
|  |             expectedTable = DefaultColumnFilter.excludedColumnsTable(expectedTable, new String[] { "produced" }); | ||||||
|  | 
 | ||||||
|  |             connection.createStatement().executeUpdate("update ITEMS set title='new name' where id = 1"); | ||||||
|  | 
 | ||||||
|  |             final IDataSet databaseDataSet = tester.getConnection().createDataSet(); | ||||||
|  |             ITable actualTable = databaseDataSet.getTable("ITEMS"); | ||||||
|  |             actualTable = DefaultColumnFilter.excludedColumnsTable(actualTable, new String[] { "produced" }); | ||||||
|  |             assertEquals(expectedTable, actualTable); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -78,10 +78,10 @@ public class JsonAssertUnitTest { | |||||||
| 
 | 
 | ||||||
|     @Test |     @Test | ||||||
|     public void givenArray_whenComparing_thenOrderMustMatchForStrict() throws JSONException { |     public void givenArray_whenComparing_thenOrderMustMatchForStrict() throws JSONException { | ||||||
|         String result = "[Alex, Barbera, Charlie, Xavier]"; |         String result = "[Alex, Barbera, Charlie, Wolf]"; | ||||||
|         JSONAssert.assertEquals("[Charlie, Alex, Xavier, Barbera]", result, JSONCompareMode.LENIENT); |         JSONAssert.assertEquals("[Charlie, Alex, Wolf, Barbera]", result, JSONCompareMode.LENIENT); | ||||||
|         JSONAssert.assertEquals("[Alex, Barbera, Charlie, Xavier]", result, JSONCompareMode.STRICT); |         JSONAssert.assertEquals("[Alex, Barbera, Charlie, Wolf]", result, JSONCompareMode.STRICT); | ||||||
|         JSONAssert.assertNotEquals("[Charlie, Alex, Xavier, Barbera]", result, JSONCompareMode.STRICT); |         JSONAssert.assertNotEquals("[Charlie, Alex, Wolf, Barbera]", result, JSONCompareMode.STRICT); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Test |     @Test | ||||||
| @ -94,7 +94,7 @@ public class JsonAssertUnitTest { | |||||||
| 
 | 
 | ||||||
|     @Test |     @Test | ||||||
|     public void whenComparingSizeOfArray_thenPass() throws JSONException { |     public void whenComparingSizeOfArray_thenPass() throws JSONException { | ||||||
|         String names = "{names:[Alex, Barbera, Charlie, Xavier]}"; |         String names = "{names:[Alex, Barbera, Charlie, Wolf]}"; | ||||||
|         JSONAssert.assertEquals("{names:[4]}", names, new ArraySizeComparator(JSONCompareMode.LENIENT)); |         JSONAssert.assertEquals("{names:[4]}", names, new ArraySizeComparator(JSONCompareMode.LENIENT)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										9
									
								
								libraries-testing/src/test/resources/dbunit/data.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								libraries-testing/src/test/resources/dbunit/data.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <dataset> | ||||||
|  |     <CLIENTS id='1' first_name='Charles' last_name='Wolf'/> | ||||||
|  |     <ITEMS id='1' title='Grey T-Shirt' price='17.99' produced='2019-03-20'/> | ||||||
|  |     <ITEMS id='2' title='Fitted Hat' price='29.99' produced='2019-03-21'/> | ||||||
|  |     <ITEMS id='3' title='Backpack' price='54.99' produced='2019-03-22'/> | ||||||
|  |     <ITEMS id='4' title='Earrings' price='14.99' produced='2019-03-23'/> | ||||||
|  |     <ITEMS id='5' title='Socks' price='9.99'/> | ||||||
|  | </dataset> | ||||||
| @ -0,0 +1,9 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <dataset> | ||||||
|  |     <ITEMS id='1' title='Grey T-Shirt' price='17.99' produced='2019-03-20'/> | ||||||
|  |     <ITEMS id='2' title='Fitted Hat' price='29.99' produced='2019-03-21'/> | ||||||
|  |     <ITEMS id='3' title='Backpack' price='54.99' produced='2019-03-22'/> | ||||||
|  |     <ITEMS id='4' title='Earrings' price='14.99' produced='2019-03-23'/> | ||||||
|  |     <ITEMS id='5' title='Socks' price='9.99'/> | ||||||
|  |     <ITEMS id='6' title='Necklace' price='199.99' produced='2019-03-23'/> | ||||||
|  | </dataset> | ||||||
| @ -0,0 +1,9 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <dataset> | ||||||
|  |     <ITEMS id='1' title='Grey T-Shirt' price='17.99' produced='2019-03-20'/> | ||||||
|  |     <ITEMS id='2' title='Fitted Hat' price='29.99' produced='2019-03-21'/> | ||||||
|  |     <ITEMS id='3' title='Backpack' price='54.99' produced='2019-03-22'/> | ||||||
|  |     <ITEMS id='4' title='Earrings' price='14.99' produced='2019-03-23'/> | ||||||
|  |     <ITEMS id='5' title='Socks' price='9.99'/> | ||||||
|  |     <ITEMS id='6' title='Necklace' price='199.99' produced='2019-03-23'/> | ||||||
|  | </dataset> | ||||||
| @ -0,0 +1,4 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <dataset> | ||||||
|  |     <CLIENTS id='2' first_name='John' last_name='Jansen'/> | ||||||
|  | </dataset> | ||||||
							
								
								
									
										8
									
								
								libraries-testing/src/test/resources/dbunit/items.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								libraries-testing/src/test/resources/dbunit/items.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <dataset> | ||||||
|  |     <ITEMS id='1' title='Grey T-Shirt' price='17.99' produced='2019-03-20'/> | ||||||
|  |     <ITEMS id='2' title='Fitted Hat' price='29.99' produced='2019-03-21'/> | ||||||
|  |     <ITEMS id='3' title='Backpack' price='54.99' produced='2019-03-22'/> | ||||||
|  |     <ITEMS id='4' title='Earrings' price='14.99' produced='2019-03-23'/> | ||||||
|  |     <ITEMS id='5' title='Socks' price='9.99'/> | ||||||
|  | </dataset> | ||||||
| @ -0,0 +1,7 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <dataset> | ||||||
|  |     <ITEMS id='1' title='Grey T-Shirt' price='17.99' produced='2019-03-20'/> | ||||||
|  |     <ITEMS id='3' title='Backpack' price='54.99' produced='2019-03-22'/> | ||||||
|  |     <ITEMS id='4' title='Earrings' price='14.99' produced='2019-03-23'/> | ||||||
|  |     <ITEMS id='5' title='Socks' price='9.99'/> | ||||||
|  | </dataset> | ||||||
| @ -0,0 +1,7 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <dataset> | ||||||
|  |     <ITEMS id='1' title='Grey T-Shirt' price='17.99'/> | ||||||
|  |     <ITEMS id='3' title='Backpack' price='54.99'/> | ||||||
|  |     <ITEMS id='4' title='Earrings' price='14.99'/> | ||||||
|  |     <ITEMS id='5' title='Socks' price='9.99'/> | ||||||
|  | </dataset> | ||||||
| @ -0,0 +1,8 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <dataset> | ||||||
|  |     <ITEMS id='1' title='new name' price='17.99' produced='2019-03-20'/> | ||||||
|  |     <ITEMS id='2' title='Fitted Hat' price='29.99' produced='2019-03-21'/> | ||||||
|  |     <ITEMS id='3' title='Backpack' price='54.99' produced='2019-03-22'/> | ||||||
|  |     <ITEMS id='4' title='Earrings' price='14.99' produced='2019-03-23'/> | ||||||
|  |     <ITEMS id='5' title='Socks' price='9.99'/> | ||||||
|  | </dataset> | ||||||
| @ -0,0 +1,8 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <dataset> | ||||||
|  |     <ITEMS id='1' title='new name' price='17.99' produced='2019-03-20'/> | ||||||
|  |     <ITEMS id='2' title='Fitted Hat' price='29.99'/> | ||||||
|  |     <ITEMS id='3' title='Backpack' price='54.99'/> | ||||||
|  |     <ITEMS id='4' title='Earrings' price='14.99'/> | ||||||
|  |     <ITEMS id='5' title='Socks' price='9.99'/> | ||||||
|  | </dataset> | ||||||
							
								
								
									
										28
									
								
								libraries-testing/src/test/resources/dbunit/schema.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								libraries-testing/src/test/resources/dbunit/schema.sql
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | |||||||
|  | CREATE TABLE IF NOT EXISTS CLIENTS | ||||||
|  | ( | ||||||
|  |     `id`         int AUTO_INCREMENT NOT NULL, | ||||||
|  |     `first_name` varchar(100)       NOT NULL, | ||||||
|  |     `last_name`  varchar(100)       NOT NULL, | ||||||
|  |     PRIMARY KEY (`id`) | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | CREATE TABLE IF NOT EXISTS ITEMS | ||||||
|  | ( | ||||||
|  |     `id`       int AUTO_INCREMENT NOT NULL, | ||||||
|  |     `title`    varchar(100)       NOT NULL, | ||||||
|  |     `produced` date, | ||||||
|  |     `price`    float, | ||||||
|  |     PRIMARY KEY (`id`) | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | CREATE TABLE IF NOT EXISTS PURCHASES | ||||||
|  | ( | ||||||
|  |     `id`          int     NOT NULL AUTO_INCREMENT, | ||||||
|  |     `id_user`     int     NOT NULL, | ||||||
|  |     `id_item`     int     NOT NULL, | ||||||
|  |     `total_price` float   NOT NULL, | ||||||
|  |     `quantity`    int(11) NOT NULL, | ||||||
|  |     PRIMARY KEY (`id`), | ||||||
|  |     FOREIGN KEY (`id_user`) REFERENCES CLIENTS (`id`) ON DELETE CASCADE, | ||||||
|  |     FOREIGN KEY (`id_item`) REFERENCES ITEMS (`id`) ON DELETE CASCADE ON UPDATE CASCADE | ||||||
|  | ); | ||||||
							
								
								
									
										6
									
								
								libraries-testing/src/test/resources/dbunit/users.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								libraries-testing/src/test/resources/dbunit/users.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <dataset> | ||||||
|  |     <CLIENTS id='1' first_name='Charles' last_name='Wolf'/> | ||||||
|  |     <CLIENTS id='2' first_name='Scott' last_name='Summers'/> | ||||||
|  |     <CLIENTS id='3' first_name='Jean' last_name='Grey'/> | ||||||
|  | </dataset> | ||||||
| @ -0,0 +1,5 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <dataset> | ||||||
|  |     <CLIENTS id='1' first_name='Charles' last_name='Wolf'/> | ||||||
|  |     <CLIENTS id='3' first_name='Jean' last_name='Grey'/> | ||||||
|  | </dataset> | ||||||
| @ -0,0 +1,6 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <dataset> | ||||||
|  |     <CLIENTS id='1' first_name='new name' last_name='Wolf'/> | ||||||
|  |     <CLIENTS id='2' first_name='Scott' last_name='Summers'/> | ||||||
|  |     <CLIENTS id='3' first_name='Jean' last_name='Grey'/> | ||||||
|  | </dataset> | ||||||
| @ -13,3 +13,4 @@ This module contains articles specific to use of Hibernate as a JPA implementati | |||||||
| - [Enabling Transaction Locks in Spring Data JPA](https://www.baeldung.com/java-jpa-transaction-locks) | - [Enabling Transaction Locks in Spring Data JPA](https://www.baeldung.com/java-jpa-transaction-locks) | ||||||
| - [TransactionRequiredException Error](https://www.baeldung.com/jpa-transaction-required-exception) | - [TransactionRequiredException Error](https://www.baeldung.com/jpa-transaction-required-exception) | ||||||
| - [JPA/Hibernate Persistence Context](https://www.baeldung.com/jpa-hibernate-persistence-context) | - [JPA/Hibernate Persistence Context](https://www.baeldung.com/jpa-hibernate-persistence-context) | ||||||
|  | - [Quick Guide to EntityManager#getReference()](https://www.baeldung.com/jpa-entity-manager-get-reference) | ||||||
|  | |||||||
| @ -18,6 +18,12 @@ | |||||||
|             <artifactId>cassandra-driver-core</artifactId> |             <artifactId>cassandra-driver-core</artifactId> | ||||||
|             <version>${cassandra-driver-core.version}</version> |             <version>${cassandra-driver-core.version}</version> | ||||||
|             <optional>true</optional> |             <optional>true</optional> | ||||||
|  |             <exclusions> | ||||||
|  |                 <exclusion> | ||||||
|  |                     <groupId>com.google.guava</groupId> | ||||||
|  |                     <artifactId>guava</artifactId> | ||||||
|  |                 </exclusion> | ||||||
|  |             </exclusions> | ||||||
|         </dependency> |         </dependency> | ||||||
| 
 | 
 | ||||||
|         <!-- https://mvnrepository.com/artifact/org.cassandraunit/cassandra-unit --> |         <!-- https://mvnrepository.com/artifact/org.cassandraunit/cassandra-unit --> | ||||||
|  | |||||||
| @ -0,0 +1,51 @@ | |||||||
|  | cluster_name: 'Test Cluster' | ||||||
|  | hinted_handoff_enabled: true | ||||||
|  | max_hint_window_in_ms: 10800000 | ||||||
|  | hinted_handoff_throttle_in_kb: 1024 | ||||||
|  | max_hints_delivery_threads: 2 | ||||||
|  | hints_directory: target/embeddedCassandra/hints | ||||||
|  | authenticator: AllowAllAuthenticator | ||||||
|  | authorizer: AllowAllAuthorizer | ||||||
|  | permissions_validity_in_ms: 2000 | ||||||
|  | partitioner: RandomPartitioner | ||||||
|  | data_file_directories: | ||||||
|  |   - target/embeddedCassandra/data | ||||||
|  | commitlog_directory: target/embeddedCassandra/commitlog | ||||||
|  | cdc_raw_directory: target/embeddedCassandra/cdc | ||||||
|  | disk_failure_policy: stop | ||||||
|  | key_cache_size_in_mb: | ||||||
|  | key_cache_save_period: 14400 | ||||||
|  | row_cache_size_in_mb: 0 | ||||||
|  | row_cache_save_period: 0 | ||||||
|  | saved_caches_directory: target/embeddedCassandra/saved_caches | ||||||
|  | commitlog_sync: periodic | ||||||
|  | commitlog_sync_period_in_ms: 10000 | ||||||
|  | commitlog_segment_size_in_mb: 32 | ||||||
|  | concurrent_reads: 32 | ||||||
|  | concurrent_writes: 32 | ||||||
|  | trickle_fsync: false | ||||||
|  | trickle_fsync_interval_in_kb: 10240 | ||||||
|  | thrift_framed_transport_size_in_mb: 15 | ||||||
|  | thrift_max_message_length_in_mb: 16 | ||||||
|  | incremental_backups: false | ||||||
|  | snapshot_before_compaction: false | ||||||
|  | auto_snapshot: false | ||||||
|  | column_index_size_in_kb: 64 | ||||||
|  | compaction_throughput_mb_per_sec: 16 | ||||||
|  | read_request_timeout_in_ms: 5000 | ||||||
|  | range_request_timeout_in_ms: 10000 | ||||||
|  | write_request_timeout_in_ms: 2000 | ||||||
|  | cas_contention_timeout_in_ms: 1000 | ||||||
|  | truncate_request_timeout_in_ms: 60000 | ||||||
|  | request_timeout_in_ms: 10000 | ||||||
|  | cross_node_timeout: false | ||||||
|  | endpoint_snitch: SimpleSnitch | ||||||
|  | dynamic_snitch_update_interval_in_ms: 100 | ||||||
|  | dynamic_snitch_reset_interval_in_ms: 600000 | ||||||
|  | dynamic_snitch_badness_threshold: 0.1 | ||||||
|  | request_scheduler: org.apache.cassandra.scheduler.NoScheduler | ||||||
|  | index_interval: 128 | ||||||
|  | seed_provider: | ||||||
|  |   - class_name: org.apache.cassandra.locator.SimpleSeedProvider | ||||||
|  |     parameters: | ||||||
|  |       - seeds: "127.0.0.1" | ||||||
| @ -10,3 +10,4 @@ This module contains articles about MongoDB in Java. | |||||||
| - [Geospatial Support in MongoDB](https://www.baeldung.com/mongodb-geospatial-support) | - [Geospatial Support in MongoDB](https://www.baeldung.com/mongodb-geospatial-support) | ||||||
| - [Introduction to Morphia – Java ODM for MongoDB](https://www.baeldung.com/mongodb-morphia) | - [Introduction to Morphia – Java ODM for MongoDB](https://www.baeldung.com/mongodb-morphia) | ||||||
| - [MongoDB Aggregations Using Java](https://www.baeldung.com/java-mongodb-aggregations) | - [MongoDB Aggregations Using Java](https://www.baeldung.com/java-mongodb-aggregations) | ||||||
|  | - [MongoDB BSON to JSON](https://www.baeldung.com/bson-to-json) | ||||||
|  | |||||||
| @ -1,5 +1,7 @@ | |||||||
| package com.baeldung.morphia.domain; | package com.baeldung.morphia.domain; | ||||||
| 
 | 
 | ||||||
|  | import java.time.LocalDate; | ||||||
|  | import java.time.LocalDateTime; | ||||||
| import java.util.HashSet; | import java.util.HashSet; | ||||||
| import java.util.Set; | import java.util.Set; | ||||||
| 
 | 
 | ||||||
| @ -29,28 +31,13 @@ public class Book { | |||||||
|     private double cost; |     private double cost; | ||||||
|     @Reference |     @Reference | ||||||
|     private Set<Book> companionBooks; |     private Set<Book> companionBooks; | ||||||
|  |     @Property | ||||||
|  |     private LocalDateTime publishDate; | ||||||
| 
 | 
 | ||||||
|     public Book() { |     public Book() { | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public String getTitle() { |  | ||||||
|         return title; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public String getAuthor() { |  | ||||||
|         return author; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public double getCost() { |  | ||||||
|         return cost; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public void addCompanionBooks(Book book) { |  | ||||||
|         if (companionBooks != null) |  | ||||||
|             this.companionBooks.add(book); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public Book(String isbn, String title, String author, double cost, Publisher publisher) { |     public Book(String isbn, String title, String author, double cost, Publisher publisher) { | ||||||
|         this.isbn = isbn; |         this.isbn = isbn; | ||||||
|         this.title = title; |         this.title = title; | ||||||
| @ -60,6 +47,71 @@ public class Book { | |||||||
|         this.companionBooks = new HashSet<>(); |         this.companionBooks = new HashSet<>(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     // Getters and setters ... | ||||||
|  |     public String getIsbn() { | ||||||
|  |         return isbn; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Book setIsbn(String isbn) { | ||||||
|  |         this.isbn = isbn; | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public String getTitle() { | ||||||
|  |         return title; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Book setTitle(String title) { | ||||||
|  |         this.title = title; | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public String getAuthor() { | ||||||
|  |         return author; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Book setAuthor(String author) { | ||||||
|  |         this.author = author; | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Publisher getPublisher() { | ||||||
|  |         return publisher; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Book setPublisher(Publisher publisher) { | ||||||
|  |         this.publisher = publisher; | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public double getCost() { | ||||||
|  |         return cost; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Book setCost(double cost) { | ||||||
|  |         this.cost = cost; | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public LocalDateTime getPublishDate() { | ||||||
|  |         return publishDate; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Book setPublishDate(LocalDateTime publishDate) { | ||||||
|  |         this.publishDate = publishDate; | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Set<Book> getCompanionBooks() { | ||||||
|  |         return companionBooks; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Book addCompanionBooks(Book book) { | ||||||
|  |         if (companionBooks != null) | ||||||
|  |             this.companionBooks.add(book); | ||||||
|  |         return this; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     @Override |     @Override | ||||||
|     public String toString() { |     public String toString() { | ||||||
|         return "Book [isbn=" + isbn + ", title=" + title + ", author=" + author + ", publisher=" + publisher + ", cost=" + cost + "]"; |         return "Book [isbn=" + isbn + ", title=" + title + ", author=" + author + ", publisher=" + publisher + ", cost=" + cost + "]"; | ||||||
| @ -113,4 +165,4 @@ public class Book { | |||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -0,0 +1,142 @@ | |||||||
|  | package com.baeldung.bsontojson; | ||||||
|  | 
 | ||||||
|  | import static org.junit.Assert.assertEquals; | ||||||
|  | import static org.junit.Assert.assertNotNull; | ||||||
|  | import static org.junit.Assert.assertTrue; | ||||||
|  | 
 | ||||||
|  | import java.sql.Timestamp; | ||||||
|  | import java.time.Instant; | ||||||
|  | import java.time.LocalDateTime; | ||||||
|  | import java.time.format.DateTimeFormatter; | ||||||
|  | import java.util.Date; | ||||||
|  | import java.util.TimeZone; | ||||||
|  | import java.util.regex.Matcher; | ||||||
|  | import java.util.regex.Pattern; | ||||||
|  | 
 | ||||||
|  | import org.bson.Document; | ||||||
|  | import org.bson.json.Converter; | ||||||
|  | import org.bson.json.JsonMode; | ||||||
|  | import org.bson.json.JsonWriterSettings; | ||||||
|  | import org.bson.json.StrictJsonWriter; | ||||||
|  | import org.bson.types.ObjectId; | ||||||
|  | import org.junit.AfterClass; | ||||||
|  | import org.junit.BeforeClass; | ||||||
|  | import org.junit.Test; | ||||||
|  | import org.junit.jupiter.api.AfterEach; | ||||||
|  | import org.slf4j.Logger; | ||||||
|  | import org.slf4j.LoggerFactory; | ||||||
|  | 
 | ||||||
|  | import com.baeldung.morphia.domain.Book; | ||||||
|  | import com.baeldung.morphia.domain.Publisher; | ||||||
|  | import com.mongodb.MongoClient; | ||||||
|  | import com.mongodb.client.MongoDatabase; | ||||||
|  | 
 | ||||||
|  | import dev.morphia.Datastore; | ||||||
|  | import dev.morphia.Morphia; | ||||||
|  | 
 | ||||||
|  | public class BsonToJsonIntegrationTest { | ||||||
|  |      | ||||||
|  |     private static final String DB_NAME = "library"; | ||||||
|  |     private static Datastore datastore; | ||||||
|  | 
 | ||||||
|  |     @BeforeClass | ||||||
|  |     public static void setUp() { | ||||||
|  |         Morphia morphia = new Morphia(); | ||||||
|  |         morphia.mapPackage("com.baeldung.morphia"); | ||||||
|  |         datastore = morphia.createDatastore(new MongoClient(), DB_NAME); | ||||||
|  |         datastore.ensureIndexes(); | ||||||
|  |          | ||||||
|  |         datastore.save(new Book() | ||||||
|  |             .setIsbn("isbn") | ||||||
|  |             .setTitle("title") | ||||||
|  |             .setAuthor("author") | ||||||
|  |             .setCost(3.95) | ||||||
|  |             .setPublisher(new Publisher(new ObjectId("fffffffffffffffffffffffa"),"publisher")) | ||||||
|  |             .setPublishDate(LocalDateTime.parse("2020-01-01T18:13:32Z", DateTimeFormatter.ISO_DATE_TIME)) | ||||||
|  |             .addCompanionBooks(new Book().setIsbn("isbn2"))); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     @AfterClass | ||||||
|  |     public static void tearDown() { | ||||||
|  |         datastore.delete(datastore.createQuery(Book.class)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenBsonDocument_whenUsingStandardJsonTransformation_thenJsonDateIsObjectEpochTime() { | ||||||
|  | 
 | ||||||
|  |         String json = null; | ||||||
|  |         try (MongoClient mongoClient = new MongoClient()) { | ||||||
|  |             MongoDatabase mongoDatabase = mongoClient.getDatabase(DB_NAME); | ||||||
|  |             Document bson = mongoDatabase.getCollection("Books").find().first(); | ||||||
|  |             json = bson.toJson(); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         String expectedJson = "{\"_id\": \"isbn\", " +  | ||||||
|  |             "\"className\": \"com.baeldung.morphia.domain.Book\", " +  | ||||||
|  |             "\"title\": \"title\", " +  | ||||||
|  |             "\"author\": \"author\", " +  | ||||||
|  |             "\"publisher\": {\"_id\": {\"$oid\": \"fffffffffffffffffffffffa\"}, " +  | ||||||
|  |             "\"name\": \"publisher\"}, " +  | ||||||
|  |             "\"price\": 3.95, " +  | ||||||
|  |             "\"publishDate\": {\"$date\": 1577898812000}}"; | ||||||
|  | 
 | ||||||
|  |         assertNotNull(json); | ||||||
|  |          | ||||||
|  |         assertEquals(expectedJson, json); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     public void givenBsonDocument_whenUsingRelaxedJsonTransformation_thenJsonDateIsObjectIsoDate() { | ||||||
|  |     | ||||||
|  |         String json = null; | ||||||
|  |         try (MongoClient mongoClient = new MongoClient()) { | ||||||
|  |             MongoDatabase mongoDatabase = mongoClient.getDatabase(DB_NAME); | ||||||
|  |             Document bson = mongoDatabase.getCollection("Books").find().first(); | ||||||
|  |             json = bson.toJson(JsonWriterSettings | ||||||
|  |                 .builder() | ||||||
|  |                 .outputMode(JsonMode.RELAXED) | ||||||
|  |                 .build()); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         String expectedJson = "{\"_id\": \"isbn\", " +  | ||||||
|  |             "\"className\": \"com.baeldung.morphia.domain.Book\", " +  | ||||||
|  |             "\"title\": \"title\", " +  | ||||||
|  |             "\"author\": \"author\", " +  | ||||||
|  |             "\"publisher\": {\"_id\": {\"$oid\": \"fffffffffffffffffffffffa\"}, " +  | ||||||
|  |             "\"name\": \"publisher\"}, " +  | ||||||
|  |             "\"price\": 3.95, " +  | ||||||
|  |             "\"publishDate\": {\"$date\": \"2020-01-01T17:13:32Z\"}}"; | ||||||
|  | 
 | ||||||
|  |         assertNotNull(json); | ||||||
|  |          | ||||||
|  |         assertEquals(expectedJson, json); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     @Test | ||||||
|  |     public void givenBsonDocument_whenUsingCustomJsonTransformation_thenJsonDateIsStringField() { | ||||||
|  | 
 | ||||||
|  |         String json = null; | ||||||
|  |         try (MongoClient mongoClient = new MongoClient()) { | ||||||
|  |             MongoDatabase mongoDatabase = mongoClient.getDatabase(DB_NAME); | ||||||
|  |             Document bson = mongoDatabase.getCollection("Books").find().first(); | ||||||
|  |             json = bson.toJson(JsonWriterSettings | ||||||
|  |                 .builder() | ||||||
|  |                 .dateTimeConverter(new JsonDateTimeConverter()) | ||||||
|  |                 .build()); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         String expectedJson = "{\"_id\": \"isbn\", " +  | ||||||
|  |             "\"className\": \"com.baeldung.morphia.domain.Book\", " +  | ||||||
|  |             "\"title\": \"title\", " +  | ||||||
|  |             "\"author\": \"author\", " +  | ||||||
|  |             "\"publisher\": {\"_id\": {\"$oid\": \"fffffffffffffffffffffffa\"}, " +  | ||||||
|  |             "\"name\": \"publisher\"}, " +  | ||||||
|  |             "\"price\": 3.95, " +  | ||||||
|  |             "\"publishDate\": \"2020-01-01T17:13:32Z\"}"; | ||||||
|  | 
 | ||||||
|  |         assertEquals(expectedJson, json); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,30 @@ | |||||||
|  | package com.baeldung.bsontojson; | ||||||
|  | 
 | ||||||
|  | import java.time.Instant; | ||||||
|  | import java.time.ZoneId; | ||||||
|  | import java.time.format.DateTimeFormatter; | ||||||
|  | import java.util.Date; | ||||||
|  | import java.util.TimeZone; | ||||||
|  | 
 | ||||||
|  | import org.bson.json.Converter; | ||||||
|  | import org.bson.json.StrictJsonWriter; | ||||||
|  | import org.slf4j.Logger; | ||||||
|  | import org.slf4j.LoggerFactory; | ||||||
|  | 
 | ||||||
|  | public class JsonDateTimeConverter implements Converter<Long> { | ||||||
|  | 
 | ||||||
|  |     private static final Logger LOGGER = LoggerFactory.getLogger(JsonDateTimeConverter.class); | ||||||
|  |     static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ISO_INSTANT | ||||||
|  |         .withZone(ZoneId.of("UTC")); | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void convert(Long value, StrictJsonWriter writer) { | ||||||
|  |         try { | ||||||
|  |             Instant instant = new Date(value).toInstant(); | ||||||
|  |             String s = DATE_TIME_FORMATTER.format(instant); | ||||||
|  |             writer.writeString(s); | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             LOGGER.error(String.format("Fail to convert offset %d to JSON date", value), e); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										2
									
								
								persistence-modules/spring-data-jpa-4/create.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								persistence-modules/spring-data-jpa-4/create.sql
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | |||||||
|  | create table PERSON (ID int8 not null, FIRST_NAME varchar(255), LAST_NAME varchar(255), primary key (ID)) | ||||||
|  | create table person (id int8 not null, first_name varchar(255), last_name varchar(255), primary key (id)) | ||||||
| @ -33,6 +33,11 @@ | |||||||
|             <artifactId>mysql-connector-java</artifactId> |             <artifactId>mysql-connector-java</artifactId> | ||||||
|         </dependency> |         </dependency> | ||||||
| 
 | 
 | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.postgresql</groupId> | ||||||
|  |             <artifactId>postgresql</artifactId> | ||||||
|  |         </dependency> | ||||||
|  | 
 | ||||||
|         <dependency> |         <dependency> | ||||||
|             <groupId>com.h2database</groupId> |             <groupId>com.h2database</groupId> | ||||||
|             <artifactId>h2</artifactId> |             <artifactId>h2</artifactId> | ||||||
|  | |||||||
| @ -0,0 +1,35 @@ | |||||||
|  | package com.baeldung.namingstrategy; | ||||||
|  | 
 | ||||||
|  | import javax.persistence.Column; | ||||||
|  | import javax.persistence.Entity; | ||||||
|  | import javax.persistence.Id; | ||||||
|  | 
 | ||||||
|  | @Entity | ||||||
|  | public class Person { | ||||||
|  |     @Id | ||||||
|  |     private Long id; | ||||||
|  | 
 | ||||||
|  |     private String firstName; | ||||||
|  | 
 | ||||||
|  |     private String lastName; | ||||||
|  | 
 | ||||||
|  |     public Person() {} | ||||||
|  | 
 | ||||||
|  |     public Person(Long id, String firstName, String lastName) { | ||||||
|  |         this.id = id; | ||||||
|  |         this.firstName = firstName; | ||||||
|  |         this.lastName = lastName; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Long id() { | ||||||
|  |         return id; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public String firstName() { | ||||||
|  |         return firstName; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public String lastName() { | ||||||
|  |         return lastName; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,6 @@ | |||||||
|  | package com.baeldung.namingstrategy; | ||||||
|  | 
 | ||||||
|  | import org.springframework.data.jpa.repository.JpaRepository; | ||||||
|  | 
 | ||||||
|  | public interface PersonRepository extends JpaRepository<Person, Long> { | ||||||
|  | } | ||||||
| @ -0,0 +1,12 @@ | |||||||
|  | package com.baeldung.namingstrategy; | ||||||
|  | 
 | ||||||
|  | import org.hibernate.boot.model.naming.Identifier; | ||||||
|  | import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; | ||||||
|  | import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy; | ||||||
|  | 
 | ||||||
|  | public class QuotedLowerCaseNamingStrategy extends SpringPhysicalNamingStrategy { | ||||||
|  |     @Override | ||||||
|  |     protected Identifier getIdentifier(String name, boolean quoted, JdbcEnvironment jdbcEnvironment) { | ||||||
|  |         return new Identifier(name.toLowerCase(), true); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,12 @@ | |||||||
|  | package com.baeldung.namingstrategy; | ||||||
|  | 
 | ||||||
|  | import org.hibernate.boot.model.naming.Identifier; | ||||||
|  | import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; | ||||||
|  | import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy; | ||||||
|  | 
 | ||||||
|  | public class QuotedUpperCaseNamingStrategy extends SpringPhysicalNamingStrategy { | ||||||
|  |     @Override | ||||||
|  |     protected Identifier getIdentifier(String name, boolean quoted, JdbcEnvironment jdbcEnvironment) { | ||||||
|  |         return new Identifier(name.toUpperCase(), true); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,7 @@ | |||||||
|  | package com.baeldung.namingstrategy; | ||||||
|  | 
 | ||||||
|  | import org.springframework.boot.autoconfigure.SpringBootApplication; | ||||||
|  | 
 | ||||||
|  | @SpringBootApplication | ||||||
|  | public class SpringDataJpaNamingConventionApplication { | ||||||
|  | } | ||||||
| @ -0,0 +1,12 @@ | |||||||
|  | package com.baeldung.namingstrategy; | ||||||
|  | 
 | ||||||
|  | import org.hibernate.boot.model.naming.Identifier; | ||||||
|  | import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; | ||||||
|  | import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy; | ||||||
|  | 
 | ||||||
|  | public class UnquotedLowerCaseNamingStrategy extends SpringPhysicalNamingStrategy { | ||||||
|  |     @Override | ||||||
|  |     protected Identifier getIdentifier(String name, boolean quoted, JdbcEnvironment jdbcEnvironment) { | ||||||
|  |         return new Identifier(name.toLowerCase(), false); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,12 @@ | |||||||
|  | package com.baeldung.namingstrategy; | ||||||
|  | 
 | ||||||
|  | import org.hibernate.boot.model.naming.Identifier; | ||||||
|  | import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; | ||||||
|  | import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy; | ||||||
|  | 
 | ||||||
|  | public class UnquotedUpperCaseNamingStrategy extends SpringPhysicalNamingStrategy { | ||||||
|  |     @Override | ||||||
|  |     protected Identifier getIdentifier(String name, boolean quoted, JdbcEnvironment jdbcEnvironment) { | ||||||
|  |         return new Identifier(name.toUpperCase(), false); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,81 @@ | |||||||
|  | package com.baeldung.namingstrategy; | ||||||
|  | 
 | ||||||
|  | import org.hibernate.exception.SQLGrammarException; | ||||||
|  | import org.junit.jupiter.api.BeforeEach; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.junit.jupiter.params.ParameterizedTest; | ||||||
|  | import org.junit.jupiter.params.provider.ValueSource; | ||||||
|  | import org.springframework.beans.factory.annotation.Autowired; | ||||||
|  | import org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration; | ||||||
|  | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; | ||||||
|  | import org.springframework.test.context.TestPropertySource; | ||||||
|  | 
 | ||||||
|  | import javax.persistence.EntityManager; | ||||||
|  | import javax.persistence.PersistenceContext; | ||||||
|  | import javax.persistence.Query; | ||||||
|  | import java.math.BigInteger; | ||||||
|  | import java.util.Arrays; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.stream.Collectors; | ||||||
|  | 
 | ||||||
|  | import static org.assertj.core.api.Assertions.assertThat; | ||||||
|  | import static org.junit.jupiter.api.Assertions.assertThrows; | ||||||
|  | 
 | ||||||
|  | @DataJpaTest(excludeAutoConfiguration = TestDatabaseAutoConfiguration.class) | ||||||
|  | @TestPropertySource("quoted-lower-case-naming-strategy.properties") | ||||||
|  | class QuotedLowerCaseNamingStrategyH2IntegrationTest { | ||||||
|  | 
 | ||||||
|  |     @PersistenceContext | ||||||
|  |     private EntityManager entityManager; | ||||||
|  | 
 | ||||||
|  |     @Autowired | ||||||
|  |     private PersonRepository personRepository; | ||||||
|  | 
 | ||||||
|  |     @BeforeEach | ||||||
|  |     void insertPeople() { | ||||||
|  |         personRepository.saveAll(Arrays.asList( | ||||||
|  |           new Person(1L, "John", "Doe"), | ||||||
|  |           new Person(2L, "Jane", "Doe"), | ||||||
|  |           new Person(3L, "Ted", "Mosby") | ||||||
|  |         )); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @ParameterizedTest | ||||||
|  |     @ValueSource(strings = {"person", "PERSON", "Person"}) | ||||||
|  |     void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonUnquoted_thenException(String tableName) { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from " + tableName); | ||||||
|  | 
 | ||||||
|  |         // Unexpected result | ||||||
|  |         assertThrows(SQLGrammarException.class, query::getResultStream); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonQuotedUpperCase_thenException() { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from \"PERSON\""); | ||||||
|  | 
 | ||||||
|  |         // Expected result | ||||||
|  |         assertThrows(SQLGrammarException.class, query::getResultStream); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonQuotedLowerCase_thenResult() { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from \"person\""); | ||||||
|  | 
 | ||||||
|  |         // Expected result | ||||||
|  |         List<Person> result = (List<Person>) query.getResultStream() | ||||||
|  |           .map(this::fromDatabase) | ||||||
|  |           .collect(Collectors.toList()); | ||||||
|  | 
 | ||||||
|  |         assertThat(result).isNotEmpty(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Person fromDatabase(Object databaseRow) { | ||||||
|  |         Object[] typedDatabaseRow = (Object[]) databaseRow; | ||||||
|  | 
 | ||||||
|  |         return new Person( | ||||||
|  |           ((BigInteger) typedDatabaseRow[0]).longValue(), | ||||||
|  |           (String) typedDatabaseRow[1], | ||||||
|  |           (String) typedDatabaseRow[2] | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,85 @@ | |||||||
|  | package com.baeldung.namingstrategy; | ||||||
|  | 
 | ||||||
|  | import org.hibernate.exception.SQLGrammarException; | ||||||
|  | import org.junit.jupiter.api.BeforeEach; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.junit.jupiter.params.ParameterizedTest; | ||||||
|  | import org.junit.jupiter.params.provider.ValueSource; | ||||||
|  | import org.springframework.beans.factory.annotation.Autowired; | ||||||
|  | import org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration; | ||||||
|  | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; | ||||||
|  | import org.springframework.test.context.TestPropertySource; | ||||||
|  | 
 | ||||||
|  | import javax.persistence.EntityManager; | ||||||
|  | import javax.persistence.PersistenceContext; | ||||||
|  | import javax.persistence.Query; | ||||||
|  | import java.math.BigInteger; | ||||||
|  | import java.util.Arrays; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.stream.Collectors; | ||||||
|  | 
 | ||||||
|  | import static org.assertj.core.api.Assertions.assertThat; | ||||||
|  | import static org.junit.jupiter.api.Assertions.assertThrows; | ||||||
|  | 
 | ||||||
|  | @DataJpaTest(excludeAutoConfiguration = TestDatabaseAutoConfiguration.class) | ||||||
|  | @TestPropertySource("quoted-lower-case-naming-strategy-on-postgres.properties") | ||||||
|  | class QuotedLowerCaseNamingStrategyPostgresLiveTest { | ||||||
|  | 
 | ||||||
|  |     @PersistenceContext | ||||||
|  |     private EntityManager entityManager; | ||||||
|  | 
 | ||||||
|  |     @Autowired | ||||||
|  |     private PersonRepository personRepository; | ||||||
|  | 
 | ||||||
|  |     @BeforeEach | ||||||
|  |     void insertPeople() { | ||||||
|  |         personRepository.saveAll(Arrays.asList( | ||||||
|  |           new Person(1L, "John", "Doe"), | ||||||
|  |           new Person(2L, "Jane", "Doe"), | ||||||
|  |           new Person(3L, "Ted", "Mosby") | ||||||
|  |         )); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @ParameterizedTest | ||||||
|  |     @ValueSource(strings = {"person", "PERSON", "Person"}) | ||||||
|  |     void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonUnquoted_thenResult(String tableName) { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from " + tableName); | ||||||
|  | 
 | ||||||
|  |         // Expected result | ||||||
|  |         List<Person> result = (List<Person>) query.getResultStream() | ||||||
|  |           .map(this::fromDatabase) | ||||||
|  |           .collect(Collectors.toList()); | ||||||
|  | 
 | ||||||
|  |         assertThat(result).isNotEmpty(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonQuotedUpperCase_thenException() { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from \"PERSON\""); | ||||||
|  | 
 | ||||||
|  |         // Expected result | ||||||
|  |         assertThrows(SQLGrammarException.class, query::getResultStream); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonQuotedLowerCase_thenResult() { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from \"person\""); | ||||||
|  | 
 | ||||||
|  |         // Expected result | ||||||
|  |         List<Person> result = (List<Person>) query.getResultStream() | ||||||
|  |           .map(this::fromDatabase) | ||||||
|  |           .collect(Collectors.toList()); | ||||||
|  | 
 | ||||||
|  |         assertThat(result).isNotEmpty(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Person fromDatabase(Object databaseRow) { | ||||||
|  |         Object[] typedDatabaseRow = (Object[]) databaseRow; | ||||||
|  | 
 | ||||||
|  |         return new Person( | ||||||
|  |           ((BigInteger) typedDatabaseRow[0]).longValue(), | ||||||
|  |           (String) typedDatabaseRow[1], | ||||||
|  |           (String) typedDatabaseRow[2] | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,85 @@ | |||||||
|  | package com.baeldung.namingstrategy; | ||||||
|  | 
 | ||||||
|  | import org.hibernate.exception.SQLGrammarException; | ||||||
|  | import org.junit.jupiter.api.BeforeEach; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.junit.jupiter.params.ParameterizedTest; | ||||||
|  | import org.junit.jupiter.params.provider.ValueSource; | ||||||
|  | import org.springframework.beans.factory.annotation.Autowired; | ||||||
|  | import org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration; | ||||||
|  | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; | ||||||
|  | import org.springframework.test.context.TestPropertySource; | ||||||
|  | 
 | ||||||
|  | import javax.persistence.EntityManager; | ||||||
|  | import javax.persistence.PersistenceContext; | ||||||
|  | import javax.persistence.Query; | ||||||
|  | import java.math.BigInteger; | ||||||
|  | import java.util.Arrays; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.stream.Collectors; | ||||||
|  | 
 | ||||||
|  | import static org.assertj.core.api.Assertions.assertThat; | ||||||
|  | import static org.junit.jupiter.api.Assertions.assertThrows; | ||||||
|  | 
 | ||||||
|  | @DataJpaTest(excludeAutoConfiguration = TestDatabaseAutoConfiguration.class) | ||||||
|  | @TestPropertySource("quoted-upper-case-naming-strategy.properties") | ||||||
|  | class QuotedUpperCaseNamingStrategyH2IntegrationTest { | ||||||
|  | 
 | ||||||
|  |     @PersistenceContext | ||||||
|  |     private EntityManager entityManager; | ||||||
|  | 
 | ||||||
|  |     @Autowired | ||||||
|  |     private PersonRepository personRepository; | ||||||
|  | 
 | ||||||
|  |     @BeforeEach | ||||||
|  |     void insertPeople() { | ||||||
|  |         personRepository.saveAll(Arrays.asList( | ||||||
|  |           new Person(1L, "John", "Doe"), | ||||||
|  |           new Person(2L, "Jane", "Doe"), | ||||||
|  |           new Person(3L, "Ted", "Mosby") | ||||||
|  |         )); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @ParameterizedTest | ||||||
|  |     @ValueSource(strings = {"person", "PERSON", "Person"}) | ||||||
|  |     void givenPeopleAndUpperCaseNamingStrategy_whenQueryPersonUnquoted_thenException(String tableName) { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from " + tableName); | ||||||
|  | 
 | ||||||
|  |         // Expected result | ||||||
|  |         List<Person> result = (List<Person>) query.getResultStream() | ||||||
|  |           .map(this::fromDatabase) | ||||||
|  |           .collect(Collectors.toList()); | ||||||
|  | 
 | ||||||
|  |         assertThat(result).isNotEmpty(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenPeopleAndUpperCaseNamingStrategy_whenQueryPersonQuotedUpperCase_thenResult() { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from \"PERSON\""); | ||||||
|  | 
 | ||||||
|  |         // Expected result | ||||||
|  |         List<Person> result = (List<Person>) query.getResultStream() | ||||||
|  |           .map(this::fromDatabase) | ||||||
|  |           .collect(Collectors.toList()); | ||||||
|  | 
 | ||||||
|  |         assertThat(result).isNotEmpty(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenPeopleAndUpperCaseNamingStrategy_whenQueryPersonQuotedLowerCase_thenException() { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from \"person\""); | ||||||
|  | 
 | ||||||
|  |         // Expected result | ||||||
|  |         assertThrows(SQLGrammarException.class, query::getResultStream); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Person fromDatabase(Object databaseRow) { | ||||||
|  |         Object[] typedDatabaseRow = (Object[]) databaseRow; | ||||||
|  | 
 | ||||||
|  |         return new Person( | ||||||
|  |           ((BigInteger) typedDatabaseRow[0]).longValue(), | ||||||
|  |           (String) typedDatabaseRow[1], | ||||||
|  |           (String) typedDatabaseRow[2] | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,81 @@ | |||||||
|  | package com.baeldung.namingstrategy; | ||||||
|  | 
 | ||||||
|  | import org.hibernate.exception.SQLGrammarException; | ||||||
|  | import org.junit.jupiter.api.BeforeEach; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.junit.jupiter.params.ParameterizedTest; | ||||||
|  | import org.junit.jupiter.params.provider.ValueSource; | ||||||
|  | import org.springframework.beans.factory.annotation.Autowired; | ||||||
|  | import org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration; | ||||||
|  | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; | ||||||
|  | import org.springframework.test.context.TestPropertySource; | ||||||
|  | 
 | ||||||
|  | import javax.persistence.EntityManager; | ||||||
|  | import javax.persistence.PersistenceContext; | ||||||
|  | import javax.persistence.Query; | ||||||
|  | import java.math.BigInteger; | ||||||
|  | import java.util.Arrays; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.stream.Collectors; | ||||||
|  | 
 | ||||||
|  | import static org.assertj.core.api.Assertions.assertThat; | ||||||
|  | import static org.junit.jupiter.api.Assertions.assertThrows; | ||||||
|  | 
 | ||||||
|  | @DataJpaTest(excludeAutoConfiguration = TestDatabaseAutoConfiguration.class) | ||||||
|  | @TestPropertySource("quoted-upper-case-naming-strategy-on-postgres.properties") | ||||||
|  | class QuotedUpperCaseNamingStrategyPostgresLiveTest { | ||||||
|  | 
 | ||||||
|  |     @PersistenceContext | ||||||
|  |     private EntityManager entityManager; | ||||||
|  | 
 | ||||||
|  |     @Autowired | ||||||
|  |     private PersonRepository personRepository; | ||||||
|  | 
 | ||||||
|  |     @BeforeEach | ||||||
|  |     void insertPeople() { | ||||||
|  |         personRepository.saveAll(Arrays.asList( | ||||||
|  |           new Person(1L, "John", "Doe"), | ||||||
|  |           new Person(2L, "Jane", "Doe"), | ||||||
|  |           new Person(3L, "Ted", "Mosby") | ||||||
|  |         )); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @ParameterizedTest | ||||||
|  |     @ValueSource(strings = {"person", "PERSON", "Person"}) | ||||||
|  |     void givenPeopleAndUpperCaseNamingStrategy_whenQueryPersonUnquoted_thenResult(String tableName) { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from " + tableName); | ||||||
|  | 
 | ||||||
|  |         // Unexpected result | ||||||
|  |         assertThrows(SQLGrammarException.class, query::getResultStream); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenPeopleAndUpperCaseNamingStrategy_whenQueryPersonQuotedUpperCase_thenException() { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from \"PERSON\""); | ||||||
|  | 
 | ||||||
|  |         // Expected result | ||||||
|  |         List<Person> result = (List<Person>) query.getResultStream() | ||||||
|  |           .map(this::fromDatabase) | ||||||
|  |           .collect(Collectors.toList()); | ||||||
|  | 
 | ||||||
|  |         assertThat(result).isNotEmpty(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenPeopleAndUpperCaseNamingStrategy_whenQueryPersonQuotedLowerCase_thenResult() { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from \"person\""); | ||||||
|  | 
 | ||||||
|  |         // Expected result | ||||||
|  |         assertThrows(SQLGrammarException.class, query::getResultStream); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Person fromDatabase(Object databaseRow) { | ||||||
|  |         Object[] typedDatabaseRow = (Object[]) databaseRow; | ||||||
|  | 
 | ||||||
|  |         return new Person( | ||||||
|  |           ((BigInteger) typedDatabaseRow[0]).longValue(), | ||||||
|  |           (String) typedDatabaseRow[1], | ||||||
|  |           (String) typedDatabaseRow[2] | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,85 @@ | |||||||
|  | package com.baeldung.namingstrategy; | ||||||
|  | 
 | ||||||
|  | import org.hibernate.exception.SQLGrammarException; | ||||||
|  | import org.junit.jupiter.api.BeforeEach; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.junit.jupiter.params.ParameterizedTest; | ||||||
|  | import org.junit.jupiter.params.provider.ValueSource; | ||||||
|  | import org.springframework.beans.factory.annotation.Autowired; | ||||||
|  | import org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration; | ||||||
|  | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; | ||||||
|  | import org.springframework.test.context.TestPropertySource; | ||||||
|  | 
 | ||||||
|  | import javax.persistence.EntityManager; | ||||||
|  | import javax.persistence.PersistenceContext; | ||||||
|  | import javax.persistence.Query; | ||||||
|  | import java.math.BigInteger; | ||||||
|  | import java.util.Arrays; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.stream.Collectors; | ||||||
|  | 
 | ||||||
|  | import static org.assertj.core.api.Assertions.assertThat; | ||||||
|  | import static org.junit.jupiter.api.Assertions.assertThrows; | ||||||
|  | 
 | ||||||
|  | @DataJpaTest(excludeAutoConfiguration = TestDatabaseAutoConfiguration.class) | ||||||
|  | @TestPropertySource("spring-physical-naming-strategy.properties") | ||||||
|  | class SpringPhysicalNamingStrategyH2IntegrationTest { | ||||||
|  | 
 | ||||||
|  |     @PersistenceContext | ||||||
|  |     private EntityManager entityManager; | ||||||
|  | 
 | ||||||
|  |     @Autowired | ||||||
|  |     private PersonRepository personRepository; | ||||||
|  | 
 | ||||||
|  |     @BeforeEach | ||||||
|  |     void insertPeople() { | ||||||
|  |         personRepository.saveAll(Arrays.asList( | ||||||
|  |           new Person(1L, "John", "Doe"), | ||||||
|  |           new Person(2L, "Jane", "Doe"), | ||||||
|  |           new Person(3L, "Ted", "Mosby") | ||||||
|  |         )); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @ParameterizedTest | ||||||
|  |     @ValueSource(strings = {"person", "PERSON", "Person"}) | ||||||
|  |     void givenPeopleAndSpringNamingStrategy_whenQueryPersonUnquoted_thenResult(String tableName) { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from " + tableName); | ||||||
|  | 
 | ||||||
|  |         // Expected result | ||||||
|  |         List<Person> result = (List<Person>) query.getResultStream() | ||||||
|  |           .map(this::fromDatabase) | ||||||
|  |           .collect(Collectors.toList()); | ||||||
|  | 
 | ||||||
|  |         assertThat(result).isNotEmpty(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenPeopleAndSpringNamingStrategy_whenQueryPersonQuotedUpperCase_thenResult() { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from \"PERSON\""); | ||||||
|  | 
 | ||||||
|  |         // Unexpected result | ||||||
|  |         List<Person> result = (List<Person>) query.getResultStream() | ||||||
|  |           .map(this::fromDatabase) | ||||||
|  |           .collect(Collectors.toList()); | ||||||
|  | 
 | ||||||
|  |         assertThat(result).isNotEmpty(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenPeopleAndSpringNamingStrategy_whenQueryPersonQuotedLowerCase_thenException() { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from \"person\""); | ||||||
|  | 
 | ||||||
|  |         // Unexpected result | ||||||
|  |         assertThrows(SQLGrammarException.class, query::getResultStream); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Person fromDatabase(Object databaseRow) { | ||||||
|  |         Object[] typedDatabaseRow = (Object[]) databaseRow; | ||||||
|  | 
 | ||||||
|  |         return new Person( | ||||||
|  |           ((BigInteger) typedDatabaseRow[0]).longValue(), | ||||||
|  |           (String) typedDatabaseRow[1], | ||||||
|  |           (String) typedDatabaseRow[2] | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,85 @@ | |||||||
|  | package com.baeldung.namingstrategy; | ||||||
|  | 
 | ||||||
|  | import org.hibernate.exception.SQLGrammarException; | ||||||
|  | import org.junit.jupiter.api.BeforeEach; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.junit.jupiter.params.ParameterizedTest; | ||||||
|  | import org.junit.jupiter.params.provider.ValueSource; | ||||||
|  | import org.springframework.beans.factory.annotation.Autowired; | ||||||
|  | import org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration; | ||||||
|  | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; | ||||||
|  | import org.springframework.test.context.TestPropertySource; | ||||||
|  | 
 | ||||||
|  | import javax.persistence.EntityManager; | ||||||
|  | import javax.persistence.PersistenceContext; | ||||||
|  | import javax.persistence.Query; | ||||||
|  | import java.math.BigInteger; | ||||||
|  | import java.util.Arrays; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.stream.Collectors; | ||||||
|  | 
 | ||||||
|  | import static org.assertj.core.api.Assertions.assertThat; | ||||||
|  | import static org.junit.jupiter.api.Assertions.assertThrows; | ||||||
|  | 
 | ||||||
|  | @DataJpaTest(excludeAutoConfiguration = TestDatabaseAutoConfiguration.class) | ||||||
|  | @TestPropertySource("spring-physical-naming-strategy-on-postgres.properties") | ||||||
|  | class SpringPhysicalNamingStrategyPostgresLiveTest { | ||||||
|  | 
 | ||||||
|  |     @PersistenceContext | ||||||
|  |     private EntityManager entityManager; | ||||||
|  | 
 | ||||||
|  |     @Autowired | ||||||
|  |     private PersonRepository personRepository; | ||||||
|  | 
 | ||||||
|  |     @BeforeEach | ||||||
|  |     void insertPeople() { | ||||||
|  |         personRepository.saveAll(Arrays.asList( | ||||||
|  |           new Person(1L, "John", "Doe"), | ||||||
|  |           new Person(2L, "Jane", "Doe"), | ||||||
|  |           new Person(3L, "Ted", "Mosby") | ||||||
|  |         )); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @ParameterizedTest | ||||||
|  |     @ValueSource(strings = {"person", "PERSON", "Person"}) | ||||||
|  |     void givenPeopleAndSpringNamingStrategy_whenQueryPersonUnquoted_thenResult(String tableName) { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from " + tableName); | ||||||
|  | 
 | ||||||
|  |         // Expected result | ||||||
|  |         List<Person> result = (List<Person>) query.getResultStream() | ||||||
|  |           .map(this::fromDatabase) | ||||||
|  |           .collect(Collectors.toList()); | ||||||
|  | 
 | ||||||
|  |         assertThat(result).isNotEmpty(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenPeopleAndSpringNamingStrategy_whenQueryPersonQuotedUpperCase_thenException() { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from \"PERSON\""); | ||||||
|  | 
 | ||||||
|  |         // Expected result | ||||||
|  |         assertThrows(SQLGrammarException.class, query::getResultStream); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenPeopleAndSpringNamingStrategy_whenQueryPersonQuotedLowerCase_thenResult() { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from \"person\""); | ||||||
|  | 
 | ||||||
|  |         // Expected result | ||||||
|  |         List<Person> result = (List<Person>) query.getResultStream() | ||||||
|  |           .map(this::fromDatabase) | ||||||
|  |           .collect(Collectors.toList()); | ||||||
|  | 
 | ||||||
|  |         assertThat(result).isNotEmpty(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Person fromDatabase(Object databaseRow) { | ||||||
|  |         Object[] typedDatabaseRow = (Object[]) databaseRow; | ||||||
|  | 
 | ||||||
|  |         return new Person( | ||||||
|  |           ((BigInteger) typedDatabaseRow[0]).longValue(), | ||||||
|  |           (String) typedDatabaseRow[1], | ||||||
|  |           (String) typedDatabaseRow[2] | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,86 @@ | |||||||
|  | package com.baeldung.namingstrategy; | ||||||
|  | 
 | ||||||
|  | import org.hibernate.exception.SQLGrammarException; | ||||||
|  | import org.junit.jupiter.api.BeforeEach; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.junit.jupiter.params.ParameterizedTest; | ||||||
|  | import org.junit.jupiter.params.provider.ValueSource; | ||||||
|  | import org.springframework.beans.factory.annotation.Autowired; | ||||||
|  | import org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration; | ||||||
|  | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; | ||||||
|  | import org.springframework.test.context.TestPropertySource; | ||||||
|  | 
 | ||||||
|  | import javax.persistence.EntityManager; | ||||||
|  | import javax.persistence.PersistenceContext; | ||||||
|  | import javax.persistence.Query; | ||||||
|  | import java.math.BigInteger; | ||||||
|  | import java.sql.SQLException; | ||||||
|  | import java.util.Arrays; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.stream.Collectors; | ||||||
|  | 
 | ||||||
|  | import static org.assertj.core.api.Assertions.assertThat; | ||||||
|  | import static org.junit.jupiter.api.Assertions.assertThrows; | ||||||
|  | 
 | ||||||
|  | @DataJpaTest(excludeAutoConfiguration = TestDatabaseAutoConfiguration.class) | ||||||
|  | @TestPropertySource("unquoted-lower-case-naming-strategy.properties") | ||||||
|  | class UnquotedLowerCaseNamingStrategyH2IntegrationTest { | ||||||
|  | 
 | ||||||
|  |     @PersistenceContext | ||||||
|  |     private EntityManager entityManager; | ||||||
|  | 
 | ||||||
|  |     @Autowired | ||||||
|  |     private PersonRepository personRepository; | ||||||
|  | 
 | ||||||
|  |     @BeforeEach | ||||||
|  |     void insertPeople() { | ||||||
|  |         personRepository.saveAll(Arrays.asList( | ||||||
|  |           new Person(1L, "John", "Doe"), | ||||||
|  |           new Person(2L, "Jane", "Doe"), | ||||||
|  |           new Person(3L, "Ted", "Mosby") | ||||||
|  |         )); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @ParameterizedTest | ||||||
|  |     @ValueSource(strings = {"person", "PERSON", "Person"}) | ||||||
|  |     void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonUnquoted_thenResult(String tableName) { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from " + tableName); | ||||||
|  | 
 | ||||||
|  |         // Expected result | ||||||
|  |         List<Person> result = (List<Person>) query.getResultStream() | ||||||
|  |           .map(this::fromDatabase) | ||||||
|  |           .collect(Collectors.toList()); | ||||||
|  | 
 | ||||||
|  |         assertThat(result).isNotEmpty(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonQuotedUpperCase_thenResult() { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from \"PERSON\""); | ||||||
|  | 
 | ||||||
|  |         // Unexpected result | ||||||
|  |         List<Person> result = (List<Person>) query.getResultStream() | ||||||
|  |           .map(this::fromDatabase) | ||||||
|  |           .collect(Collectors.toList()); | ||||||
|  | 
 | ||||||
|  |         assertThat(result).isNotEmpty(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonQuotedLowerCase_thenException() { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from \"person\""); | ||||||
|  | 
 | ||||||
|  |         // Unexpected result | ||||||
|  |         assertThrows(SQLGrammarException.class, query::getResultStream); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Person fromDatabase(Object databaseRow) { | ||||||
|  |         Object[] typedDatabaseRow = (Object[]) databaseRow; | ||||||
|  | 
 | ||||||
|  |         return new Person( | ||||||
|  |           ((BigInteger) typedDatabaseRow[0]).longValue(), | ||||||
|  |           (String) typedDatabaseRow[1], | ||||||
|  |           (String) typedDatabaseRow[2] | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,85 @@ | |||||||
|  | package com.baeldung.namingstrategy; | ||||||
|  | 
 | ||||||
|  | import org.hibernate.exception.SQLGrammarException; | ||||||
|  | import org.junit.jupiter.api.BeforeEach; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.junit.jupiter.params.ParameterizedTest; | ||||||
|  | import org.junit.jupiter.params.provider.ValueSource; | ||||||
|  | import org.springframework.beans.factory.annotation.Autowired; | ||||||
|  | import org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration; | ||||||
|  | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; | ||||||
|  | import org.springframework.test.context.TestPropertySource; | ||||||
|  | 
 | ||||||
|  | import javax.persistence.EntityManager; | ||||||
|  | import javax.persistence.PersistenceContext; | ||||||
|  | import javax.persistence.Query; | ||||||
|  | import java.math.BigInteger; | ||||||
|  | import java.util.Arrays; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.stream.Collectors; | ||||||
|  | 
 | ||||||
|  | import static org.assertj.core.api.Assertions.assertThat; | ||||||
|  | import static org.junit.jupiter.api.Assertions.assertThrows; | ||||||
|  | 
 | ||||||
|  | @DataJpaTest(excludeAutoConfiguration = TestDatabaseAutoConfiguration.class) | ||||||
|  | @TestPropertySource("unquoted-lower-case-naming-strategy-on-postgres.properties") | ||||||
|  | class UnquotedLowerCaseNamingStrategyPostgresLiveTest { | ||||||
|  | 
 | ||||||
|  |     @PersistenceContext | ||||||
|  |     private EntityManager entityManager; | ||||||
|  | 
 | ||||||
|  |     @Autowired | ||||||
|  |     private PersonRepository personRepository; | ||||||
|  | 
 | ||||||
|  |     @BeforeEach | ||||||
|  |     void insertPeople() { | ||||||
|  |         personRepository.saveAll(Arrays.asList( | ||||||
|  |           new Person(1L, "John", "Doe"), | ||||||
|  |           new Person(2L, "Jane", "Doe"), | ||||||
|  |           new Person(3L, "Ted", "Mosby") | ||||||
|  |         )); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @ParameterizedTest | ||||||
|  |     @ValueSource(strings = {"person", "PERSON", "Person"}) | ||||||
|  |     void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonUnquoted_thenResult(String tableName) { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from " + tableName); | ||||||
|  | 
 | ||||||
|  |         // Expected result | ||||||
|  |         List<Person> result = (List<Person>) query.getResultStream() | ||||||
|  |           .map(this::fromDatabase) | ||||||
|  |           .collect(Collectors.toList()); | ||||||
|  | 
 | ||||||
|  |         assertThat(result).isNotEmpty(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonQuotedUpperCase_thenException() { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from \"PERSON\""); | ||||||
|  | 
 | ||||||
|  |         // Expected result | ||||||
|  |         assertThrows(SQLGrammarException.class, query::getResultStream); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenPeopleAndLowerCaseNamingStrategy_whenQueryPersonQuotedLowerCase_thenResult() { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from \"person\""); | ||||||
|  | 
 | ||||||
|  |         // Expected result | ||||||
|  |         List<Person> result = (List<Person>) query.getResultStream() | ||||||
|  |           .map(this::fromDatabase) | ||||||
|  |           .collect(Collectors.toList()); | ||||||
|  | 
 | ||||||
|  |         assertThat(result).isNotEmpty(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Person fromDatabase(Object databaseRow) { | ||||||
|  |         Object[] typedDatabaseRow = (Object[]) databaseRow; | ||||||
|  | 
 | ||||||
|  |         return new Person( | ||||||
|  |           ((BigInteger) typedDatabaseRow[0]).longValue(), | ||||||
|  |           (String) typedDatabaseRow[1], | ||||||
|  |           (String) typedDatabaseRow[2] | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,85 @@ | |||||||
|  | package com.baeldung.namingstrategy; | ||||||
|  | 
 | ||||||
|  | import org.hibernate.exception.SQLGrammarException; | ||||||
|  | import org.junit.jupiter.api.BeforeEach; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.junit.jupiter.params.ParameterizedTest; | ||||||
|  | import org.junit.jupiter.params.provider.ValueSource; | ||||||
|  | import org.springframework.beans.factory.annotation.Autowired; | ||||||
|  | import org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration; | ||||||
|  | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; | ||||||
|  | import org.springframework.test.context.TestPropertySource; | ||||||
|  | 
 | ||||||
|  | import javax.persistence.EntityManager; | ||||||
|  | import javax.persistence.PersistenceContext; | ||||||
|  | import javax.persistence.Query; | ||||||
|  | import java.math.BigInteger; | ||||||
|  | import java.util.Arrays; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.stream.Collectors; | ||||||
|  | 
 | ||||||
|  | import static org.assertj.core.api.Assertions.assertThat; | ||||||
|  | import static org.junit.jupiter.api.Assertions.assertThrows; | ||||||
|  | 
 | ||||||
|  | @DataJpaTest(excludeAutoConfiguration = TestDatabaseAutoConfiguration.class) | ||||||
|  | @TestPropertySource("unquoted-upper-case-naming-strategy.properties") | ||||||
|  | class UnquotedUpperCaseNamingStrategyH2IntegrationTest { | ||||||
|  | 
 | ||||||
|  |     @PersistenceContext | ||||||
|  |     private EntityManager entityManager; | ||||||
|  | 
 | ||||||
|  |     @Autowired | ||||||
|  |     private PersonRepository personRepository; | ||||||
|  | 
 | ||||||
|  |     @BeforeEach | ||||||
|  |     void insertPeople() { | ||||||
|  |         personRepository.saveAll(Arrays.asList( | ||||||
|  |           new Person(1L, "John", "Doe"), | ||||||
|  |           new Person(2L, "Jane", "Doe"), | ||||||
|  |           new Person(3L, "Ted", "Mosby") | ||||||
|  |         )); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @ParameterizedTest | ||||||
|  |     @ValueSource(strings = {"person", "PERSON", "Person"}) | ||||||
|  |     void givenPeopleAndUpperCaseNamingStrategy_whenQueryPersonUnquoted_thenResult(String tableName) { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from " + tableName); | ||||||
|  | 
 | ||||||
|  |         // Expected result | ||||||
|  |         List<Person> result = (List<Person>) query.getResultStream() | ||||||
|  |           .map(this::fromDatabase) | ||||||
|  |           .collect(Collectors.toList()); | ||||||
|  | 
 | ||||||
|  |         assertThat(result).isNotEmpty(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenPeopleAndUpperCaseNamingStrategy_whenQueryPersonQuotedUpperCase_thenResult() { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from \"PERSON\""); | ||||||
|  | 
 | ||||||
|  |         // Expected result | ||||||
|  |         List<Person> result = (List<Person>) query.getResultStream() | ||||||
|  |           .map(this::fromDatabase) | ||||||
|  |           .collect(Collectors.toList()); | ||||||
|  | 
 | ||||||
|  |         assertThat(result).isNotEmpty(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenPeopleAndUpperCaseNamingStrategy_whenQueryPersonQuotedLowerCase_thenException() { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from \"person\""); | ||||||
|  | 
 | ||||||
|  |         // Expected result | ||||||
|  |         assertThrows(SQLGrammarException.class, query::getResultStream); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Person fromDatabase(Object databaseRow) { | ||||||
|  |         Object[] typedDatabaseRow = (Object[]) databaseRow; | ||||||
|  | 
 | ||||||
|  |         return new Person( | ||||||
|  |           ((BigInteger) typedDatabaseRow[0]).longValue(), | ||||||
|  |           (String) typedDatabaseRow[1], | ||||||
|  |           (String) typedDatabaseRow[2] | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,85 @@ | |||||||
|  | package com.baeldung.namingstrategy; | ||||||
|  | 
 | ||||||
|  | import org.hibernate.exception.SQLGrammarException; | ||||||
|  | import org.junit.jupiter.api.BeforeEach; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.junit.jupiter.params.ParameterizedTest; | ||||||
|  | import org.junit.jupiter.params.provider.ValueSource; | ||||||
|  | import org.springframework.beans.factory.annotation.Autowired; | ||||||
|  | import org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration; | ||||||
|  | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; | ||||||
|  | import org.springframework.test.context.TestPropertySource; | ||||||
|  | 
 | ||||||
|  | import javax.persistence.EntityManager; | ||||||
|  | import javax.persistence.PersistenceContext; | ||||||
|  | import javax.persistence.Query; | ||||||
|  | import java.math.BigInteger; | ||||||
|  | import java.util.Arrays; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.stream.Collectors; | ||||||
|  | 
 | ||||||
|  | import static org.assertj.core.api.Assertions.assertThat; | ||||||
|  | import static org.junit.jupiter.api.Assertions.assertThrows; | ||||||
|  | 
 | ||||||
|  | @DataJpaTest(excludeAutoConfiguration = TestDatabaseAutoConfiguration.class) | ||||||
|  | @TestPropertySource("unquoted-upper-case-naming-strategy-on-postgres.properties") | ||||||
|  | class UnquotedUpperCaseNamingStrategyPostgresLiveTest { | ||||||
|  | 
 | ||||||
|  |     @PersistenceContext | ||||||
|  |     private EntityManager entityManager; | ||||||
|  | 
 | ||||||
|  |     @Autowired | ||||||
|  |     private PersonRepository personRepository; | ||||||
|  | 
 | ||||||
|  |     @BeforeEach | ||||||
|  |     void insertPeople() { | ||||||
|  |         personRepository.saveAll(Arrays.asList( | ||||||
|  |           new Person(1L, "John", "Doe"), | ||||||
|  |           new Person(2L, "Jane", "Doe"), | ||||||
|  |           new Person(3L, "Ted", "Mosby") | ||||||
|  |         )); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @ParameterizedTest | ||||||
|  |     @ValueSource(strings = {"person", "PERSON", "Person"}) | ||||||
|  |     void givenPeopleAndUpperCaseNamingStrategy_whenQueryPersonUnquoted_thenResult(String tableName) { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from " + tableName); | ||||||
|  | 
 | ||||||
|  |         // Expected result | ||||||
|  |         List<Person> result = (List<Person>) query.getResultStream() | ||||||
|  |           .map(this::fromDatabase) | ||||||
|  |           .collect(Collectors.toList()); | ||||||
|  | 
 | ||||||
|  |         assertThat(result).isNotEmpty(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenPeopleAndUpperCaseNamingStrategy_whenQueryPersonQuotedUpperCase_thenException() { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from \"PERSON\""); | ||||||
|  | 
 | ||||||
|  |         // Unexpected result | ||||||
|  |         assertThrows(SQLGrammarException.class, query::getResultStream); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Test | ||||||
|  |     void givenPeopleAndUpperCaseNamingStrategy_whenQueryPersonQuotedLowerCase_thenResult() { | ||||||
|  |         Query query = entityManager.createNativeQuery("select * from \"person\""); | ||||||
|  | 
 | ||||||
|  |         // Unexpected result | ||||||
|  |         List<Person> result = (List<Person>) query.getResultStream() | ||||||
|  |           .map(this::fromDatabase) | ||||||
|  |           .collect(Collectors.toList()); | ||||||
|  | 
 | ||||||
|  |         assertThat(result).isNotEmpty(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Person fromDatabase(Object databaseRow) { | ||||||
|  |         Object[] typedDatabaseRow = (Object[]) databaseRow; | ||||||
|  | 
 | ||||||
|  |         return new Person( | ||||||
|  |           ((BigInteger) typedDatabaseRow[0]).longValue(), | ||||||
|  |           (String) typedDatabaseRow[1], | ||||||
|  |           (String) typedDatabaseRow[2] | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,9 @@ | |||||||
|  | spring.datasource.url=jdbc:postgresql://localhost:5432/quoted-lower-case-strategy | ||||||
|  | spring.datasource.username=postgres | ||||||
|  | spring.datasource.password=root | ||||||
|  | 
 | ||||||
|  | spring.jpa.hibernate.ddl-auto=create-drop | ||||||
|  | spring.jpa.hibernate.naming.physical-strategy=com.baeldung.namingstrategy.QuotedLowerCaseNamingStrategy | ||||||
|  | #spring.jpa.properties.javax.persistence.schema-generation.create-source=metadata | ||||||
|  | #spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create | ||||||
|  | #spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=upper-case-naming-strategy-ddl.sql | ||||||
| @ -0,0 +1,9 @@ | |||||||
|  | spring.datasource.url=jdbc:h2:mem:quoted-lower-case-strategy | ||||||
|  | spring.datasource.username=sa | ||||||
|  | spring.datasource.password= | ||||||
|  | 
 | ||||||
|  | spring.jpa.hibernate.ddl-auto=create-drop | ||||||
|  | spring.jpa.hibernate.naming.physical-strategy=com.baeldung.namingstrategy.QuotedLowerCaseNamingStrategy | ||||||
|  | #spring.jpa.properties.javax.persistence.schema-generation.create-source=metadata | ||||||
|  | #spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create | ||||||
|  | #spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=upper-case-naming-strategy-ddl.sql | ||||||
| @ -0,0 +1,9 @@ | |||||||
|  | spring.datasource.url=jdbc:postgresql://localhost:5432/quoted-upper-case-strategy | ||||||
|  | spring.datasource.username=postgres | ||||||
|  | spring.datasource.password=root | ||||||
|  | 
 | ||||||
|  | spring.jpa.hibernate.ddl-auto=create-drop | ||||||
|  | spring.jpa.hibernate.naming.physical-strategy=com.baeldung.namingstrategy.QuotedUpperCaseNamingStrategy | ||||||
|  | #spring.jpa.properties.javax.persistence.schema-generation.create-source=metadata | ||||||
|  | #spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create | ||||||
|  | #spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=upper-case-naming-strategy-ddl.sql | ||||||
| @ -0,0 +1,9 @@ | |||||||
|  | spring.datasource.url=jdbc:h2:mem:quoted-upper-case-strategy | ||||||
|  | spring.datasource.username=sa | ||||||
|  | spring.datasource.password= | ||||||
|  | 
 | ||||||
|  | spring.jpa.hibernate.ddl-auto=create-drop | ||||||
|  | spring.jpa.hibernate.naming.physical-strategy=com.baeldung.namingstrategy.QuotedUpperCaseNamingStrategy | ||||||
|  | #spring.jpa.properties.javax.persistence.schema-generation.create-source=metadata | ||||||
|  | #spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create | ||||||
|  | #spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=upper-case-naming-strategy-ddl.sql | ||||||
| @ -0,0 +1,9 @@ | |||||||
|  | spring.datasource.url=jdbc:postgresql://localhost:5432/spring-strategy | ||||||
|  | spring.datasource.username=postgres | ||||||
|  | spring.datasource.password=root | ||||||
|  | 
 | ||||||
|  | spring.jpa.hibernate.ddl-auto=create-drop | ||||||
|  | spring.jpa.hibernate.naming.physical-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy | ||||||
|  | #spring.jpa.properties.javax.persistence.schema-generation.create-source=metadata | ||||||
|  | #spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create | ||||||
|  | #spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=default-naming-strategy-ddl.sql | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user