diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..c2a369a1b3 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,17 @@ +language: java + +install: travis_wait 40 mvn -q clean install -Dgib.enabled=true + +jdk: + - oraclejdk8 + +sudo: false +addons: + apt: + packages: + - oracle-java8-installer + +cache: + directories: + - .autoconf + - $HOME/.m2 \ No newline at end of file diff --git a/JGit/README.md b/JGit/README.md new file mode 100644 index 0000000000..5c65f1101b --- /dev/null +++ b/JGit/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [A Guide to JGit](http://www.baeldung.com/jgit) diff --git a/algorithms/README.md b/algorithms/README.md new file mode 100644 index 0000000000..42f696d9be --- /dev/null +++ b/algorithms/README.md @@ -0,0 +1,4 @@ +## Relevant articles: + +- [Dijkstra Algorithm in Java](http://www.baeldung.com/java-dijkstra) +- [Introduction to Cobertura](http://www.baeldung.com/cobertura) diff --git a/algorithms/pom.xml b/algorithms/pom.xml index 0c85a19534..f72457650a 100644 --- a/algorithms/pom.xml +++ b/algorithms/pom.xml @@ -41,4 +41,23 @@ - \ No newline at end of file + + + + org.codehaus.mojo + cobertura-maven-plugin + 2.7 + + + + com/baeldung/algorithms/dijkstra/* + + + com/baeldung/algorithms/dijkstra/* + + + + + + + diff --git a/apache-bval/README.md b/apache-bval/README.md new file mode 100644 index 0000000000..80ea149993 --- /dev/null +++ b/apache-bval/README.md @@ -0,0 +1,2 @@ +### Relevant Articles: +- [Intro to Apache BVal](http://www.baeldung.com/apache-bval) diff --git a/apache-bval/pom.xml b/apache-bval/pom.xml new file mode 100644 index 0000000000..5d556af56f --- /dev/null +++ b/apache-bval/pom.xml @@ -0,0 +1,51 @@ + + 4.0.0 + apache-bval + apache-bval + 0.0.1-SNAPSHOT + + + + org.apache.bval + bval-jsr + ${bval.version} + + + javax.validation + validation-api + 1.1.0.Final + + + org.apache.bval + bval-extras + ${bval.version} + + + + junit + junit + ${junit.version} + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + + + 3.6.0 + 4.12 + 1.1.2 + + \ No newline at end of file diff --git a/apache-bval/src/main/java/com/baeldung/model/User.java b/apache-bval/src/main/java/com/baeldung/model/User.java new file mode 100644 index 0000000000..477136ddb4 --- /dev/null +++ b/apache-bval/src/main/java/com/baeldung/model/User.java @@ -0,0 +1,120 @@ +package com.baeldung.model; + +import java.io.File; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +import org.apache.bval.constraints.Email; +import org.apache.bval.constraints.NotEmpty; +import org.apache.bval.extras.constraints.checkdigit.IBAN; +import org.apache.bval.extras.constraints.creditcard.Visa; +import org.apache.bval.extras.constraints.file.Directory; +import org.apache.bval.extras.constraints.net.InetAddress; + +import com.baeldung.validation.Password; + +public class User { + @NotNull + @Email + private String email; + + @NotEmpty + @Password + private String password; + + @Size(min = 1, max = 20) + private String name; + + @Min(18) + private int age; + + @Visa + private String cardNumber = ""; + + @IBAN + private String iban = ""; + + @InetAddress + private String website = ""; + + @Directory + private File mainDirectory=new File("."); + + public User() { + } + + public User(String email, String password, String name, int age) { + super(); + this.email = email; + this.password = password; + this.name = name; + this.age = age; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getCardNumber() { + return cardNumber; + } + + public void setCardNumber(String cardNumber) { + this.cardNumber = cardNumber; + } + + public String getIban() { + return iban; + } + + public void setIban(String iban) { + this.iban = iban; + } + + public String getWebsite() { + return website; + } + + public void setWebsite(String website) { + this.website = website; + } + + public File getMainDirectory() { + return mainDirectory; + } + + public void setMainDirectory(File mainDirectory) { + this.mainDirectory = mainDirectory; + } + +} diff --git a/apache-bval/src/main/java/com/baeldung/validation/Password.java b/apache-bval/src/main/java/com/baeldung/validation/Password.java new file mode 100644 index 0000000000..4ae06b2fb0 --- /dev/null +++ b/apache-bval/src/main/java/com/baeldung/validation/Password.java @@ -0,0 +1,25 @@ +package com.baeldung.validation; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; + +import static java.lang.annotation.ElementType.*; + +@Constraint(validatedBy = { PasswordValidator.class }) +@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER }) +@Retention(RetentionPolicy.RUNTIME) +public @interface Password { + String message() default "Invalid password"; + + Class[] groups() default {}; + + Class[] payload() default {}; + + int length() default 6; + + int nonAlpha() default 1; +} diff --git a/apache-bval/src/main/java/com/baeldung/validation/PasswordValidator.java b/apache-bval/src/main/java/com/baeldung/validation/PasswordValidator.java new file mode 100644 index 0000000000..19038d04d5 --- /dev/null +++ b/apache-bval/src/main/java/com/baeldung/validation/PasswordValidator.java @@ -0,0 +1,35 @@ +package com.baeldung.validation; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +public class PasswordValidator implements ConstraintValidator { + + private int length; + private int nonAlpha; + + @Override + public void initialize(Password password) { + this.length = password.length(); + this.nonAlpha = password.nonAlpha(); + + } + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + if (value.length() < length) { + return false; + } + int nonAlphaNr = 0; + for (int i = 0; i < value.length(); i++) { + if (!Character.isLetterOrDigit(value.charAt(i))) { + nonAlphaNr++; + } + } + if (nonAlphaNr < nonAlpha) { + return false; + } + return true; + } + +} diff --git a/apache-bval/src/test/java/com/baeldung/validation/ValidationTest.java b/apache-bval/src/test/java/com/baeldung/validation/ValidationTest.java new file mode 100644 index 0000000000..cd58d4460a --- /dev/null +++ b/apache-bval/src/test/java/com/baeldung/validation/ValidationTest.java @@ -0,0 +1,97 @@ +package com.baeldung.validation; + +import java.io.File; +import java.util.Set; + +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; + +import org.apache.bval.jsr.ApacheValidationProvider; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import static org.junit.Assert.*; + +import com.baeldung.model.User; + +public class ValidationTest { + private static ValidatorFactory validatorFactory; + private static Validator validator; + + @BeforeClass + public static void setup() { + validatorFactory = Validation.byProvider(ApacheValidationProvider.class) + .configure() + .buildValidatorFactory(); + validator = validatorFactory.getValidator(); + } + + @Test + public void givenUser_whenValidate_thenValidationViolations() { + User user = new User("ana@yahoo.com", "pass", "nameTooLong_______________", 15); + + Set> violations = validator.validate(user); + assertTrue("no violations", violations.size() > 0); + } + + @Test + public void givenInvalidAge_whenValidateProperty_thenConstraintViolation() { + User user = new User("ana@yahoo.com", "pass", "Ana", 12); + + Set> propertyViolations = validator.validateProperty(user, "age"); + assertEquals("size is not 1", 1, propertyViolations.size()); + } + + @Test + public void givenValidAge_whenValidateValue_thenNoConstraintViolation() { + User user = new User("ana@yahoo.com", "pass", "Ana", 18); + + Set> valueViolations = validator.validateValue(User.class, "age", 20); + assertEquals("size is not 0", 0, valueViolations.size()); + } + + @Test + public void whenValidateNonJSR_thenCorrect() { + User user = new User("ana@yahoo.com", "pass", "Ana", 20); + user.setCardNumber("1234"); + user.setIban("1234"); + user.setWebsite("10.0.2.50"); + user.setMainDirectory(new File(".")); + + Set> violations = validator.validateProperty(user, "iban"); + assertEquals("size is not 1", 1, violations.size()); + + violations = validator.validateProperty(user, "website"); + assertEquals("size is not 0", 0, violations.size()); + + violations = validator.validateProperty(user, "mainDirectory"); + assertEquals("size is not 0", 0, violations.size()); + } + + @Test + public void givenInvalidPassword_whenValidatePassword_thenConstraintViolation() { + User user = new User("ana@yahoo.com", "password", "Ana", 20); + Set> violations = validator.validateProperty(user, "password"); + assertEquals("message incorrect", "Invalid password", violations.iterator() + .next() + .getMessage()); + } + + @Test + public void givenValidPassword_whenValidatePassword_thenNoConstraintViolation() { + User user = new User("ana@yahoo.com", "password#", "Ana", 20); + + Set> violations = validator.validateProperty(user, "password"); + assertEquals("size is not 0", 0, violations.size()); + } + + @AfterClass + public static void close() { + if (validatorFactory != null) { + validatorFactory.close(); + } + } +} diff --git a/apache-poi/README.md b/apache-poi/README.md index cef6810c97..10fe8ba2e7 100644 --- a/apache-poi/README.md +++ b/apache-poi/README.md @@ -1,2 +1,3 @@ ### Relevant Articles: - [Microsoft Word Processing in Java with Apache POI](http://www.baeldung.com/java-microsoft-word-with-apache-poi) +- [Working with Microsoft Excel in Java](http://www.baeldung.com/java-microsoft-excel) diff --git a/apache-poi/pom.xml b/apache-poi/pom.xml index d94b2e2ad1..d8a2cc72e0 100644 --- a/apache-poi/pom.xml +++ b/apache-poi/pom.xml @@ -9,6 +9,7 @@ 3.6.0 4.12 3.15 + 1.0.6 @@ -37,5 +38,10 @@ poi-ooxml ${poi.version} + + org.jxls + jxls-jexcel + ${jexcel.version} + diff --git a/spring-mvc-java/src/main/java/com/baeldung/excel/JExcelHelper.java b/apache-poi/src/main/java/com/baeldung/jexcel/JExcelHelper.java similarity index 79% rename from spring-mvc-java/src/main/java/com/baeldung/excel/JExcelHelper.java rename to apache-poi/src/main/java/com/baeldung/jexcel/JExcelHelper.java index d0e33bf471..4ad3fc766c 100644 --- a/spring-mvc-java/src/main/java/com/baeldung/excel/JExcelHelper.java +++ b/apache-poi/src/main/java/com/baeldung/jexcel/JExcelHelper.java @@ -1,24 +1,21 @@ -package com.baeldung.excel; +package com.baeldung.jexcel; -import jxl.Sheet; -import jxl.Workbook; -import jxl.format.Colour; +import jxl.*; +import java.util.Map; +import java.util.HashMap; +import java.util.ArrayList; +import java.util.List; import jxl.read.biff.BiffException; -import jxl.write.*; -import jxl.write.Number; -import org.springframework.stereotype.Service; - import java.io.File; import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; +import jxl.write.*; +import jxl.write.Number; +import jxl.format.Colour; -@Service public class JExcelHelper { - public Map> readJExcel(String fileLocation) throws IOException, BiffException { - Map> data = new HashMap<>(); + public Map> readJExcel(String fileLocation) throws IOException, BiffException { + Map> data = new HashMap<>(); Workbook workbook = Workbook.getWorkbook(new File(fileLocation)); Sheet sheet = workbook.getSheet(0); @@ -26,7 +23,7 @@ public class JExcelHelper { int columns = sheet.getColumns(); for (int i = 0; i < rows; i++) { - data.put(i, new ArrayList<>()); + data.put(i, new ArrayList()); for (int j = 0; j < columns; j++) { data.get(i).add(sheet.getCell(j, i).getContents()); } @@ -65,12 +62,7 @@ public class JExcelHelper { sheet.addCell(cellLabel); Number cellNumber = new Number(1, 2, 20, cellFormat); sheet.addCell(cellNumber); - - cellLabel = new Label(0, 3, "Ana Johnson", cellFormat); - sheet.addCell(cellLabel); - cellNumber = new Number(1, 3, 30, cellFormat); - sheet.addCell(cellNumber); - + workbook.write(); } finally { if (workbook != null) { diff --git a/apache-poi/src/main/java/com/baeldung/poi/excel/ExcelPOIHelper.java b/apache-poi/src/main/java/com/baeldung/poi/excel/ExcelPOIHelper.java new file mode 100644 index 0000000000..b6b0cbef20 --- /dev/null +++ b/apache-poi/src/main/java/com/baeldung/poi/excel/ExcelPOIHelper.java @@ -0,0 +1,128 @@ +package com.baeldung.poi.excel; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.apache.poi.xssf.usermodel.XSSFFont; +import org.apache.poi.ss.usermodel.DateUtil; +import org.apache.poi.ss.usermodel.FillPatternType; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; +import java.util.HashMap; +import java.util.ArrayList; +import java.util.List; + +public class ExcelPOIHelper { + + public Map> readExcel(String fileLocation) throws IOException { + + Map> data = new HashMap<>(); + FileInputStream file = new FileInputStream(new File(fileLocation)); + Workbook workbook = new XSSFWorkbook(file); + Sheet sheet = workbook.getSheetAt(0); + int i = 0; + for (Row row : sheet) { + data.put(i, new ArrayList()); + for (Cell cell : row) { + switch (cell.getCellTypeEnum()) { + case STRING: + data.get(i) + .add(cell.getRichStringCellValue() + .getString()); + break; + case NUMERIC: + if (DateUtil.isCellDateFormatted(cell)) { + data.get(i) + .add(cell.getDateCellValue() + ""); + } else { + data.get(i) + .add((int)cell.getNumericCellValue() + ""); + } + break; + case BOOLEAN: + data.get(i) + .add(cell.getBooleanCellValue() + ""); + break; + case FORMULA: + data.get(i) + .add(cell.getCellFormula() + ""); + break; + default: + data.get(i) + .add(" "); + } + } + i++; + } + if (workbook != null){ + workbook.close(); + } + return data; + } + + public void writeExcel() throws IOException { + Workbook workbook = new XSSFWorkbook(); + + try { + Sheet sheet = workbook.createSheet("Persons"); + sheet.setColumnWidth(0, 6000); + sheet.setColumnWidth(1, 4000); + + Row header = sheet.createRow(0); + + CellStyle headerStyle = workbook.createCellStyle(); + + headerStyle.setFillForegroundColor(IndexedColors.LIGHT_BLUE.getIndex()); + headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); + + XSSFFont font = ((XSSFWorkbook) workbook).createFont(); + font.setFontName("Arial"); + font.setFontHeightInPoints((short) 16); + font.setBold(true); + headerStyle.setFont(font); + + Cell headerCell = header.createCell(0); + headerCell.setCellValue("Name"); + headerCell.setCellStyle(headerStyle); + + headerCell = header.createCell(1); + headerCell.setCellValue("Age"); + headerCell.setCellStyle(headerStyle); + + CellStyle style = workbook.createCellStyle(); + style.setWrapText(true); + + Row row = sheet.createRow(2); + Cell cell = row.createCell(0); + cell.setCellValue("John Smith"); + cell.setCellStyle(style); + + cell = row.createCell(1); + cell.setCellValue(20); + cell.setCellStyle(style); + + File currDir = new File("."); + String path = currDir.getAbsolutePath(); + String fileLocation = path.substring(0, path.length() - 1) + "temp.xlsx"; + + FileOutputStream outputStream = new FileOutputStream(fileLocation); + workbook.write(outputStream); + } finally { + if (workbook != null) { + + workbook.close(); + + } + } + } + +} \ No newline at end of file diff --git a/apache-poi/src/test/java/com/baeldung/jexcel/JExcelTest.java b/apache-poi/src/test/java/com/baeldung/jexcel/JExcelTest.java new file mode 100644 index 0000000000..8ee465be34 --- /dev/null +++ b/apache-poi/src/test/java/com/baeldung/jexcel/JExcelTest.java @@ -0,0 +1,56 @@ +package com.baeldung.jexcel; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import jxl.read.biff.BiffException; +import java.util.Map; +import java.util.ArrayList; +import java.util.List; + +import com.baeldung.jexcel.JExcelHelper; + +import jxl.write.WriteException; +import jxl.read.biff.BiffException; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.junit.Before; + +public class JExcelTest { + + private JExcelHelper jExcelHelper; + private static String FILE_NAME = "temp.xls"; + private String fileLocation; + + @Before + public void generateExcelFile() throws IOException, WriteException { + + File currDir = new File("."); + String path = currDir.getAbsolutePath(); + fileLocation = path.substring(0, path.length() - 1) + FILE_NAME; + + jExcelHelper = new JExcelHelper(); + jExcelHelper.writeJExcel(); + + } + + @Test + public void whenParsingJExcelFile_thenCorrect() throws IOException, BiffException { + Map> data = jExcelHelper.readJExcel(fileLocation); + + assertEquals("Name", data.get(0) + .get(0)); + assertEquals("Age", data.get(0) + .get(1)); + + assertEquals("John Smith", data.get(2) + .get(0)); + assertEquals("20", data.get(2) + .get(1)); + } + +} \ No newline at end of file diff --git a/apache-poi/src/test/java/com/baeldung/poi/excel/ExcelTest.java b/apache-poi/src/test/java/com/baeldung/poi/excel/ExcelTest.java new file mode 100644 index 0000000000..34fa64dd94 --- /dev/null +++ b/apache-poi/src/test/java/com/baeldung/poi/excel/ExcelTest.java @@ -0,0 +1,53 @@ +package com.baeldung.poi.excel; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import jxl.read.biff.BiffException; +import java.util.Map; +import java.util.ArrayList; +import java.util.List; + +import com.baeldung.poi.excel.ExcelPOIHelper; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.junit.Before; + +public class ExcelTest { + + private ExcelPOIHelper excelPOIHelper; + private static String FILE_NAME = "temp.xlsx"; + private String fileLocation; + + @Before + public void generateExcelFile() throws IOException { + + File currDir = new File("."); + String path = currDir.getAbsolutePath(); + fileLocation = path.substring(0, path.length() - 1) + FILE_NAME; + + excelPOIHelper = new ExcelPOIHelper(); + excelPOIHelper.writeExcel(); + + } + + @Test + public void whenParsingPOIExcelFile_thenCorrect() throws IOException { + Map> data = excelPOIHelper.readExcel(fileLocation); + + assertEquals("Name", data.get(0) + .get(0)); + assertEquals("Age", data.get(0) + .get(1)); + + assertEquals("John Smith", data.get(1) + .get(0)); + assertEquals("20", data.get(1) + .get(1)); + } + +} \ No newline at end of file diff --git a/apache-poi/temp.xls b/apache-poi/temp.xls new file mode 100644 index 0000000000..1fad76d88d Binary files /dev/null and b/apache-poi/temp.xls differ diff --git a/apache-poi/temp.xlsx b/apache-poi/temp.xlsx new file mode 100644 index 0000000000..5281b2c4de Binary files /dev/null and b/apache-poi/temp.xlsx differ diff --git a/apache-solrj/pom.xml b/apache-solrj/pom.xml new file mode 100644 index 0000000000..74daeae55c --- /dev/null +++ b/apache-solrj/pom.xml @@ -0,0 +1,50 @@ + + 4.0.0 + com.baeldung + apache-solrj + 0.0.1-SNAPSHOT + jar + apache-solrj + + + 4.12 + 2.19.1 + + + + + org.apache.solr + solr-solrj + 6.4.0 + + + junit + junit + ${junit.version} + test + + + + + + + maven-compiler-plugin + 2.3.2 + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + 1.8 + 1.8 + + **/*IntegrationTest.java + **/*LiveTest.java + + + + + + \ No newline at end of file diff --git a/apache-solrj/src/main/java/com/baeldung/solrjava/SolrJavaIntegration.java b/apache-solrj/src/main/java/com/baeldung/solrjava/SolrJavaIntegration.java new file mode 100644 index 0000000000..f2d21f0993 --- /dev/null +++ b/apache-solrj/src/main/java/com/baeldung/solrjava/SolrJavaIntegration.java @@ -0,0 +1,43 @@ +package com.baeldung.solrjava; + +import java.io.IOException; + +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.client.solrj.impl.HttpSolrClient; +import org.apache.solr.client.solrj.impl.XMLResponseParser; +import org.apache.solr.common.SolrInputDocument; + +public class SolrJavaIntegration { + + private HttpSolrClient solrClient; + + public SolrJavaIntegration(String clientUrl) { + + solrClient = new HttpSolrClient.Builder(clientUrl).build(); + solrClient.setParser(new XMLResponseParser()); + } + + public void addSolrDocument(String documentId, String itemName, String itemPrice) throws SolrServerException, IOException { + + SolrInputDocument document = new SolrInputDocument(); + document.addField("id", documentId); + document.addField("name", itemName); + document.addField("price", itemPrice); + solrClient.add(document); + solrClient.commit(); + } + + public void deleteSolrDocument(String documentId) throws SolrServerException, IOException { + + solrClient.deleteById(documentId); + solrClient.commit(); + } + + protected HttpSolrClient getSolrClient() { + return solrClient; + } + + protected void setSolrClient(HttpSolrClient solrClient) { + this.solrClient = solrClient; + } +} diff --git a/apache-solrj/src/test/java/com/baeldung/solrjava/SolrJavaIntegrationTest.java b/apache-solrj/src/test/java/com/baeldung/solrjava/SolrJavaIntegrationTest.java new file mode 100644 index 0000000000..22f9eae8ee --- /dev/null +++ b/apache-solrj/src/test/java/com/baeldung/solrjava/SolrJavaIntegrationTest.java @@ -0,0 +1,58 @@ +package com.baeldung.solrjava; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; + +import org.apache.solr.client.solrj.SolrQuery; +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.client.solrj.response.QueryResponse; +import org.apache.solr.common.SolrDocument; +import org.apache.solr.common.SolrDocumentList; +import org.junit.Before; +import org.junit.Test; + +public class SolrJavaIntegrationTest { + + private SolrJavaIntegration solrJavaIntegration; + + @Before + public void setUp() throws Exception { + + solrJavaIntegration = new SolrJavaIntegration("http://localhost:8983/solr/bigboxstore"); + solrJavaIntegration.addSolrDocument("123456", "Kenmore Dishwasher", "599.99"); + } + + @Test + public void whenAdd_thenVerifyAdded() throws SolrServerException, IOException { + + SolrQuery query = new SolrQuery(); + query.set("q", "id:123456"); + QueryResponse response = null; + + response = solrJavaIntegration.getSolrClient().query(query); + + SolrDocumentList docList = response.getResults(); + assertEquals(docList.getNumFound(), 1); + + for (SolrDocument doc : docList) { + assertEquals((String) doc.getFieldValue("id"), "123456"); + assertEquals((Double) doc.getFieldValue("price"), (Double) 599.99); + } + } + + @Test + public void whenDelete_thenVerifyDeleted() throws SolrServerException, IOException { + + solrJavaIntegration.deleteSolrDocument("123456"); + + SolrQuery query = new SolrQuery(); + query.set("q", "id:123456"); + QueryResponse response = null; + + response = solrJavaIntegration.getSolrClient().query(query); + + SolrDocumentList docList = response.getResults(); + assertEquals(docList.getNumFound(), 0); + } +} diff --git a/apache-thrift/README.md b/apache-thrift/README.md new file mode 100644 index 0000000000..d8b9195dcc --- /dev/null +++ b/apache-thrift/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Working with Apache Thrift](http://www.baeldung.com/apache-thrift) diff --git a/apache-thrift/src/main/java/com/baeldung/thrift/Application.java b/apache-thrift/src/main/java/com/baeldung/thrift/Application.java index 09d5cc74f3..3321a0927a 100644 --- a/apache-thrift/src/main/java/com/baeldung/thrift/Application.java +++ b/apache-thrift/src/main/java/com/baeldung/thrift/Application.java @@ -1,8 +1,10 @@ package com.baeldung.thrift; +import org.apache.thrift.transport.TTransportException; + public class Application { - public static void main(String[] args) { + public static void main(String[] args) throws TTransportException { CrossPlatformServiceServer server = new CrossPlatformServiceServer(); server.start(); } diff --git a/apache-thrift/src/main/java/com/baeldung/thrift/CrossPlatformServiceServer.java b/apache-thrift/src/main/java/com/baeldung/thrift/CrossPlatformServiceServer.java index 9a21512b52..32c7891ef2 100644 --- a/apache-thrift/src/main/java/com/baeldung/thrift/CrossPlatformServiceServer.java +++ b/apache-thrift/src/main/java/com/baeldung/thrift/CrossPlatformServiceServer.java @@ -6,25 +6,22 @@ import org.apache.thrift.server.TServer; import org.apache.thrift.server.TSimpleServer; import org.apache.thrift.transport.TServerSocket; import org.apache.thrift.transport.TServerTransport; +import org.apache.thrift.transport.TTransportException; public class CrossPlatformServiceServer { private TServer server; - public void start() { - try { - TServerTransport serverTransport = new TServerSocket(9090); - server = new TSimpleServer(new TServer.Args(serverTransport) - .processor(new CrossPlatformService.Processor<>(new CrossPlatformServiceImpl()))); + public void start() throws TTransportException { + TServerTransport serverTransport = new TServerSocket(9090); + server = new TSimpleServer(new TServer.Args(serverTransport) + .processor(new CrossPlatformService.Processor<>(new CrossPlatformServiceImpl()))); - System.out.print("Starting the server... "); + System.out.print("Starting the server... "); - server.serve(); + server.serve(); - System.out.println("done."); - } catch (Exception e) { - e.printStackTrace(); - } + System.out.println("done."); } public void stop() { diff --git a/apache-thrift/src/test/java/com/baeldung/thrift/CrossPlatformServiceTest.java b/apache-thrift/src/test/java/com/baeldung/thrift/CrossPlatformServiceTest.java index 8a7022a281..4ba9ef2914 100644 --- a/apache-thrift/src/test/java/com/baeldung/thrift/CrossPlatformServiceTest.java +++ b/apache-thrift/src/test/java/com/baeldung/thrift/CrossPlatformServiceTest.java @@ -1,5 +1,6 @@ package com.baeldung.thrift; +import org.apache.thrift.transport.TTransportException; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -11,7 +12,13 @@ public class CrossPlatformServiceTest { @Before public void setUp() { - new Thread(() -> server.start()).start(); + new Thread(() -> { + try { + server.start(); + } catch (TTransportException e) { + e.printStackTrace(); + } + }).start(); try { // wait for the server start up Thread.sleep(1000); diff --git a/apache-velocity/README.md b/apache-velocity/README.md new file mode 100644 index 0000000000..53c67f847e --- /dev/null +++ b/apache-velocity/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Introduction to Apache Velocity](http://www.baeldung.com/apache-velocity) diff --git a/apache-velocity/pom.xml b/apache-velocity/pom.xml new file mode 100644 index 0000000000..08f0e96a58 --- /dev/null +++ b/apache-velocity/pom.xml @@ -0,0 +1,101 @@ + + + 4.0.0 + com.baeldung + 0.1-SNAPSHOT + apache-velocity + + war + apache-velocity + + + 1.8 + 1.2 + 4.11 + 1.0.13 + 1.7.5 + 3.6.0 + 2.6 + 2.19.1 + 4.5.2 + 1.7 + 2.0 + + + + + junit + junit + ${junit.version} + test + + + org.apache.velocity + velocity + ${velocity-version} + + + org.apache.velocity + velocity-tools + ${velocity-tools-version} + + + org.slf4j + jcl-over-slf4j + ${jcl-over-slf4j.version} + + + ch.qos.logback + logback-classic + ${logback.version} + + + org.apache.httpcomponents + httpclient + ${org.apache.httpcomponents.version} + test + + + + apache-velocity + + + src/main/resources + true + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${jdk.version} + ${jdk.version} + + + + org.apache.maven.plugins + maven-war-plugin + ${maven-war-plugin.version} + + false + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + **/*LiveTest.java + + + + + + + + diff --git a/apache-velocity/src/main/java/com/baeldung/apache/velocity/model/Product.java b/apache-velocity/src/main/java/com/baeldung/apache/velocity/model/Product.java new file mode 100644 index 0000000000..c215223181 --- /dev/null +++ b/apache-velocity/src/main/java/com/baeldung/apache/velocity/model/Product.java @@ -0,0 +1,33 @@ +package com.baeldung.apache.velocity.model; + +public class Product { + + private String name; + private double price; + + public Product(String name, double price) { + this.name = name; + this.price = price; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public double getPrice() { + return price; + } + + public void setPrice(double price) { + this.price = price; + } + + @Override + public String toString() { + return "Product{" + "name='" + name + '\'' + ", price=" + price + '}'; + } +} diff --git a/apache-velocity/src/main/java/com/baeldung/apache/velocity/service/ProductService.java b/apache-velocity/src/main/java/com/baeldung/apache/velocity/service/ProductService.java new file mode 100644 index 0000000000..0a623d4d65 --- /dev/null +++ b/apache-velocity/src/main/java/com/baeldung/apache/velocity/service/ProductService.java @@ -0,0 +1,20 @@ +package com.baeldung.apache.velocity.service; + +import com.baeldung.apache.velocity.model.Product; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; +import java.util.List; + +public class ProductService { + + Logger logger = LoggerFactory.getLogger(ProductService.class); + + public List getProducts() { + logger.debug("Product service returning list of products"); + + return Arrays.asList(new Product("Laptop", 31000.00), new Product("Mobile", 16000.00), + new Product("Tablet", 15000.00), new Product("Camera", 23000.00)); + } +} diff --git a/apache-velocity/src/main/java/com/baeldung/apache/velocity/servlet/LayoutServlet.java b/apache-velocity/src/main/java/com/baeldung/apache/velocity/servlet/LayoutServlet.java new file mode 100644 index 0000000000..d4208a3880 --- /dev/null +++ b/apache-velocity/src/main/java/com/baeldung/apache/velocity/servlet/LayoutServlet.java @@ -0,0 +1,41 @@ +package com.baeldung.apache.velocity.servlet; + +import com.baeldung.apache.velocity.model.Product; +import com.baeldung.apache.velocity.service.ProductService; +import org.apache.velocity.Template; +import org.apache.velocity.context.Context; +import org.apache.velocity.tools.view.VelocityLayoutServlet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.List; + +public class LayoutServlet extends VelocityLayoutServlet { + ProductService service = new ProductService(); + + @Override + public Template handleRequest(HttpServletRequest request, HttpServletResponse response, Context context) { + + Logger logger= LoggerFactory.getLogger(LayoutServlet.class); + + List products = service.getProducts(); + + context.put("products", products); + + Template template = null; + + try { + template = getTemplate("templates/layoutdemo.vm"); + + response.setHeader("Template Returned", "Success"); + } catch (Exception e) { + logger.error("Error while reading the template ",e); + } + + return template; + + } + +} diff --git a/apache-velocity/src/main/java/com/baeldung/apache/velocity/servlet/ProductServlet.java b/apache-velocity/src/main/java/com/baeldung/apache/velocity/servlet/ProductServlet.java new file mode 100644 index 0000000000..60c9169fce --- /dev/null +++ b/apache-velocity/src/main/java/com/baeldung/apache/velocity/servlet/ProductServlet.java @@ -0,0 +1,40 @@ +package com.baeldung.apache.velocity.servlet; + +import com.baeldung.apache.velocity.model.Product; +import com.baeldung.apache.velocity.service.ProductService; +import org.apache.velocity.Template; +import org.apache.velocity.context.Context; +import org.apache.velocity.tools.view.VelocityViewServlet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.List; + +public class ProductServlet extends VelocityViewServlet { + + ProductService service = new ProductService(); + + @Override + public Template handleRequest(HttpServletRequest request, HttpServletResponse response, Context context) { + + Logger logger= LoggerFactory.getLogger(ProductServlet.class); + + List products = service.getProducts(); + + context.put("products", products); + + Template template = null; + + try { + template = getTemplate("templates/index.vm"); + response.setHeader("Template Returned", "Success"); + } catch (Exception e) { + logger.error("Error while reading the template ", e); + } + + return template; + + } +} diff --git a/apache-velocity/src/main/resources/logback.xml b/apache-velocity/src/main/resources/logback.xml new file mode 100644 index 0000000000..70a420a57a --- /dev/null +++ b/apache-velocity/src/main/resources/logback.xml @@ -0,0 +1,23 @@ + + + + + + + + %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apache-velocity/src/main/webapp/WEB-INF/velocity.properties b/apache-velocity/src/main/webapp/WEB-INF/velocity.properties new file mode 100644 index 0000000000..00e0b7e410 --- /dev/null +++ b/apache-velocity/src/main/webapp/WEB-INF/velocity.properties @@ -0,0 +1,4 @@ +resource.loader=webapp +webapp.resource.loader.class=org.apache.velocity.tools.view.WebappResourceLoader +webapp.resource.loader.path = . +webapp.resource.loader.cache = true \ No newline at end of file diff --git a/apache-velocity/src/main/webapp/WEB-INF/web.xml b/apache-velocity/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..95b41b36dd --- /dev/null +++ b/apache-velocity/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,49 @@ + + + + apache-velocity + + ProductServlet + com.baeldung.apache.velocity.servlet.ProductServlet + + + + LayoutServlet + com.baeldung.apache.velocity.servlet.LayoutServlet + + + velocityLayout + org.apache.velocity.tools.view.VelocityLayoutServlet + + + org.apache.velocity.properties + /WEB-INF/velocity.properties + + + + ProductServlet + / + + + + LayoutServlet + /layout + + + velocityLayout + *.vm + + + + + 30 + + + + + + index.html + + diff --git a/apache-velocity/src/main/webapp/fragments/footer.vm b/apache-velocity/src/main/webapp/fragments/footer.vm new file mode 100644 index 0000000000..41bb36ce5e --- /dev/null +++ b/apache-velocity/src/main/webapp/fragments/footer.vm @@ -0,0 +1,4 @@ +
+ @Copyright baeldung.com +
\ No newline at end of file diff --git a/apache-velocity/src/main/webapp/fragments/header.vm b/apache-velocity/src/main/webapp/fragments/header.vm new file mode 100644 index 0000000000..96700d3baf --- /dev/null +++ b/apache-velocity/src/main/webapp/fragments/header.vm @@ -0,0 +1,5 @@ +
+
+

Layout Demo Page

+
+
\ No newline at end of file diff --git a/apache-velocity/src/main/webapp/layout/Default.vm b/apache-velocity/src/main/webapp/layout/Default.vm new file mode 100644 index 0000000000..39a8b277a5 --- /dev/null +++ b/apache-velocity/src/main/webapp/layout/Default.vm @@ -0,0 +1,22 @@ + + + Velocity + + +
+ #parse("/fragments/header.vm") +
+ + +
+ + + $screen_content + +
+ +
+ #parse("/fragments/footer.vm") +
+ + \ No newline at end of file diff --git a/apache-velocity/src/main/webapp/templates/index.vm b/apache-velocity/src/main/webapp/templates/index.vm new file mode 100644 index 0000000000..0ca07caf42 --- /dev/null +++ b/apache-velocity/src/main/webapp/templates/index.vm @@ -0,0 +1,63 @@ + + + Online Electronic Store + + + + +
+

Today's Offers

+
+
+

$products.size() Products on Sale!

+
+ We are proud to offer these fine products + at these amazing prices. +
+
+ #set( $count = 1 ) + + + + + #foreach( $product in $products ) + + + + + + #set( $count = $count + 1 ) + #end +
Serial #Product NamePrice
$count)$product.getName()$product.getPrice()
+
+
+ + + diff --git a/apache-velocity/src/main/webapp/templates/layoutdemo.vm b/apache-velocity/src/main/webapp/templates/layoutdemo.vm new file mode 100644 index 0000000000..0626b655c9 --- /dev/null +++ b/apache-velocity/src/main/webapp/templates/layoutdemo.vm @@ -0,0 +1,27 @@ +#set( $layout = "layout.vm" ) +
+

Today's Offers

+
+
+

$products.size() Products on Sale!

+
+ We are proud to offer these fine products + at these amazing prices. +
+
+ #set( $count = 1 ) + + + + + #foreach( $product in $products ) + + + + + + #set( $count = $count + 1 ) + #end +
Serial #Product NamePrice
$count)$product.getName()$product.getPrice()
+
+
\ No newline at end of file diff --git a/apache-velocity/src/test/java/com/baeldung/apache/velocity/servlet/LayoutServletLiveTest.java b/apache-velocity/src/test/java/com/baeldung/apache/velocity/servlet/LayoutServletLiveTest.java new file mode 100644 index 0000000000..f1f166b119 --- /dev/null +++ b/apache-velocity/src/test/java/com/baeldung/apache/velocity/servlet/LayoutServletLiveTest.java @@ -0,0 +1,26 @@ +package com.baeldung.apache.velocity.servlet; + +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.DefaultHttpClient; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + + +public class LayoutServletLiveTest { + + @Test + public void whenRequestUsingHttpClient_thenCorrectResponse() throws Exception { + + HttpClient client = new DefaultHttpClient(); + HttpGet method= new HttpGet("http://localhost:8080/layout"); + + HttpResponse httpResponse = client.execute(method); + + assertEquals("Success", httpResponse.getHeaders("Template Returned")[0].getValue()); + + } + +} diff --git a/apache-velocity/src/test/java/com/baeldung/apache/velocity/servlet/ProductServletLiveTest.java b/apache-velocity/src/test/java/com/baeldung/apache/velocity/servlet/ProductServletLiveTest.java new file mode 100644 index 0000000000..397e575d4d --- /dev/null +++ b/apache-velocity/src/test/java/com/baeldung/apache/velocity/servlet/ProductServletLiveTest.java @@ -0,0 +1,24 @@ +package com.baeldung.apache.velocity.servlet; + +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.DefaultHttpClient; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class ProductServletLiveTest { + + @Test + public void whenRequestUsingHttpClient_thenCorrectResponse() throws Exception { + + HttpClient client = new DefaultHttpClient(); + HttpGet method= new HttpGet("http://localhost:8080/"); + + HttpResponse httpResponse = client.execute(method); + + assertEquals("Success", httpResponse.getHeaders("Template Returned")[0].getValue()); + + } +} diff --git a/aws/pom.xml b/aws/pom.xml index f3ae672a2f..681b76cfd4 100644 --- a/aws/pom.xml +++ b/aws/pom.xml @@ -7,17 +7,36 @@ jar aws + + 2.5 + 1.3.0 + 1.1.0 + 2.8.0 + + com.amazonaws aws-lambda-java-core - 1.1.0 + ${aws-lambda-java-core.version} + + + + com.amazonaws + aws-lambda-java-events + ${aws-lambda-java-events.version} commons-io commons-io - 2.5 + ${commons-io.version} + + + + com.google.code.gson + gson + ${gson.version} @@ -26,7 +45,7 @@ org.apache.maven.plugins maven-shade-plugin - 2.3 + 3.0.0 false diff --git a/aws/src/main/java/com/baeldung/lambda/dynamodb/SavePersonHandler.java b/aws/src/main/java/com/baeldung/lambda/dynamodb/SavePersonHandler.java new file mode 100644 index 0000000000..625da62efd --- /dev/null +++ b/aws/src/main/java/com/baeldung/lambda/dynamodb/SavePersonHandler.java @@ -0,0 +1,49 @@ +package com.baeldung.lambda.dynamodb; + +import com.amazonaws.regions.Region; +import com.amazonaws.regions.Regions; +import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; +import com.amazonaws.services.dynamodbv2.document.DynamoDB; +import com.amazonaws.services.dynamodbv2.document.Item; +import com.amazonaws.services.dynamodbv2.document.PutItemOutcome; +import com.amazonaws.services.dynamodbv2.document.spec.PutItemSpec; +import com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException; +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.baeldung.lambda.dynamodb.bean.PersonRequest; +import com.baeldung.lambda.dynamodb.bean.PersonResponse; + +public class SavePersonHandler implements RequestHandler { + + private DynamoDB dynamoDb; + + private String DYNAMODB_TABLE_NAME = "Person"; + private Regions REGION = Regions.US_WEST_2; + + public PersonResponse handleRequest(PersonRequest personRequest, Context context) { + this.initDynamoDbClient(); + + persistData(personRequest); + + PersonResponse personResponse = new PersonResponse(); + personResponse.setMessage("Saved Successfully!!!"); + return personResponse; + } + + private PutItemOutcome persistData(PersonRequest personRequest) throws ConditionalCheckFailedException { + return this.dynamoDb.getTable(DYNAMODB_TABLE_NAME) + .putItem( + new PutItemSpec().withItem(new Item() + .withNumber("id", personRequest.getId()) + .withString("firstName", personRequest.getFirstName()) + .withString("lastName", personRequest.getLastName()) + .withNumber("age", personRequest.getAge()) + .withString("address", personRequest.getAddress()))); + } + + private void initDynamoDbClient() { + AmazonDynamoDBClient client = new AmazonDynamoDBClient(); + client.setRegion(Region.getRegion(REGION)); + this.dynamoDb = new DynamoDB(client); + } +} diff --git a/aws/src/main/java/com/baeldung/lambda/dynamodb/bean/PersonRequest.java b/aws/src/main/java/com/baeldung/lambda/dynamodb/bean/PersonRequest.java new file mode 100644 index 0000000000..0c0706e676 --- /dev/null +++ b/aws/src/main/java/com/baeldung/lambda/dynamodb/bean/PersonRequest.java @@ -0,0 +1,67 @@ +package com.baeldung.lambda.dynamodb.bean; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +public class PersonRequest { + private int id; + private String firstName; + private String lastName; + private int age; + private String address; + + public static void main(String[] args) { + PersonRequest personRequest = new PersonRequest(); + personRequest.setId(1); + personRequest.setFirstName("John"); + personRequest.setLastName("Doe"); + personRequest.setAge(30); + personRequest.setAddress("United States"); + System.out.println(personRequest); + } + + public String toString() { + final Gson gson = new GsonBuilder().setPrettyPrinting().create(); + return gson.toJson(this); + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } +} diff --git a/aws/src/main/java/com/baeldung/lambda/dynamodb/bean/PersonResponse.java b/aws/src/main/java/com/baeldung/lambda/dynamodb/bean/PersonResponse.java new file mode 100644 index 0000000000..a61294ddea --- /dev/null +++ b/aws/src/main/java/com/baeldung/lambda/dynamodb/bean/PersonResponse.java @@ -0,0 +1,20 @@ +package com.baeldung.lambda.dynamodb.bean; + +import com.google.gson.Gson; + +public class PersonResponse { + private String message; + + public String toString() { + final Gson gson = new Gson(); + return gson.toJson(this); + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/core-java-9/README.md b/core-java-9/README.md index 1b44239e40..53ad79e59c 100644 --- a/core-java-9/README.md +++ b/core-java-9/README.md @@ -6,3 +6,5 @@ ### Relevant Articles: - [Java 9 Stream API Improvements](http://www.baeldung.com/java-9-stream-api) +- [Java 9 Convenience Factory Methods for Collections](http://www.baeldung.com/java-9-collections-factory-methods) +- [New Stream Collectors in Java 9](http://www.baeldung.com/java9-stream-collectors) diff --git a/core-java-9/pom.xml b/core-java-9/pom.xml index 9d1ff29ef7..23473ff161 100644 --- a/core-java-9/pom.xml +++ b/core-java-9/pom.xml @@ -21,6 +21,11 @@ slf4j-api ${org.slf4j.version} + + ch.qos.logback + logback-classic + ${ch.qos.logback.version} + org.hamcrest @@ -76,9 +81,9 @@ 1.7.21 - + 1.2.1 - 3.6-jigsaw-SNAPSHOT + 3.6.0 2.19.1 diff --git a/core-java-9/src/test/java/com/baeldung/java9/process/ProcessAPIEnhancementsTest.java b/core-java-9/src/test/java/com/baeldung/java9/process/ProcessAPIEnhancementsTest.java new file mode 100644 index 0000000000..1129a10d17 --- /dev/null +++ b/core-java-9/src/test/java/com/baeldung/java9/process/ProcessAPIEnhancementsTest.java @@ -0,0 +1,133 @@ +package com.baeldung.java9.process; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Stream; + +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Created by sanaulla on 2/23/2017. + */ + +public class ProcessAPIEnhancementsTest { + + Logger log = LoggerFactory.getLogger(ProcessAPIEnhancementsTest.class); + + @Test + public void givenCurrentProcess_whenInvokeGetInfo_thenSuccess() throws IOException { + ProcessHandle processHandle = ProcessHandle.current(); + ProcessHandle.Info processInfo = processHandle.info(); + assertNotNull(processHandle.getPid()); + assertEquals(false, processInfo.arguments() + .isPresent()); + assertEquals(true, processInfo.command() + .isPresent()); + assertTrue(processInfo.command() + .get() + .contains("java")); + + assertEquals(true, processInfo.startInstant() + .isPresent()); + assertEquals(true, processInfo.totalCpuDuration() + .isPresent()); + assertEquals(true, processInfo.user() + .isPresent()); + } + + @Test + public void givenSpawnProcess_whenInvokeGetInfo_thenSuccess() throws IOException { + + String javaCmd = ProcessUtils.getJavaCmd() + .getAbsolutePath(); + ProcessBuilder processBuilder = new ProcessBuilder(javaCmd, "-version"); + Process process = processBuilder.inheritIO() + .start(); + ProcessHandle processHandle = process.toHandle(); + ProcessHandle.Info processInfo = processHandle.info(); + assertNotNull(processHandle.getPid()); + assertEquals(false, processInfo.arguments() + .isPresent()); + assertEquals(true, processInfo.command() + .isPresent()); + assertTrue(processInfo.command() + .get() + .contains("java")); + assertEquals(true, processInfo.startInstant() + .isPresent()); + assertEquals(true, processInfo.totalCpuDuration() + .isPresent()); + assertEquals(true, processInfo.user() + .isPresent()); + } + + @Test + public void givenLiveProcesses_whenInvokeGetInfo_thenSuccess() { + Stream liveProcesses = ProcessHandle.allProcesses(); + liveProcesses.filter(ProcessHandle::isAlive) + .forEach(ph -> { + assertNotNull(ph.getPid()); + assertEquals(true, ph.info() + .command() + .isPresent()); + assertEquals(true, ph.info() + .startInstant() + .isPresent()); + assertEquals(true, ph.info() + .totalCpuDuration() + .isPresent()); + assertEquals(true, ph.info() + .user() + .isPresent()); + }); + } + + @Test + public void givenProcess_whenGetChildProcess_thenSuccess() throws IOException { + int childProcessCount = 5; + for (int i = 0; i < childProcessCount; i++) { + String javaCmd = ProcessUtils.getJavaCmd() + .getAbsolutePath(); + ProcessBuilder processBuilder + = new ProcessBuilder(javaCmd, "-version"); + processBuilder.inheritIO().start(); + } + + Stream children = ProcessHandle.current() + .children(); + children.filter(ProcessHandle::isAlive) + .forEach(ph -> log.info("PID: {}, Cmd: {}", ph.getPid(), ph.info() + .command())); + Stream descendants = ProcessHandle.current() + .descendants(); + descendants.filter(ProcessHandle::isAlive) + .forEach(ph -> log.info("PID: {}, Cmd: {}", ph.getPid(), ph.info() + .command())); + } + + @Test + public void givenProcess_whenAddExitCallback_thenSuccess() throws Exception { + String javaCmd = ProcessUtils.getJavaCmd() + .getAbsolutePath(); + ProcessBuilder processBuilder + = new ProcessBuilder(javaCmd, "-version"); + Process process = processBuilder.inheritIO() + .start(); + ProcessHandle processHandle = process.toHandle(); + + log.info("PID: {} has started", processHandle.getPid()); + CompletableFuture onProcessExit = processHandle.onExit(); + onProcessExit.get(); + assertEquals(false, processHandle.isAlive()); + onProcessExit.thenAccept(ph -> { + log.info("PID: {} has stopped", ph.getPid()); + }); + } + +} diff --git a/core-java/0.004102810554955205 b/core-java/0.004102810554955205 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/core-java/0.04832801936270381 b/core-java/0.04832801936270381 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/core-java/0.5633433244738808 b/core-java/0.5633433244738808 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/core-java/0.5967303215007616 b/core-java/0.5967303215007616 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/core-java/0.6256429734439612 b/core-java/0.6256429734439612 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/core-java/0.9252611327674576 b/core-java/0.9252611327674576 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/core-java/0.9799201796740292 b/core-java/0.9799201796740292 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/core-java/README.md b/core-java/README.md index cd16935864..a34908d8ae 100644 --- a/core-java/README.md +++ b/core-java/README.md @@ -57,3 +57,25 @@ - [Guide to java.util.concurrent.Future](http://www.baeldung.com/java-future) - [Guide to java.util.concurrent.BlockingQueue](http://www.baeldung.com/java-blocking-queue) - [Guide to CountDownLatch in Java](http://www.baeldung.com/java-countdown-latch) +- [How to Design a Genetic Algorithm in Java](http://www.baeldung.com/java-genetic-algorithm) +- [A Guide to ConcurrentMap](http://www.baeldung.com/java-concurrent-map) +- [Guide to PriorityBlockingQueue in Java](http://www.baeldung.com/java-priority-blocking-queue) +- [Guide to Java 8 groupingBy Collector](http://www.baeldung.com/java-groupingby-collector) +- [Avoiding the ConcurrentModificationException in Java](http://www.baeldung.com/java-concurrentmodificationexception) +- [Guide to WeakHashMap in Java](http://www.baeldung.com/java-weakhashmap) +- [Strategy Design Pattern in Java 8](http://www.baeldung.com/java-strategy-pattern) +- [Java 8 and Infinite Streams](http://www.baeldung.com/java-inifinite-streams) +- [Custom Thread Pools In Java 8 Parallel Streams](http://www.baeldung.com/java-8-parallel-streams-custom-threadpool) +- [String Operations with Java Streams](http://www.baeldung.com/java-stream-operations-on-strings) +- [Spring Security – Cache Control Headers](http://www.baeldung.com/spring-security-cache-control-headers) +- [Basic Introduction to JMX](http://www.baeldung.com/java-management-extensions) +- [AWS Lambda With Java](http://www.baeldung.com/java-aws-lambda) +- [Introduction to Nashorn](http://www.baeldung.com/java-nashorn) +- [Exceptions in Java 8 Lambda Expressions](http://www.baeldung.com/java-lambda-exceptions) +- [Guide to the Guava BiMap](http://www.baeldung.com/guava-bimap) +- [Iterable to Stream in Java](http://www.baeldung.com/java-iterable-to-stream) +- [Java 8 Stream findFirst() vs. findAny()](http://www.baeldung.com/java-stream-findfirst-vs-findany) +- [Chained Exceptions in Java](http://www.baeldung.com/java-chained-exceptions) +- [The Java HashMap Under the Hood](http://www.baeldung.com/java-hashmap) +- [A Guide to LinkedHashMap in Java](http://www.baeldung.com/java-linked-hashmap) +- [A Guide to TreeMap in Java](http://www.baeldung.com/java-treemap) diff --git a/core-java/pom.xml b/core-java/pom.xml index 85afee2968..b2c59989f1 100644 --- a/core-java/pom.xml +++ b/core-java/pom.xml @@ -1,5 +1,5 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 com.baeldung core-java @@ -9,7 +9,7 @@ core-java - + net.sourceforge.collections @@ -63,7 +63,6 @@ grep4j ${grep4j.version} - @@ -154,6 +153,12 @@ ${mockito.version} test + + com.jayway.awaitility + awaitility + ${avaitility.version} + test + commons-codec @@ -263,7 +268,8 @@ true - + org.baeldung.executable.ExecutableMavenJar @@ -371,6 +377,7 @@ 1.10.19 6.10 3.6.1 + 1.7.0 3.6.0 diff --git a/core-java/src/main/java/com/baeldung/algorithms/RunAlgorithm.java b/core-java/src/main/java/com/baeldung/algorithms/RunAlgorithm.java index 113ac1cc53..3f7c8bf4b3 100644 --- a/core-java/src/main/java/com/baeldung/algorithms/RunAlgorithm.java +++ b/core-java/src/main/java/com/baeldung/algorithms/RunAlgorithm.java @@ -3,28 +3,35 @@ package com.baeldung.algorithms; import java.util.Scanner; import com.baeldung.algorithms.annealing.SimulatedAnnealing; +import com.baeldung.algorithms.ga.binary.SimpleGeneticAlgorithm; import com.baeldung.algorithms.slope_one.SlopeOne; public class RunAlgorithm { - public static void main(String[] args) { - Scanner in = new Scanner(System.in); - System.out.println("Run algorithm:"); - System.out.println("1 - Simulated Annealing"); - System.out.println("2 - Slope One"); - int decision = in.nextInt(); - switch (decision) { - case 1: - System.out.println("Optimized distance for travel: " + SimulatedAnnealing.simulateAnnealing(10, 10000, 0.9995)); - break; - case 2: - SlopeOne.slopeOne(3); - break; - default: - System.out.println("Unknown option"); - break; - } - in.close(); - } + public static void main(String[] args) { + Scanner in = new Scanner(System.in); + System.out.println("Run algorithm:"); + System.out.println("1 - Simulated Annealing"); + System.out.println("2 - Slope One"); + System.out.println("3 - Simple Genetic Algorithm"); + int decision = in.nextInt(); + switch (decision) { + case 1: + System.out.println( + "Optimized distance for travel: " + SimulatedAnnealing.simulateAnnealing(10, 10000, 0.9995)); + break; + case 2: + SlopeOne.slopeOne(3); + break; + case 3: + SimpleGeneticAlgorithm ga = new SimpleGeneticAlgorithm(); + ga.runAlgorithm(50, "1011000100000100010000100000100111001000000100000100000000001111"); + break; + default: + System.out.println("Unknown option"); + break; + } + in.close(); + } } diff --git a/core-java/src/main/java/com/baeldung/algorithms/ga/binary/Individual.java b/core-java/src/main/java/com/baeldung/algorithms/ga/binary/Individual.java new file mode 100644 index 0000000000..2a740777f3 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/algorithms/ga/binary/Individual.java @@ -0,0 +1,44 @@ +package com.baeldung.algorithms.ga.binary; + +import lombok.Data; + +@Data +public class Individual { + + protected int defaultGeneLength = 64; + private byte[] genes = new byte[defaultGeneLength]; + private int fitness = 0; + + public Individual() { + for (int i = 0; i < genes.length; i++) { + byte gene = (byte) Math.round(Math.random()); + genes[i] = gene; + } + } + + protected byte getSingleGene(int index) { + return genes[index]; + } + + protected void setSingleGene(int index, byte value) { + genes[index] = value; + fitness = 0; + } + + public int getFitness() { + if (fitness == 0) { + fitness = SimpleGeneticAlgorithm.getFitness(this); + } + return fitness; + } + + @Override + public String toString() { + String geneString = ""; + for (int i = 0; i < genes.length; i++) { + geneString += getSingleGene(i); + } + return geneString; + } + +} diff --git a/core-java/src/main/java/com/baeldung/algorithms/ga/binary/Population.java b/core-java/src/main/java/com/baeldung/algorithms/ga/binary/Population.java new file mode 100644 index 0000000000..47677d7d88 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/algorithms/ga/binary/Population.java @@ -0,0 +1,40 @@ +package com.baeldung.algorithms.ga.binary; + +import java.util.ArrayList; +import java.util.List; + +import lombok.Data; + +@Data +public class Population { + + private List individuals; + + public Population(int size, boolean createNew) { + individuals = new ArrayList<>(); + if (createNew) { + createNewPopulation(size); + } + } + + protected Individual getIndividual(int index) { + return individuals.get(index); + } + + protected Individual getFittest() { + Individual fittest = individuals.get(0); + for (int i = 0; i < individuals.size(); i++) { + if (fittest.getFitness() <= getIndividual(i).getFitness()) { + fittest = getIndividual(i); + } + } + return fittest; + } + + private void createNewPopulation(int size) { + for (int i = 0; i < size; i++) { + Individual newIndividual = new Individual(); + individuals.add(i, newIndividual); + } + } +} diff --git a/core-java/src/main/java/com/baeldung/algorithms/ga/binary/SimpleGeneticAlgorithm.java b/core-java/src/main/java/com/baeldung/algorithms/ga/binary/SimpleGeneticAlgorithm.java new file mode 100644 index 0000000000..e62eab0d57 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/algorithms/ga/binary/SimpleGeneticAlgorithm.java @@ -0,0 +1,117 @@ +package com.baeldung.algorithms.ga.binary; + +import lombok.Data; + +@Data +public class SimpleGeneticAlgorithm { + + private static final double uniformRate = 0.5; + private static final double mutationRate = 0.025; + private static final int tournamentSize = 5; + private static final boolean elitism = true; + private static byte[] solution = new byte[64]; + + public boolean runAlgorithm(int populationSize, String solution) { + if (solution.length() != SimpleGeneticAlgorithm.solution.length) { + throw new RuntimeException("The solution needs to have " + SimpleGeneticAlgorithm.solution.length + " bytes"); + } + setSolution(solution); + Population myPop = new Population(populationSize, true); + + int generationCount = 1; + while (myPop.getFittest().getFitness() < getMaxFitness()) { + System.out.println("Generation: " + generationCount + " Correct genes found: " + myPop.getFittest().getFitness()); + myPop = evolvePopulation(myPop); + generationCount++; + } + System.out.println("Solution found!"); + System.out.println("Generation: " + generationCount); + System.out.println("Genes: "); + System.out.println(myPop.getFittest()); + return true; + } + + public Population evolvePopulation(Population pop) { + int elitismOffset; + Population newPopulation = new Population(pop.getIndividuals().size(), false); + + if (elitism) { + newPopulation.getIndividuals().add(0, pop.getFittest()); + elitismOffset = 1; + } else { + elitismOffset = 0; + } + + for (int i = elitismOffset; i < pop.getIndividuals().size(); i++) { + Individual indiv1 = tournamentSelection(pop); + Individual indiv2 = tournamentSelection(pop); + Individual newIndiv = crossover(indiv1, indiv2); + newPopulation.getIndividuals().add(i, newIndiv); + } + + for (int i = elitismOffset; i < newPopulation.getIndividuals().size(); i++) { + mutate(newPopulation.getIndividual(i)); + } + + return newPopulation; + } + + private Individual crossover(Individual indiv1, Individual indiv2) { + Individual newSol = new Individual(); + for (int i = 0; i < newSol.getDefaultGeneLength(); i++) { + if (Math.random() <= uniformRate) { + newSol.setSingleGene(i, indiv1.getSingleGene(i)); + } else { + newSol.setSingleGene(i, indiv2.getSingleGene(i)); + } + } + return newSol; + } + + private void mutate(Individual indiv) { + for (int i = 0; i < indiv.getDefaultGeneLength(); i++) { + if (Math.random() <= mutationRate) { + byte gene = (byte) Math.round(Math.random()); + indiv.setSingleGene(i, gene); + } + } + } + + private Individual tournamentSelection(Population pop) { + Population tournament = new Population(tournamentSize, false); + for (int i = 0; i < tournamentSize; i++) { + int randomId = (int) (Math.random() * pop.getIndividuals().size()); + tournament.getIndividuals().add(i, pop.getIndividual(randomId)); + } + Individual fittest = tournament.getFittest(); + return fittest; + } + + protected static int getFitness(Individual individual) { + int fitness = 0; + for (int i = 0; i < individual.getDefaultGeneLength() && i < solution.length; i++) { + if (individual.getSingleGene(i) == solution[i]) { + fitness++; + } + } + return fitness; + } + + protected int getMaxFitness() { + int maxFitness = solution.length; + return maxFitness; + } + + protected void setSolution(String newSolution) { + solution = new byte[newSolution.length()]; + for (int i = 0; i < newSolution.length(); i++) { + String character = newSolution.substring(i, i + 1); + if (character.contains("0") || character.contains("1")) { + solution[i] = Byte.parseByte(character); + } else { + solution[i] = 0; + } + } + } + +} diff --git a/core-java/src/main/java/com/baeldung/concurrent/future/SquareCalculator.java b/core-java/src/main/java/com/baeldung/concurrent/future/SquareCalculator.java index e53a2413d1..bcd559dd3b 100644 --- a/core-java/src/main/java/com/baeldung/concurrent/future/SquareCalculator.java +++ b/core-java/src/main/java/com/baeldung/concurrent/future/SquareCalculator.java @@ -15,6 +15,6 @@ public class SquareCalculator { return executor.submit(() -> { Thread.sleep(1000); return input * input; - }); + }); } } diff --git a/core-java/src/main/java/com/baeldung/concurrent/locks/ReentrantLockWithCondition.java b/core-java/src/main/java/com/baeldung/concurrent/locks/ReentrantLockWithCondition.java new file mode 100644 index 0000000000..4f061d2efd --- /dev/null +++ b/core-java/src/main/java/com/baeldung/concurrent/locks/ReentrantLockWithCondition.java @@ -0,0 +1,83 @@ +package com.baeldung.concurrent.locks; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Stack; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; + +import static java.lang.Thread.sleep; + +public class ReentrantLockWithCondition { + + static Logger logger = LoggerFactory.getLogger(ReentrantLockWithCondition.class); + + Stack stack = new Stack<>(); + int CAPACITY = 5; + + ReentrantLock lock = new ReentrantLock(); + Condition stackEmptyCondition = lock.newCondition(); + Condition stackFullCondition = lock.newCondition(); + + public void pushToStack(String item) throws InterruptedException { + try { + lock.lock(); + if (stack.size() == CAPACITY) { + logger.info(Thread.currentThread().getName() + " wait on stack full"); + stackFullCondition.await(); + } + logger.info("Pushing the item " + item); + stack.push(item); + stackEmptyCondition.signalAll(); + } finally { + lock.unlock(); + } + + } + + public String popFromStack() throws InterruptedException { + try { + lock.lock(); + if (stack.size() == 0) { + logger.info(Thread.currentThread().getName() + " wait on stack empty"); + stackEmptyCondition.await(); + } + return stack.pop(); + } finally { + stackFullCondition.signalAll(); + lock.unlock(); + } + } + + public static void main(String[] args) { + final int threadCount = 2; + ReentrantLockWithCondition object = new ReentrantLockWithCondition(); + final ExecutorService service = Executors.newFixedThreadPool(threadCount); + service.execute(() -> { + for (int i = 0; i < 10; i++) { + try { + object.pushToStack("Item " + i); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + }); + + service.execute(() -> { + for (int i = 0; i < 10; i++) { + try { + logger.info("Item popped " + object.popFromStack()); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + }); + + service.shutdown(); + } +} diff --git a/core-java/src/main/java/com/baeldung/concurrent/locks/SharedObjectWithLock.java b/core-java/src/main/java/com/baeldung/concurrent/locks/SharedObjectWithLock.java new file mode 100644 index 0000000000..b6a4615638 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/concurrent/locks/SharedObjectWithLock.java @@ -0,0 +1,92 @@ +package com.baeldung.concurrent.locks; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantLock; + +import static java.lang.Thread.sleep; + +public class SharedObjectWithLock { + + Logger logger = LoggerFactory.getLogger(SharedObjectWithLock.class); + + ReentrantLock lock = new ReentrantLock(true); + + int counter = 0; + + public void perform() { + + lock.lock(); + logger.info("Thread - " + Thread.currentThread().getName() + " acquired the lock"); + try { + logger.info("Thread - " + Thread.currentThread().getName() + " processing"); + counter++; + } catch (Exception exception) { + logger.error(" Interrupted Exception ", exception); + } finally { + lock.unlock(); + logger.info("Thread - " + Thread.currentThread().getName() + " released the lock"); + } + } + + public void performTryLock() { + + logger.info("Thread - " + Thread.currentThread().getName() + " attempting to acquire the lock"); + try { + boolean isLockAcquired = lock.tryLock(2, TimeUnit.SECONDS); + if (isLockAcquired) { + try { + logger.info("Thread - " + Thread.currentThread().getName() + " acquired the lock"); + + logger.info("Thread - " + Thread.currentThread().getName() + " processing"); + sleep(1000); + } finally { + lock.unlock(); + logger.info("Thread - " + Thread.currentThread().getName() + " released the lock"); + + } + } + } catch (InterruptedException exception) { + logger.error(" Interrupted Exception ", exception); + } + logger.info("Thread - " + Thread.currentThread().getName() + " could not acquire the lock"); + } + + public ReentrantLock getLock() { + return lock; + } + + boolean isLocked() { + return lock.isLocked(); + } + + boolean hasQueuedThreads() { + return lock.hasQueuedThreads(); + } + + int getCounter() { + return counter; + } + + public static void main(String[] args) { + + final int threadCount = 2; + final ExecutorService service = Executors.newFixedThreadPool(threadCount); + final SharedObjectWithLock object = new SharedObjectWithLock(); + + service.execute(() -> { + object.perform(); + }); + service.execute(() -> { + object.performTryLock(); + }); + + service.shutdown(); + + } + +} diff --git a/core-java/src/main/java/com/baeldung/concurrent/locks/StampedLockDemo.java b/core-java/src/main/java/com/baeldung/concurrent/locks/StampedLockDemo.java new file mode 100644 index 0000000000..0b0dbc72cb --- /dev/null +++ b/core-java/src/main/java/com/baeldung/concurrent/locks/StampedLockDemo.java @@ -0,0 +1,104 @@ +package com.baeldung.concurrent.locks; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.locks.StampedLock; + +import static java.lang.Thread.sleep; + +public class StampedLockDemo { + Map map = new HashMap<>(); + Logger logger = LoggerFactory.getLogger(StampedLockDemo.class); + + private final StampedLock lock = new StampedLock(); + + public void put(String key, String value) throws InterruptedException { + long stamp = lock.writeLock(); + + try { + logger.info(Thread.currentThread().getName() + " acquired the write lock with stamp " + stamp); + map.put(key, value); + } finally { + lock.unlockWrite(stamp); + logger.info(Thread.currentThread().getName() + " unlocked the write lock with stamp " + stamp); + } + } + + public String get(String key) throws InterruptedException { + long stamp = lock.readLock(); + logger.info(Thread.currentThread().getName() + " acquired the read lock with stamp " + stamp); + try { + sleep(5000); + return map.get(key); + + } finally { + lock.unlockRead(stamp); + logger.info(Thread.currentThread().getName() + " unlocked the read lock with stamp " + stamp); + + } + + } + + public String readWithOptimisticLock(String key) throws InterruptedException { + long stamp = lock.tryOptimisticRead(); + String value = map.get(key); + + if (!lock.validate(stamp)) { + stamp = lock.readLock(); + try { + sleep(5000); + return map.get(key); + + } finally { + lock.unlock(stamp); + logger.info(Thread.currentThread().getName() + " unlocked the read lock with stamp " + stamp); + + } + } + return value; + } + + public static void main(String[] args) { + final int threadCount = 4; + final ExecutorService service = Executors.newFixedThreadPool(threadCount); + StampedLockDemo object = new StampedLockDemo(); + + Runnable writeTask = () -> { + + try { + object.put("key1", "value1"); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }; + Runnable readTask = () -> { + + try { + object.get("key1"); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }; + Runnable readOptimisticTask = () -> { + + try { + object.readWithOptimisticLock("key1"); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }; + service.submit(writeTask); + service.submit(writeTask); + service.submit(readTask); + service.submit(readOptimisticTask); + + service.shutdown(); + + } + +} diff --git a/core-java/src/main/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLock.java b/core-java/src/main/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLock.java new file mode 100644 index 0000000000..83b8b34fe9 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLock.java @@ -0,0 +1,120 @@ +package com.baeldung.concurrent.locks; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import static java.lang.Thread.sleep; + +public class SynchronizedHashMapWithRWLock { + + static Map syncHashMap = new HashMap<>(); + Logger logger = LoggerFactory.getLogger(SynchronizedHashMapWithRWLock.class); + + private final ReadWriteLock lock = new ReentrantReadWriteLock(); + private final Lock readLock = lock.readLock(); + private final Lock writeLock = lock.writeLock(); + + public void put(String key, String value) throws InterruptedException { + + try { + writeLock.lock(); + logger.info(Thread.currentThread().getName() + " writing"); + syncHashMap.put(key, value); + sleep(1000); + } finally { + writeLock.unlock(); + } + + } + + public String get(String key) { + try { + readLock.lock(); + logger.info(Thread.currentThread().getName() + " reading"); + return syncHashMap.get(key); + } finally { + readLock.unlock(); + } + } + + public String remove(String key) { + try { + writeLock.lock(); + return syncHashMap.remove(key); + } finally { + writeLock.unlock(); + } + } + + public boolean containsKey(String key) { + try { + readLock.lock(); + return syncHashMap.containsKey(key); + } finally { + readLock.unlock(); + } + } + + boolean isReadLockAvailable() { + return readLock.tryLock(); + } + + public static void main(String[] args) throws InterruptedException { + + final int threadCount = 3; + final ExecutorService service = Executors.newFixedThreadPool(threadCount); + SynchronizedHashMapWithRWLock object = new SynchronizedHashMapWithRWLock(); + + service.execute(new Thread(new Writer(object), "Writer")); + service.execute(new Thread(new Reader(object), "Reader1")); + service.execute(new Thread(new Reader(object), "Reader2")); + + service.shutdown(); + } + + private static class Reader implements Runnable { + + SynchronizedHashMapWithRWLock object; + + public Reader(SynchronizedHashMapWithRWLock object) { + this.object = object; + } + + @Override + public void run() { + for (int i = 0; i < 10; i++) { + object.get("key" + i); + } + } + } + + private static class Writer implements Runnable { + + SynchronizedHashMapWithRWLock object; + + public Writer(SynchronizedHashMapWithRWLock object) { + this.object = object; + } + + @Override + public void run() { + for (int i = 0; i < 10; i++) { + try { + object.put("key" + i, "value" + i); + sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + +} diff --git a/core-java/src/main/java/com/baeldung/java_8_features/Person.java b/core-java/src/main/java/com/baeldung/java_8_features/Person.java new file mode 100644 index 0000000000..83b5530ee8 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/java_8_features/Person.java @@ -0,0 +1,27 @@ +package com.baeldung.java_8_features; + +public class Person { + private String name; + private Integer age; + + public Person(String name, int age) { + this.name = name; + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } +} diff --git a/core-java/src/main/java/com/baeldung/java_8_features/groupingby/BlogPost.java b/core-java/src/main/java/com/baeldung/java_8_features/groupingby/BlogPost.java new file mode 100644 index 0000000000..afc05e356a --- /dev/null +++ b/core-java/src/main/java/com/baeldung/java_8_features/groupingby/BlogPost.java @@ -0,0 +1,36 @@ +package com.baeldung.java_8_features.groupingby; + +public class BlogPost { + private String title; + private String author; + private BlogPostType type; + private int likes; + + public BlogPost(String title, String author, BlogPostType type, int likes) { + this.title = title; + this.author = author; + this.type = type; + this.likes = likes; + } + + public String getTitle() { + return title; + } + + public String getAuthor() { + return author; + } + + public BlogPostType getType() { + return type; + } + + public int getLikes() { + return likes; + } + + @Override + public String toString() { + return "BlogPost{" + "title='" + title + '\'' + ", type=" + type + ", likes=" + likes + '}'; + } +} diff --git a/core-java/src/main/java/com/baeldung/java_8_features/groupingby/BlogPostType.java b/core-java/src/main/java/com/baeldung/java_8_features/groupingby/BlogPostType.java new file mode 100644 index 0000000000..2029784e91 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/java_8_features/groupingby/BlogPostType.java @@ -0,0 +1,5 @@ +package com.baeldung.java_8_features.groupingby; + +public enum BlogPostType { + NEWS, REVIEW, GUIDE +} diff --git a/core-java/src/main/java/com/baeldung/strategy/ChristmasDiscounter.java b/core-java/src/main/java/com/baeldung/strategy/ChristmasDiscounter.java new file mode 100644 index 0000000000..a0c36bb63e --- /dev/null +++ b/core-java/src/main/java/com/baeldung/strategy/ChristmasDiscounter.java @@ -0,0 +1,11 @@ +package com.baeldung.strategy; + +import java.math.BigDecimal; + +public class ChristmasDiscounter implements Discounter { + + @Override + public BigDecimal apply(BigDecimal amount) { + return amount.multiply(BigDecimal.valueOf(0.9)); + } +} diff --git a/core-java/src/main/java/com/baeldung/strategy/Discounter.java b/core-java/src/main/java/com/baeldung/strategy/Discounter.java new file mode 100644 index 0000000000..00bf4855d1 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/strategy/Discounter.java @@ -0,0 +1,23 @@ +package com.baeldung.strategy; + +import java.math.BigDecimal; +import java.util.function.UnaryOperator; + +public interface Discounter extends UnaryOperator { + + default Discounter combine(Discounter after) { + return value -> after.apply(this.apply(value)); + } + + static Discounter christmas() { + return (amount) -> amount.multiply(BigDecimal.valueOf(0.9)); + } + + static Discounter newYear() { + return (amount) -> amount.multiply(BigDecimal.valueOf(0.8)); + } + + static Discounter easter() { + return (amount) -> amount.multiply(BigDecimal.valueOf(0.5)); + } +} diff --git a/core-java/src/main/java/com/baeldung/strategy/EasterDiscounter.java b/core-java/src/main/java/com/baeldung/strategy/EasterDiscounter.java new file mode 100644 index 0000000000..990d10073b --- /dev/null +++ b/core-java/src/main/java/com/baeldung/strategy/EasterDiscounter.java @@ -0,0 +1,11 @@ +package com.baeldung.strategy; + +import java.math.BigDecimal; + +public class EasterDiscounter implements Discounter { + + @Override + public BigDecimal apply(BigDecimal amount) { + return amount.multiply(BigDecimal.valueOf(0.5)); + } +} diff --git a/core-java/src/main/java/com/baeldung/stream/InfiniteStreams.java b/core-java/src/main/java/com/baeldung/stream/InfiniteStreams.java new file mode 100644 index 0000000000..097b516f8c --- /dev/null +++ b/core-java/src/main/java/com/baeldung/stream/InfiniteStreams.java @@ -0,0 +1,27 @@ +package com.baeldung.stream; + + +import java.util.stream.Stream; + +public class InfiniteStreams { + public static void main(String[] args) { + doWhileOldWay(); + + doWhileStreamWay(); + + } + + private static void doWhileOldWay() { + + int i = 0; + while (i < 10) { + System.out.println(i); + i++; + } + } + + private static void doWhileStreamWay() { + Stream integers = Stream.iterate(0, i -> i + 1); + integers.limit(10).forEach(System.out::println); + } +} diff --git a/core-java/src/main/java/com/baeldung/string/JoinerSplitter.java b/core-java/src/main/java/com/baeldung/string/JoinerSplitter.java new file mode 100644 index 0000000000..085be66801 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/string/JoinerSplitter.java @@ -0,0 +1,36 @@ +package com.baeldung.string; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class JoinerSplitter { + + public static String join ( String[] arrayOfString ) { + return Arrays.asList(arrayOfString) + .stream() + .map(x -> x) + .collect(Collectors.joining(",")); + } + + public static String joinWithPrefixPostFix ( String[] arrayOfString ) { + return Arrays.asList(arrayOfString) + .stream() + .map(x -> x) + .collect(Collectors.joining(",","[","]")); + } + + public static List split ( String str ) { + return Stream.of(str.split(",")) + .map (elem -> new String(elem)) + .collect(Collectors.toList()); + } + + public static List splitToListOfChar ( String str ) { + return str.chars() + .mapToObj(item -> (char) item) + .collect(Collectors.toList()); + } + +} diff --git a/core-java/src/test/java/com/baeldung/CharArrayToStringUnitTest.java b/core-java/src/test/java/com/baeldung/CharArrayToStringUnitTest.java index 2f7830bbf4..3488f8b390 100644 --- a/core-java/src/test/java/com/baeldung/CharArrayToStringUnitTest.java +++ b/core-java/src/test/java/com/baeldung/CharArrayToStringUnitTest.java @@ -8,55 +8,55 @@ public class CharArrayToStringUnitTest { @Test public void givenCharArray_whenCallingStringConstructor_shouldConvertToString() { - char[] charArray = {'c', 'h', 'a', 'r', 'a', 'c', 't', 'e', 'r'}; + char[] charArray = { 'c', 'h', 'a', 'r', 'a', 'c', 't', 'e', 'r' }; String result = new String(charArray); String expectedValue = "character"; - + assertEquals(expectedValue, result); } - + @Test - public void givenCharArray_whenCallingStringConstructorWithOffsetAndLength_shouldConvertToString(){ - char[] charArray = {'c', 'h', 'a', 'r', 'a', 'c', 't', 'e', 'r'}; + public void givenCharArray_whenCallingStringConstructorWithOffsetAndLength_shouldConvertToString() { + char[] charArray = { 'c', 'h', 'a', 'r', 'a', 'c', 't', 'e', 'r' }; String result = new String(charArray, 4, 3); String expectedValue = "act"; - + assertEquals(expectedValue, result); } - + @Test - public void givenCharArray_whenCallingStringCopyValueOf_shouldConvertToString(){ - char[] charArray = {'c', 'h', 'a', 'r', 'a', 'c', 't', 'e', 'r'}; + public void givenCharArray_whenCallingStringCopyValueOf_shouldConvertToString() { + char[] charArray = { 'c', 'h', 'a', 'r', 'a', 'c', 't', 'e', 'r' }; String result = String.copyValueOf(charArray); String expectedValue = "character"; - + assertEquals(expectedValue, result); } - + @Test - public void givenCharArray_whenCallingStringCopyValueOfWithOffsetAndLength_shouldConvertToString(){ - char[] charArray = {'c', 'h', 'a', 'r', 'a', 'c', 't', 'e', 'r'}; + public void givenCharArray_whenCallingStringCopyValueOfWithOffsetAndLength_shouldConvertToString() { + char[] charArray = { 'c', 'h', 'a', 'r', 'a', 'c', 't', 'e', 'r' }; String result = String.copyValueOf(charArray, 0, 4); String expectedValue = "char"; - + assertEquals(expectedValue, result); } - + @Test - public void givenCharArray_whenCallingStringValueOf_shouldConvertToString(){ - char[] charArray = {'c', 'h', 'a', 'r', 'a', 'c', 't', 'e', 'r'}; + public void givenCharArray_whenCallingStringValueOf_shouldConvertToString() { + char[] charArray = { 'c', 'h', 'a', 'r', 'a', 'c', 't', 'e', 'r' }; String result = String.valueOf(charArray); String expectedValue = "character"; - + assertEquals(expectedValue, result); } - + @Test - public void givenCharArray_whenCallingStringValueOfWithOffsetAndLength_shouldConvertToString(){ - char[] charArray = {'c', 'h', 'a', 'r', 'a', 'c', 't', 'e', 'r'}; + public void givenCharArray_whenCallingStringValueOfWithOffsetAndLength_shouldConvertToString() { + char[] charArray = { 'c', 'h', 'a', 'r', 'a', 'c', 't', 'e', 'r' }; String result = String.valueOf(charArray, 3, 4); String expectedValue = "ract"; - + assertEquals(expectedValue, result); } } diff --git a/core-java/src/test/java/com/baeldung/StringToCharArrayUnitTest.java b/core-java/src/test/java/com/baeldung/StringToCharArrayUnitTest.java index 2e7dc24a17..cd996e58e2 100644 --- a/core-java/src/test/java/com/baeldung/StringToCharArrayUnitTest.java +++ b/core-java/src/test/java/com/baeldung/StringToCharArrayUnitTest.java @@ -6,15 +6,15 @@ import org.junit.Test; public class StringToCharArrayUnitTest { -@Test -public void givenString_whenCallingStringToCharArray_shouldConvertToCharArray() { - String givenString = "characters"; + @Test + public void givenString_whenCallingStringToCharArray_shouldConvertToCharArray() { + String givenString = "characters"; - char[] result = givenString.toCharArray(); + char[] result = givenString.toCharArray(); - char[] expectedCharArray = { 'c', 'h', 'a', 'r', 'a', 'c', 't', 'e', 'r', 's' }; + char[] expectedCharArray = { 'c', 'h', 'a', 'r', 'a', 'c', 't', 'e', 'r', 's' }; - assertArrayEquals(expectedCharArray, result); -} + assertArrayEquals(expectedCharArray, result); + } } diff --git a/core-java/src/test/java/com/baeldung/algorithms/BinaryGeneticAlgorithmUnitTest.java b/core-java/src/test/java/com/baeldung/algorithms/BinaryGeneticAlgorithmUnitTest.java new file mode 100644 index 0000000000..2e92177c8c --- /dev/null +++ b/core-java/src/test/java/com/baeldung/algorithms/BinaryGeneticAlgorithmUnitTest.java @@ -0,0 +1,16 @@ +package com.baeldung.algorithms; + +import org.junit.Assert; +import org.junit.Test; + +import com.baeldung.algorithms.ga.binary.SimpleGeneticAlgorithm; + +public class BinaryGeneticAlgorithmUnitTest { + + @Test + public void testGA() { + SimpleGeneticAlgorithm ga = new SimpleGeneticAlgorithm(); + Assert.assertTrue(ga.runAlgorithm(50, "1011000100000100010000100000100111001000000100000100000000001111")); + } + +} diff --git a/core-java/src/test/java/com/baeldung/concurrent/locks/SharedObjectWithLockManualTest.java b/core-java/src/test/java/com/baeldung/concurrent/locks/SharedObjectWithLockManualTest.java new file mode 100644 index 0000000000..9b82ced642 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/concurrent/locks/SharedObjectWithLockManualTest.java @@ -0,0 +1,75 @@ +package com.baeldung.concurrent.locks; + +import org.junit.Test; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static junit.framework.TestCase.assertEquals; + +public class SharedObjectWithLockManualTest { + + @Test + public void whenLockAcquired_ThenLockedIsTrue() { + final SharedObjectWithLock object = new SharedObjectWithLock(); + + final int threadCount = 2; + final ExecutorService service = Executors.newFixedThreadPool(threadCount); + + executeThreads(object, threadCount, service); + + assertEquals(true, object.isLocked()); + + service.shutdown(); + } + + @Test + public void whenLocked_ThenQueuedThread() { + final int threadCount = 4; + final ExecutorService service = Executors.newFixedThreadPool(threadCount); + final SharedObjectWithLock object = new SharedObjectWithLock(); + + executeThreads(object, threadCount, service); + + assertEquals(object.hasQueuedThreads(), true); + + service.shutdown(); + + } + + public void whenTryLock_ThenQueuedThread() { + final SharedObjectWithLock object = new SharedObjectWithLock(); + + final int threadCount = 2; + final ExecutorService service = Executors.newFixedThreadPool(threadCount); + + executeThreads(object, threadCount, service); + + assertEquals(true, object.isLocked()); + + service.shutdown(); + } + + @Test + public void whenGetCount_ThenCorrectCount() throws InterruptedException { + final int threadCount = 4; + final ExecutorService service = Executors.newFixedThreadPool(threadCount); + final SharedObjectWithLock object = new SharedObjectWithLock(); + + executeThreads(object, threadCount, service); + Thread.sleep(1000); + assertEquals(object.getCounter(), 4); + + service.shutdown(); + + } + + private void executeThreads(SharedObjectWithLock object, int threadCount, ExecutorService service) { + for (int i = 0; i < threadCount; i++) { + service.execute(() -> { + object.perform(); + }); + } + } + +} diff --git a/core-java/src/test/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLockManualTest.java b/core-java/src/test/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLockManualTest.java new file mode 100644 index 0000000000..fd6cf08442 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/concurrent/locks/SynchronizedHashMapWithRWLockManualTest.java @@ -0,0 +1,58 @@ +package com.baeldung.concurrent.locks; + +import jdk.nashorn.internal.ir.annotations.Ignore; +import org.junit.Test; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static junit.framework.TestCase.assertEquals; + +public class SynchronizedHashMapWithRWLockManualTest { + + @Test + public void whenWriting_ThenNoReading() { + SynchronizedHashMapWithRWLock object = new SynchronizedHashMapWithRWLock(); + final int threadCount = 3; + final ExecutorService service = Executors.newFixedThreadPool(threadCount); + + executeWriterThreads(object, threadCount, service); + + assertEquals(object.isReadLockAvailable(), false); + + service.shutdown(); + } + + @Test + public void whenReading_ThenMultipleReadingAllowed() { + SynchronizedHashMapWithRWLock object = new SynchronizedHashMapWithRWLock(); + final int threadCount = 5; + final ExecutorService service = Executors.newFixedThreadPool(threadCount); + + executeReaderThreads(object, threadCount, service); + + assertEquals(object.isReadLockAvailable(), true); + + service.shutdown(); + } + + private void executeWriterThreads(SynchronizedHashMapWithRWLock object, int threadCount, ExecutorService service) { + for (int i = 0; i < threadCount; i++) { + service.execute(() -> { + try { + object.put("key" + threadCount, "value" + threadCount); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }); + } + } + + private void executeReaderThreads(SynchronizedHashMapWithRWLock object, int threadCount, ExecutorService service) { + for (int i = 0; i < threadCount; i++) + service.execute(() -> { + object.get("key" + threadCount); + }); + } + +} diff --git a/core-java/src/test/java/com/baeldung/concurrent/priorityblockingqueue/PriorityBlockingQueueUnitTest.java b/core-java/src/test/java/com/baeldung/concurrent/priorityblockingqueue/PriorityBlockingQueueUnitTest.java index 063e07d859..0272726465 100644 --- a/core-java/src/test/java/com/baeldung/concurrent/priorityblockingqueue/PriorityBlockingQueueUnitTest.java +++ b/core-java/src/test/java/com/baeldung/concurrent/priorityblockingqueue/PriorityBlockingQueueUnitTest.java @@ -1,12 +1,10 @@ package com.baeldung.concurrent.priorityblockingqueue; -import org.assertj.core.api.Assertions; import org.junit.Test; import java.util.ArrayList; import java.util.concurrent.PriorityBlockingQueue; import java.util.concurrent.TimeUnit; -import java.util.stream.IntStream; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.util.Lists.newArrayList; @@ -24,11 +22,7 @@ public class PriorityBlockingQueueUnitTest { queue.add(3); queue.add(4); - polledElements.add(queue.poll()); - polledElements.add(queue.poll()); - polledElements.add(queue.poll()); - polledElements.add(queue.poll()); - polledElements.add(queue.poll()); + queue.drainTo(polledElements); assertThat(polledElements).containsExactly(1, 2, 3, 4, 5); } @@ -38,13 +32,14 @@ public class PriorityBlockingQueueUnitTest { PriorityBlockingQueue queue = new PriorityBlockingQueue<>(); final Thread thread = new Thread(() -> { - System.out.println("Polling..."); - while (true) { - try { - Integer poll = queue.take(); - System.out.println("Polled: " + poll); - } catch (InterruptedException e) {} - } + System.out.println("Polling..."); + while (true) { + try { + Integer poll = queue.take(); + System.out.println("Polled: " + poll); + } catch (InterruptedException e) { + } + } }); thread.start(); diff --git a/core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapAggregateStatusTest.java b/core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapAggregateStatusManualTest.java similarity index 97% rename from core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapAggregateStatusTest.java rename to core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapAggregateStatusManualTest.java index 73a4cdc0cd..ec865f71c4 100644 --- a/core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapAggregateStatusTest.java +++ b/core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapAggregateStatusManualTest.java @@ -14,7 +14,7 @@ import java.util.concurrent.TimeUnit; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; -public class ConcurrentMapAggregateStatusTest { +public class ConcurrentMapAggregateStatusManualTest { private ExecutorService executorService; private Map concurrentMap; diff --git a/core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapNullKeyValueTest.java b/core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapNullKeyValueManualTest.java similarity index 99% rename from core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapNullKeyValueTest.java rename to core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapNullKeyValueManualTest.java index 62a3d10add..33e3326427 100644 --- a/core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapNullKeyValueTest.java +++ b/core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapNullKeyValueManualTest.java @@ -10,7 +10,7 @@ import java.util.concurrent.ConcurrentMap; import static org.junit.Assert.assertNull; -public class ConcurrentMapNullKeyValueTest { +public class ConcurrentMapNullKeyValueManualTest { ConcurrentMap concurrentMap; diff --git a/core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapPerformanceTest.java b/core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapPerformanceManualTest.java similarity index 98% rename from core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapPerformanceTest.java rename to core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapPerformanceManualTest.java index a0efa89351..5c1612ca60 100644 --- a/core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapPerformanceTest.java +++ b/core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurrentMapPerformanceManualTest.java @@ -11,7 +11,7 @@ import java.util.concurrent.*; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -public class ConcurrentMapPerformanceTest { +public class ConcurrentMapPerformanceManualTest { @Test public void givenMaps_whenGetPut500KTimes_thenConcurrentMapFaster() throws Exception { diff --git a/core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurrentNavigableMapTests.java b/core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurrentNavigableMapManualTests.java similarity index 95% rename from core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurrentNavigableMapTests.java rename to core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurrentNavigableMapManualTests.java index 93087626a4..d102680aa4 100644 --- a/core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurrentNavigableMapTests.java +++ b/core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurrentNavigableMapManualTests.java @@ -10,7 +10,7 @@ import java.util.concurrent.atomic.AtomicInteger; import static org.testng.Assert.*; -public class ConcurrentNavigableMapTests { +public class ConcurrentNavigableMapManualTests { @Test public void givenSkipListMap_whenAccessInMultiThreads_thenOrderingStable() throws InterruptedException { @@ -18,9 +18,7 @@ public class ConcurrentNavigableMapTests { updateMapConcurrently(skipListMap, 4); - Iterator skipListIter = skipListMap - .keySet() - .iterator(); + Iterator skipListIter = skipListMap.keySet().iterator(); int previous = skipListIter.next(); while (skipListIter.hasNext()) { int current = skipListIter.next(); diff --git a/core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurretMapMemoryConsistencyTest.java b/core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurretMapMemoryConsistencyManualTest.java similarity index 97% rename from core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurretMapMemoryConsistencyTest.java rename to core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurretMapMemoryConsistencyManualTest.java index 63a96dd5ee..43cbb2d293 100644 --- a/core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurretMapMemoryConsistencyTest.java +++ b/core-java/src/test/java/com/baeldung/java/concurrentmap/ConcurretMapMemoryConsistencyManualTest.java @@ -10,7 +10,7 @@ import java.util.concurrent.TimeUnit; import static org.junit.Assert.*; -public class ConcurretMapMemoryConsistencyTest { +public class ConcurretMapMemoryConsistencyManualTest { @Test public void givenConcurrentMap_whenSumParallel_thenCorrect() throws Exception { diff --git a/core-java/src/test/java/com/baeldung/java/concurrentmodification/ConcurrentModificationUnitTest.java b/core-java/src/test/java/com/baeldung/java/concurrentmodification/ConcurrentModificationUnitTest.java new file mode 100644 index 0000000000..f7a7bd5fe0 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/java/concurrentmodification/ConcurrentModificationUnitTest.java @@ -0,0 +1,80 @@ +package com.baeldung.java.concurrentmodification; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.ConcurrentModificationException; +import java.util.Iterator; +import java.util.List; + +import static java.util.stream.Collectors.toList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.util.Lists.newArrayList; + +public class ConcurrentModificationUnitTest { + @Test(expected = ConcurrentModificationException.class) + public void givenIterating_whenRemoving_thenThrowException() throws InterruptedException { + + List integers = newArrayList(1, 2, 3); + + for (Integer integer : integers) { + integers.remove(1); + } + } + + @Test + public void givenIterating_whenUsingIteratorRemove_thenNoError() throws InterruptedException { + + List integers = newArrayList(1, 2, 3); + + for (Iterator iterator = integers.iterator(); iterator.hasNext();) { + Integer integer = iterator.next(); + if(integer == 2) { + iterator.remove(); + } + } + + assertThat(integers).containsExactly(1, 3); + } + + @Test + public void givenIterating_whenUsingRemovalList_thenNoError() throws InterruptedException { + + List integers = newArrayList(1, 2, 3); + List toRemove = newArrayList(); + + for (Integer integer : integers) { + if(integer == 2) { + toRemove.add(integer); + } + } + integers.removeAll(toRemove); + + assertThat(integers).containsExactly(1, 3); + } + + @Test + public void whenUsingRemoveIf_thenRemoveElements() throws InterruptedException { + + Collection integers = newArrayList(1, 2, 3); + + integers.removeIf(i -> i == 2); + + assertThat(integers).containsExactly(1, 3); + } + + @Test + public void whenUsingStream_thenRemoveElements() { + Collection integers = newArrayList(1, 2, 3); + + List collected = integers + .stream() + .filter(i -> i != 2) + .map(Object::toString) + .collect(toList()); + + assertThat(collected).containsExactly("1", "3"); + } + +} diff --git a/core-java/src/test/java/com/baeldung/java/map/README.md b/core-java/src/test/java/com/baeldung/java/map/README.md deleted file mode 100644 index 0bba153763..0000000000 --- a/core-java/src/test/java/com/baeldung/java/map/README.md +++ /dev/null @@ -1,2 +0,0 @@ -### Relevant Articles: -- [The Java HashMap Under the Hood](http://www.baeldung.com/java-hashmap) diff --git a/core-java/src/test/java/com/baeldung/java8/Java8GroupingByCollectorUnitTest.java b/core-java/src/test/java/com/baeldung/java8/Java8GroupingByCollectorUnitTest.java new file mode 100644 index 0000000000..4452b4db9a --- /dev/null +++ b/core-java/src/test/java/com/baeldung/java8/Java8GroupingByCollectorUnitTest.java @@ -0,0 +1,231 @@ +package com.baeldung.java8; + +import com.baeldung.java_8_features.groupingby.BlogPost; +import com.baeldung.java_8_features.groupingby.BlogPostType; +import org.junit.Test; + +import java.util.*; +import java.util.concurrent.ConcurrentMap; + +import static java.util.Comparator.comparingInt; +import static java.util.stream.Collectors.*; +import static org.junit.Assert.*; + +public class Java8GroupingByCollectorUnitTest { + + private static final List posts = Arrays.asList( + new BlogPost("News item 1", "Author 1", BlogPostType.NEWS, 15), + new BlogPost("Tech review 1", "Author 2", BlogPostType.REVIEW, 5), + new BlogPost("Programming guide", "Author 1", BlogPostType.GUIDE, 20), + new BlogPost("News item 2", "Author 2", BlogPostType.NEWS, 35), + new BlogPost("Tech review 2", "Author 1", BlogPostType.REVIEW, 15)); + + @Test + public void givenAListOfPosts_whenGroupedByType_thenGetAMapBetweenTypeAndPosts() { + Map> postsPerType = posts + .stream() + .collect(groupingBy(BlogPost::getType)); + + assertEquals(2, postsPerType + .get(BlogPostType.NEWS) + .size()); + assertEquals(1, postsPerType + .get(BlogPostType.GUIDE) + .size()); + assertEquals(2, postsPerType + .get(BlogPostType.REVIEW) + .size()); + } + + @Test + public void givenAListOfPosts_whenGroupedByTypeAndTheirTitlesAreJoinedInAString_thenGetAMapBetweenTypeAndCsvTitles() { + Map postsPerType = posts + .stream() + .collect(groupingBy(BlogPost::getType, mapping(BlogPost::getTitle, joining(", ", "Post titles: [", "]")))); + + assertEquals("Post titles: [News item 1, News item 2]", postsPerType.get(BlogPostType.NEWS)); + assertEquals("Post titles: [Programming guide]", postsPerType.get(BlogPostType.GUIDE)); + assertEquals("Post titles: [Tech review 1, Tech review 2]", postsPerType.get(BlogPostType.REVIEW)); + } + + @Test + public void givenAListOfPosts_whenGroupedByTypeAndSumTheLikes_thenGetAMapBetweenTypeAndPostLikes() { + Map likesPerType = posts + .stream() + .collect(groupingBy(BlogPost::getType, summingInt(BlogPost::getLikes))); + + assertEquals(50, likesPerType + .get(BlogPostType.NEWS) + .intValue()); + assertEquals(20, likesPerType + .get(BlogPostType.REVIEW) + .intValue()); + assertEquals(20, likesPerType + .get(BlogPostType.GUIDE) + .intValue()); + } + + @Test + public void givenAListOfPosts_whenGroupedByTypeInAnEnumMap_thenGetAnEnumMapBetweenTypeAndPosts() { + EnumMap> postsPerType = posts + .stream() + .collect(groupingBy(BlogPost::getType, () -> new EnumMap<>(BlogPostType.class), toList())); + + assertEquals(2, postsPerType + .get(BlogPostType.NEWS) + .size()); + assertEquals(1, postsPerType + .get(BlogPostType.GUIDE) + .size()); + assertEquals(2, postsPerType + .get(BlogPostType.REVIEW) + .size()); + } + + @Test + public void givenAListOfPosts_whenGroupedByTypeInSets_thenGetAMapBetweenTypesAndSetsOfPosts() { + Map> postsPerType = posts + .stream() + .collect(groupingBy(BlogPost::getType, toSet())); + + assertEquals(2, postsPerType + .get(BlogPostType.NEWS) + .size()); + assertEquals(1, postsPerType + .get(BlogPostType.GUIDE) + .size()); + assertEquals(2, postsPerType + .get(BlogPostType.REVIEW) + .size()); + } + + @Test + public void givenAListOfPosts_whenGroupedByTypeConcurrently_thenGetAMapBetweenTypeAndPosts() { + ConcurrentMap> postsPerType = posts + .parallelStream() + .collect(groupingByConcurrent(BlogPost::getType)); + + assertEquals(2, postsPerType + .get(BlogPostType.NEWS) + .size()); + assertEquals(1, postsPerType + .get(BlogPostType.GUIDE) + .size()); + assertEquals(2, postsPerType + .get(BlogPostType.REVIEW) + .size()); + } + + @Test + public void givenAListOfPosts_whenGroupedByTypeAndAveragingLikes_thenGetAMapBetweenTypeAndAverageNumberOfLikes() { + Map averageLikesPerType = posts + .stream() + .collect(groupingBy(BlogPost::getType, averagingInt(BlogPost::getLikes))); + + assertEquals(25, averageLikesPerType + .get(BlogPostType.NEWS) + .intValue()); + assertEquals(20, averageLikesPerType + .get(BlogPostType.GUIDE) + .intValue()); + assertEquals(10, averageLikesPerType + .get(BlogPostType.REVIEW) + .intValue()); + } + + @Test + public void givenAListOfPosts_whenGroupedByTypeAndCounted_thenGetAMapBetweenTypeAndNumberOfPosts() { + Map numberOfPostsPerType = posts + .stream() + .collect(groupingBy(BlogPost::getType, counting())); + + assertEquals(2, numberOfPostsPerType + .get(BlogPostType.NEWS) + .intValue()); + assertEquals(1, numberOfPostsPerType + .get(BlogPostType.GUIDE) + .intValue()); + assertEquals(2, numberOfPostsPerType + .get(BlogPostType.REVIEW) + .intValue()); + } + + @Test + public void givenAListOfPosts_whenGroupedByTypeAndMaxingLikes_thenGetAMapBetweenTypeAndMaximumNumberOfLikes() { + Map> maxLikesPerPostType = posts + .stream() + .collect(groupingBy(BlogPost::getType, maxBy(comparingInt(BlogPost::getLikes)))); + + assertTrue(maxLikesPerPostType + .get(BlogPostType.NEWS) + .isPresent()); + assertEquals(35, maxLikesPerPostType + .get(BlogPostType.NEWS) + .get() + .getLikes()); + + assertTrue(maxLikesPerPostType + .get(BlogPostType.GUIDE) + .isPresent()); + assertEquals(20, maxLikesPerPostType + .get(BlogPostType.GUIDE) + .get() + .getLikes()); + + assertTrue(maxLikesPerPostType + .get(BlogPostType.REVIEW) + .isPresent()); + assertEquals(15, maxLikesPerPostType + .get(BlogPostType.REVIEW) + .get() + .getLikes()); + } + + @Test + public void givenAListOfPosts_whenGroupedByAuthorAndThenByType_thenGetAMapBetweenAuthorAndMapsBetweenTypeAndBlogPosts() { + Map>> map = posts + .stream() + .collect(groupingBy(BlogPost::getAuthor, groupingBy(BlogPost::getType))); + + assertEquals(1, map + .get("Author 1") + .get(BlogPostType.NEWS) + .size()); + assertEquals(1, map + .get("Author 1") + .get(BlogPostType.GUIDE) + .size()); + assertEquals(1, map + .get("Author 1") + .get(BlogPostType.REVIEW) + .size()); + + assertEquals(1, map + .get("Author 2") + .get(BlogPostType.NEWS) + .size()); + assertEquals(1, map + .get("Author 2") + .get(BlogPostType.REVIEW) + .size()); + assertNull(map + .get("Author 2") + .get(BlogPostType.GUIDE)); + } + + @Test + public void givenAListOfPosts_whenGroupedByTypeAndSummarizingLikes_thenGetAMapBetweenTypeAndSummary() { + Map likeStatisticsPerType = posts + .stream() + .collect(groupingBy(BlogPost::getType, summarizingInt(BlogPost::getLikes))); + + IntSummaryStatistics newsLikeStatistics = likeStatisticsPerType.get(BlogPostType.NEWS); + + assertEquals(2, newsLikeStatistics.getCount()); + assertEquals(50, newsLikeStatistics.getSum()); + assertEquals(25.0, newsLikeStatistics.getAverage(), 0.001); + assertEquals(35, newsLikeStatistics.getMax()); + assertEquals(15, newsLikeStatistics.getMin()); + } + +} diff --git a/core-java/src/test/java/com/baeldung/java8/Java8MaxMinTest.java b/core-java/src/test/java/com/baeldung/java8/Java8MaxMinTest.java new file mode 100644 index 0000000000..b0e514124d --- /dev/null +++ b/core-java/src/test/java/com/baeldung/java8/Java8MaxMinTest.java @@ -0,0 +1,47 @@ +package com.baeldung.java8; + +import com.baeldung.java_8_features.Person; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.NoSuchElementException; + +import static org.junit.Assert.assertEquals; + +public class Java8MaxMinTest { + + @Test + public void whenListIsOfIntegerThenMaxCanBeDoneUsingIntegerComparator() { + //given + final List listOfIntegers = Arrays.asList(1, 2, 3, 4, 56, 7, 89, 10); + final Integer expectedResult = 89; + + //then + final Integer max = listOfIntegers + .stream() + .mapToInt(v -> v) + .max().orElseThrow(NoSuchElementException::new); + + assertEquals("Should be 89", expectedResult, max); + } + + @Test + public void whenListIsOfPersonObjectThenMinCanBeDoneUsingCustomComparatorThroughLambda() { + //given + final Person alex = new Person("Alex", 23); + final Person john = new Person("John", 40); + final Person peter = new Person("Peter", 32); + final List people = Arrays.asList(alex, john, peter); + + //then + final Person minByAge = people + .stream() + .min(Comparator.comparing(Person::getAge)) + .orElseThrow(NoSuchElementException::new); + + assertEquals("Should be Alex", alex, minByAge); + } + +} diff --git a/core-java/src/test/java/com/baeldung/junit4vstestng/DivisibilityTest.java b/core-java/src/test/java/com/baeldung/junit4vstestng/DivisibilityTest.java new file mode 100644 index 0000000000..dec7dbe6aa --- /dev/null +++ b/core-java/src/test/java/com/baeldung/junit4vstestng/DivisibilityTest.java @@ -0,0 +1,21 @@ +package com.baeldung.junit4vstestng; + +import static org.junit.Assert.assertEquals; + +import org.junit.BeforeClass; +import org.junit.Test; + +public class DivisibilityTest { + + private static int number; + + @BeforeClass + public static void setup() { + number = 40; + } + + @Test + public void givenNumber_whenDivisibleByTwo_thenCorrect() { + assertEquals(number % 2, 0); + } +} diff --git a/core-java/src/test/java/com/baeldung/junit4vstestng/ParametrizedTests.java b/core-java/src/test/java/com/baeldung/junit4vstestng/ParametrizedTests.java new file mode 100644 index 0000000000..e9a9c6a07a --- /dev/null +++ b/core-java/src/test/java/com/baeldung/junit4vstestng/ParametrizedTests.java @@ -0,0 +1,34 @@ +package com.baeldung.junit4vstestng; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.util.Arrays; +import java.util.Collection; + +@RunWith(value = Parameterized.class) +public class ParametrizedTests { + + private int value; + private boolean isEven; + + public ParametrizedTests(int value, boolean isEven) { + this.value = value; + this.isEven = isEven; + } + + @Parameters + public static Collection data() { + Object[][] data = new Object[][]{{1, false}, {2, true}, {4, true}}; + return Arrays.asList(data); + } + + @Test + public void givenParametrizedNumber_ifEvenCheckOK_thenCorrect() { + Assert.assertEquals(isEven, value % 2 == 0); + } +} diff --git a/core-java/src/test/java/com/baeldung/junit4vstestng/RegistrationTest.java b/core-java/src/test/java/com/baeldung/junit4vstestng/RegistrationTest.java new file mode 100644 index 0000000000..4aa1fa1a17 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/junit4vstestng/RegistrationTest.java @@ -0,0 +1,15 @@ +package com.baeldung.junit4vstestng; + +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class RegistrationTest { + private static final Logger LOGGER = LoggerFactory.getLogger(RegistrationTest.class); + + @Test + public void whenCalledFromSuite_thanOK() { + LOGGER.info("Registration successful"); + } +} diff --git a/core-java/src/test/java/com/baeldung/junit4vstestng/SignInTest.java b/core-java/src/test/java/com/baeldung/junit4vstestng/SignInTest.java new file mode 100644 index 0000000000..bb908ff37e --- /dev/null +++ b/core-java/src/test/java/com/baeldung/junit4vstestng/SignInTest.java @@ -0,0 +1,14 @@ +package com.baeldung.junit4vstestng; + +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SignInTest { + private static final Logger LOGGER = LoggerFactory.getLogger(SignInTest.class); + + @Test + public void whenCalledFromSuite_thanOK() { + LOGGER.info("SignIn successful"); + } +} diff --git a/core-java/src/test/java/com/baeldung/junit4vstestng/StringCaseTest.java b/core-java/src/test/java/com/baeldung/junit4vstestng/StringCaseTest.java new file mode 100644 index 0000000000..520017e4c1 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/junit4vstestng/StringCaseTest.java @@ -0,0 +1,22 @@ +package com.baeldung.junit4vstestng; + +import static org.junit.Assert.assertEquals; + +import org.junit.BeforeClass; +import org.junit.Test; + +public class StringCaseTest { + + private static String data; + + @BeforeClass + public static void setup() { + data = "HELLO BAELDUNG"; + } + + @Test + public void givenString_whenAllCaps_thenCorrect() { + assertEquals(data.toUpperCase(), data); + } + +} diff --git a/core-java/src/test/java/com/baeldung/junit4vstestng/SuiteTest.java b/core-java/src/test/java/com/baeldung/junit4vstestng/SuiteTest.java new file mode 100644 index 0000000000..effd7fa10a --- /dev/null +++ b/core-java/src/test/java/com/baeldung/junit4vstestng/SuiteTest.java @@ -0,0 +1,10 @@ +package com.baeldung.junit4vstestng; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ RegistrationTest.class, SignInTest.class }) +public class SuiteTest { + +} diff --git a/core-java/src/test/java/com/baeldung/junit4vstestng/SummationServiceTest.java b/core-java/src/test/java/com/baeldung/junit4vstestng/SummationServiceTest.java new file mode 100644 index 0000000000..7d1bf3b7af --- /dev/null +++ b/core-java/src/test/java/com/baeldung/junit4vstestng/SummationServiceTest.java @@ -0,0 +1,58 @@ +package com.baeldung.junit4vstestng; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +public class SummationServiceTest { + private static List numbers; + + @BeforeClass + public static void initialize() { + numbers = new ArrayList<>(); + } + + @AfterClass + public static void tearDown() { + numbers = null; + } + + @Before + public void runBeforeEachTest() { + numbers.add(1); + numbers.add(2); + numbers.add(3); + } + + @After + public void runAfterEachTest() { + numbers.clear(); + } + + @Test + public void givenNumbers_sumEquals_thenCorrect() { + int sum = numbers.stream() + .reduce(0, Integer::sum); + Assert.assertEquals(6, sum); + } + + @Ignore + @Test + public void givenEmptyList_sumEqualsZero_thenCorrect() { + int sum = numbers.stream() + .reduce(0, Integer::sum); + Assert.assertEquals(6, sum); + } + + @Test(expected = ArithmeticException.class) + public void givenNumber_whenThrowsException_thenCorrect() { + int i = 1 / 0; + } +} diff --git a/core-java/src/test/java/com/baeldung/strategy/StrategyDesignPatternUnitTest.java b/core-java/src/test/java/com/baeldung/strategy/StrategyDesignPatternUnitTest.java new file mode 100644 index 0000000000..7ca1d000be --- /dev/null +++ b/core-java/src/test/java/com/baeldung/strategy/StrategyDesignPatternUnitTest.java @@ -0,0 +1,73 @@ +package com.baeldung.strategy; + +import org.junit.Test; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; + +import static com.baeldung.strategy.Discounter.*; +import static org.assertj.core.api.Assertions.assertThat; + +public class StrategyDesignPatternUnitTest { + @Test + public void shouldDivideByTwo_WhenApplyingStaffDiscounter() { + Discounter staffDiscounter = new EasterDiscounter(); + + final BigDecimal discountedValue = staffDiscounter + .apply(BigDecimal.valueOf(100)); + + assertThat(discountedValue) + .isEqualByComparingTo(BigDecimal.valueOf(50)); + } + + @Test + public void shouldDivideByTwo_WhenApplyingStaffDiscounterWithAnonyousTypes() { + Discounter staffDiscounter = new Discounter() { + @Override + public BigDecimal apply( BigDecimal amount) { + return amount.multiply(BigDecimal.valueOf(0.5)); + } + }; + + final BigDecimal discountedValue = staffDiscounter + .apply(BigDecimal.valueOf(100)); + + assertThat(discountedValue) + .isEqualByComparingTo(BigDecimal.valueOf(50)); + } + + @Test + public void shouldDivideByTwo_WhenApplyingStaffDiscounterWithLamda() { + Discounter staffDiscounter = amount -> amount.multiply(BigDecimal.valueOf(0.5)); + + final BigDecimal discountedValue = staffDiscounter + .apply(BigDecimal.valueOf(100)); + + assertThat(discountedValue) + .isEqualByComparingTo(BigDecimal.valueOf(50)); + } + + @Test + public void shouldApplyAllDiscounts() { + List discounters = Arrays.asList(christmas(), newYear(), easter()); + + BigDecimal amount = BigDecimal.valueOf(100); + + final Discounter combinedDiscounter = discounters + .stream() + .reduce(v -> v, Discounter::combine); + + combinedDiscounter.apply(amount); + } + + @Test + public void shouldChainDiscounters() { + final Function combinedDiscounters = Discounter + .christmas() + .andThen(newYear()); + + combinedDiscounters.apply(BigDecimal.valueOf(100)); + } +} diff --git a/core-java/src/test/java/com/baeldung/stream/InfiniteStreamTest.java b/core-java/src/test/java/com/baeldung/stream/InfiniteStreamTest.java new file mode 100644 index 0000000000..a1537a1735 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/stream/InfiniteStreamTest.java @@ -0,0 +1,48 @@ +package com.baeldung.stream; + + +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.Random; +import java.util.UUID; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.junit.Assert.assertEquals; + +public class InfiniteStreamTest { + + @Test + public void givenInfiniteStream_whenUseIntermediateLimitMethod_thenShouldTerminateInFiniteTime() { + //given + Stream infiniteStream = Stream.iterate(0, i -> i + 2); + + //when + List collect = infiniteStream + .limit(10) + .collect(Collectors.toList()); + + //then + assertEquals(collect, Arrays.asList(0, 2, 4, 6, 8, 10, 12, 14, 16, 18)); + } + + @Test + public void givenInfiniteStreamOfRandomInts_whenUseLimit_shouldTerminateInFiniteTime() { + //given + Supplier randomUUIDSupplier = UUID::randomUUID; + Stream infiniteStreamOfRandomUUID = Stream.generate(randomUUIDSupplier); + + //when + List randomInts = infiniteStreamOfRandomUUID + .skip(10) + .limit(10) + .collect(Collectors.toList()); + + //then + assertEquals(randomInts.size(), 10); + } + +} diff --git a/core-java/src/test/java/com/baeldung/string/JoinerSplitterTest.java b/core-java/src/test/java/com/baeldung/string/JoinerSplitterTest.java new file mode 100644 index 0000000000..a89f89b8d5 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/string/JoinerSplitterTest.java @@ -0,0 +1,68 @@ +package com.baeldung.string; + +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import com.baeldung.string.JoinerSplitter; + +public class JoinerSplitterTest { + + @Test + public void provided_array_convert_to_stream_and_convert_to_string() { + + String[] programming_languages = {"java", "python", "nodejs", "ruby"}; + + String expectation = "java,python,nodejs,ruby"; + + String result = JoinerSplitter.join(programming_languages); + assertEquals(result, expectation); + } + + @Test + public void givenArray_transformedToStream_convertToPrefixPostfixString() { + + String[] programming_languages = {"java", "python", + "nodejs", "ruby"}; + String expectation = "[java,python,nodejs,ruby]"; + + String result = JoinerSplitter.joinWithPrefixPostFix(programming_languages); + assertEquals(result, expectation); + } + + @Test + public void givenString_transformedToStream_convertToList() { + + String programming_languages = "java,python,nodejs,ruby"; + + List expectation = new ArrayList(); + expectation.add("java"); + expectation.add("python"); + expectation.add("nodejs"); + expectation.add("ruby"); + + List result = JoinerSplitter.split(programming_languages); + + assertEquals(result, expectation); + } + + @Test + public void givenString_transformedToStream_convertToListOfChar() { + + String programming_languages = "java,python,nodejs,ruby"; + + List expectation = new ArrayList(); + char[] charArray = programming_languages.toCharArray(); + for (char c : charArray) { + expectation.add(c); + } + + List result = JoinerSplitter.splitToListOfChar(programming_languages); + assertEquals(result, expectation); + + } + +} diff --git a/core-java/src/test/java/com/baeldung/weakhashmap/WeakHashMapTest.java b/core-java/src/test/java/com/baeldung/weakhashmap/WeakHashMapTest.java new file mode 100644 index 0000000000..1c5a261eea --- /dev/null +++ b/core-java/src/test/java/com/baeldung/weakhashmap/WeakHashMapTest.java @@ -0,0 +1,72 @@ +package com.baeldung.weakhashmap; + + +import org.junit.Test; + +import java.util.WeakHashMap; +import java.util.concurrent.TimeUnit; + +import static com.jayway.awaitility.Awaitility.await; +import static org.junit.Assert.assertTrue; + +public class WeakHashMapTest { + + @Test + public void givenWeakHashMap_whenCacheValueThatHasNoReferenceToIt_GCShouldReclaimThatObject() { + //given + WeakHashMap map = new WeakHashMap<>(); + BigImage bigImage = new BigImage("image_id"); + UniqueImageName imageName = new UniqueImageName("name_of_big_image"); + + map.put(imageName, bigImage); + assertTrue(map.containsKey(imageName)); + + //when big image key is not reference anywhere + imageName = null; + System.gc(); + + //then GC will finally reclaim that object + await().atMost(10, TimeUnit.SECONDS).until(map::isEmpty); + } + + @Test + public void givenWeakHashMap_whenCacheValueThatHasNoReferenceToIt_GCShouldReclaimThatObjectButLeaveReferencedObject() { + //given + WeakHashMap map = new WeakHashMap<>(); + BigImage bigImageFirst = new BigImage("foo"); + UniqueImageName imageNameFirst = new UniqueImageName("name_of_big_image"); + + BigImage bigImageSecond = new BigImage("foo_2"); + UniqueImageName imageNameSecond = new UniqueImageName("name_of_big_image_2"); + + map.put(imageNameFirst, bigImageFirst); + map.put(imageNameSecond, bigImageSecond); + assertTrue(map.containsKey(imageNameFirst)); + assertTrue(map.containsKey(imageNameSecond)); + + //when + imageNameFirst = null; + System.gc(); + + //then + await().atMost(10, TimeUnit.SECONDS).until(() -> map.size() == 1); + await().atMost(10, TimeUnit.SECONDS).until(() -> map.containsKey(imageNameSecond)); + } + + + class BigImage { + public final String imageId; + + BigImage(String imageId) { + this.imageId = imageId; + } + } + + class UniqueImageName { + public final String imageName; + + UniqueImageName(String imageName) { + this.imageName = imageName; + } + } +} diff --git a/core-java/src/test/java/org/baeldung/java/JavaRandomUnitTest.java b/core-java/src/test/java/org/baeldung/java/JavaRandomUnitTest.java index 4febe7c9fc..08f98025c3 100644 --- a/core-java/src/test/java/org/baeldung/java/JavaRandomUnitTest.java +++ b/core-java/src/test/java/org/baeldung/java/JavaRandomUnitTest.java @@ -1,12 +1,12 @@ package org.baeldung.java; -import java.nio.charset.Charset; -import java.util.Random; - import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.math3.random.RandomDataGenerator; import org.junit.Test; +import java.nio.charset.Charset; +import java.util.Random; + public class JavaRandomUnitTest { // tests - random long @@ -164,7 +164,7 @@ public class JavaRandomUnitTest { final int targetStringLength = 10; final StringBuilder buffer = new StringBuilder(targetStringLength); for (int i = 0; i < targetStringLength; i++) { - final int randomLimitedInt = leftLimit + (int) (new Random().nextFloat() * (rightLimit - leftLimit)); + final int randomLimitedInt = leftLimit + (int) (new Random().nextFloat() * (rightLimit - leftLimit + 1)); buffer.append((char) randomLimitedInt); } final String generatedString = buffer.toString(); diff --git a/core-java/src/test/java/org/baeldung/java/streams/ThreadPoolInParallelStreamTest.java b/core-java/src/test/java/org/baeldung/java/streams/ThreadPoolInParallelStreamTest.java index 5fd3fa4cb0..c2eb1cff5d 100644 --- a/core-java/src/test/java/org/baeldung/java/streams/ThreadPoolInParallelStreamTest.java +++ b/core-java/src/test/java/org/baeldung/java/streams/ThreadPoolInParallelStreamTest.java @@ -1,5 +1,5 @@ package org.baeldung.java.streams; - + import org.junit.Test; import java.util.ArrayList; @@ -14,28 +14,25 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; public class ThreadPoolInParallelStreamTest { - + @Test - public void giveRangeOfLongs_whenSummedInParallel_shouldBeEqualToExpectedTotal() - throws InterruptedException, ExecutionException { + public void giveRangeOfLongs_whenSummedInParallel_shouldBeEqualToExpectedTotal() throws InterruptedException, ExecutionException { long firstNum = 1; long lastNum = 1_000_000; - List aList = LongStream.rangeClosed(firstNum, lastNum).boxed() - .collect(Collectors.toList()); + List aList = LongStream.rangeClosed(firstNum, lastNum).boxed().collect(Collectors.toList()); ForkJoinPool customThreadPool = new ForkJoinPool(4); - long actualTotal = customThreadPool.submit(() -> aList.parallelStream() - .reduce(0L, Long::sum)).get(); - - assertEquals((lastNum + firstNum) * lastNum / 2, actualTotal); + long actualTotal = customThreadPool.submit(() -> aList.parallelStream().reduce(0L, Long::sum)).get(); + + assertEquals((lastNum + firstNum) * lastNum / 2, actualTotal); } - + @Test - public void givenList_whenCallingParallelStream_shouldBeParallelStream(){ + public void givenList_whenCallingParallelStream_shouldBeParallelStream() { List aList = new ArrayList<>(); Stream parallelStream = aList.parallelStream(); - + assertTrue(parallelStream.isParallel()); } } diff --git a/couchbase-sdk/README.md b/couchbase-sdk/README.md index 9cdcdea012..f124a0192c 100644 --- a/couchbase-sdk/README.md +++ b/couchbase-sdk/README.md @@ -4,6 +4,7 @@ - [Introduction to Couchbase SDK for Java](http://www.baeldung.com/java-couchbase-sdk) - [Using Couchbase in a Spring Application](http://www.baeldung.com/couchbase-sdk-spring) - [Asynchronous Batch Opereations in Couchbase](http://www.baeldung.com/async-batch-operations-in-couchbase) +- [Querying Couchbase with MapReduce Views](http://www.baeldung.com/couchbase-query-mapreduce-view) ### Overview This Maven project contains the Java code for the Couchbase entities and Spring services diff --git a/couchbase-sdk/pom.xml b/couchbase-sdk/pom.xml index 301fd81c51..1200fab454 100644 --- a/couchbase-sdk/pom.xml +++ b/couchbase-sdk/pom.xml @@ -102,10 +102,10 @@ 1.8 UTF-8 - 2.3.6 - 4.3.4.RELEASE - 1.1.7 - 1.7.21 + 2.4.0 + 4.3.5.RELEASE + 1.1.8 + 1.7.22 4.12 3.5 3.6.0 diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/mapreduce/CouchbaseKeyGenerator.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/mapreduce/CouchbaseKeyGenerator.java new file mode 100644 index 0000000000..9ac1bbb3f7 --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/mapreduce/CouchbaseKeyGenerator.java @@ -0,0 +1,6 @@ +package com.baeldung.couchbase.mapreduce; + +public interface CouchbaseKeyGenerator { + + String generateKey(T t); +} diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/mapreduce/DuplicateKeyException.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/mapreduce/DuplicateKeyException.java new file mode 100644 index 0000000000..78baaa155c --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/mapreduce/DuplicateKeyException.java @@ -0,0 +1,10 @@ +package com.baeldung.couchbase.mapreduce; + +@SuppressWarnings("serial") +public class DuplicateKeyException extends Exception { + + public DuplicateKeyException(String s) { + super(s); + } + +} diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/mapreduce/RandomUUIDGenerator.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/mapreduce/RandomUUIDGenerator.java new file mode 100644 index 0000000000..9baf4a4f43 --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/mapreduce/RandomUUIDGenerator.java @@ -0,0 +1,11 @@ +package com.baeldung.couchbase.mapreduce; + +import java.util.UUID; + +public class RandomUUIDGenerator implements CouchbaseKeyGenerator { + + @Override + public String generateKey(T t) { + return UUID.randomUUID().toString(); + } +} diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/mapreduce/StudentGrade.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/mapreduce/StudentGrade.java new file mode 100644 index 0000000000..846aba716a --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/mapreduce/StudentGrade.java @@ -0,0 +1,50 @@ +package com.baeldung.couchbase.mapreduce; + +public class StudentGrade { + + private String name; + private String course; + private Integer grade; + private Integer hours; + + public StudentGrade() { } + + public StudentGrade(String name, String course, Integer grade, Integer hours) { + this.name = name; + this.course = course; + this.grade = grade; + this.hours = hours; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCourse() { + return course; + } + + public void setCourse(String course) { + this.course = course; + } + + public Integer getGrade() { + return grade; + } + + public void setGrade(Integer grade) { + this.grade = grade; + } + + public Integer getHours() { + return hours; + } + + public void setHours(Integer hours) { + this.hours = hours; + } +} diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/mapreduce/StudentGradeKeyGenerator.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/mapreduce/StudentGradeKeyGenerator.java new file mode 100644 index 0000000000..680e37ba57 --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/mapreduce/StudentGradeKeyGenerator.java @@ -0,0 +1,9 @@ +package com.baeldung.couchbase.mapreduce; + +public class StudentGradeKeyGenerator implements CouchbaseKeyGenerator { + + @Override + public String generateKey(StudentGrade g) { + return g.getName() + ":" + g.getCourse(); + } +} diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/mapreduce/StudentGradeQueryBuilder.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/mapreduce/StudentGradeQueryBuilder.java new file mode 100644 index 0000000000..37bb03645a --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/mapreduce/StudentGradeQueryBuilder.java @@ -0,0 +1,70 @@ +package com.baeldung.couchbase.mapreduce; + +import com.couchbase.client.deps.com.fasterxml.jackson.databind.ObjectMapper; +import com.couchbase.client.java.document.json.JsonArray; +import com.couchbase.client.java.view.ViewQuery; + +public class StudentGradeQueryBuilder { + + final ObjectMapper om = new ObjectMapper(); + + public ViewQuery findAll() { + return ViewQuery.from("studentGrades", "findByCourse"); + } + + public ViewQuery findByCourse(String course) { + return ViewQuery.from("studentGrades", "findByCourse") + .key(course); + } + + public ViewQuery findByCourses(String... courses) { + return ViewQuery.from("studentGrades", "findByCourse") + .keys(JsonArray.from(courses)); + } + + public ViewQuery findByGradeInRange(int lower, int upper, boolean inclusiveEnd) { + return ViewQuery.from("studentGrades", "findByGrade") + .startKey(lower) + .endKey(upper) + .inclusiveEnd(inclusiveEnd); + } + + public ViewQuery findByGradeLessThan(int upper) { + return ViewQuery.from("studentGrades", "findByGrade") + .endKey(upper) + .inclusiveEnd(false); + } + + public ViewQuery findByGradeGreaterThan(int lower) { + return ViewQuery.from("studentGrades", "findByGrade") + .startKey(lower); + } + + public ViewQuery findByCourseAndGradeInRange(String course, int minGrade, int maxGrade, boolean inclusiveEnd) { + return ViewQuery.from("studentGrades", "findByCourseAndGrade") + .startKey(JsonArray.from(course, minGrade)) + .endKey(JsonArray.from(course, maxGrade)) + .inclusiveEnd(inclusiveEnd); + } + + public ViewQuery findTopGradesByCourse(String course, int limit) { + return ViewQuery.from("studentGrades", "findByCourseAndGrade") + .startKey(JsonArray.from(course, 100)) + .endKey(JsonArray.from(course, 0)) + .inclusiveEnd(true) + .descending() + .limit(limit); + } + + public ViewQuery countStudentsByCourse() { + return ViewQuery.from("studentGrades", "countStudentsByCourse") + .reduce() + .groupLevel(1); + } + + public ViewQuery sumCreditsByStudent() { + return ViewQuery.from("studentGrades", "sumCreditsByStudent") + .reduce() + .groupLevel(1); + } +} diff --git a/couchbase-sdk/src/main/java/com/baeldung/couchbase/mapreduce/StudentGradeService.java b/couchbase-sdk/src/main/java/com/baeldung/couchbase/mapreduce/StudentGradeService.java new file mode 100644 index 0000000000..2d2c63f699 --- /dev/null +++ b/couchbase-sdk/src/main/java/com/baeldung/couchbase/mapreduce/StudentGradeService.java @@ -0,0 +1,169 @@ +package com.baeldung.couchbase.mapreduce; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import com.couchbase.client.deps.com.fasterxml.jackson.databind.ObjectMapper; +import com.couchbase.client.java.Bucket; +import com.couchbase.client.java.CouchbaseCluster; +import com.couchbase.client.java.document.JsonDocument; +import com.couchbase.client.java.document.json.JsonArray; +import com.couchbase.client.java.document.json.JsonObject; +import com.couchbase.client.java.view.ViewQuery; +import com.couchbase.client.java.view.ViewResult; +import com.couchbase.client.java.view.ViewRow; + +public class StudentGradeService { + + final CouchbaseKeyGenerator keyGenerator; + final CouchbaseCluster cluster; + final Bucket bucket; + final ObjectMapper om = new ObjectMapper(); + final StudentGradeQueryBuilder queryBuilder; + + public StudentGradeService(CouchbaseKeyGenerator keyGenerator) { + this.keyGenerator = keyGenerator; + this.queryBuilder = new StudentGradeQueryBuilder(); + cluster = CouchbaseCluster.create("127.0.0.1"); + bucket = cluster.openBucket("baeldung-tutorial"); + } + + public String insert(StudentGrade studentGrade) throws DuplicateKeyException { + String id = keyGenerator.generateKey(studentGrade); + if(bucket.exists(id)) { + throw new DuplicateKeyException("document already exists with key " + id); + } + JsonObject content = JsonObject.empty() + .put("type", "StudentGrade") + .put("name", studentGrade.getName()) + .put("course", studentGrade.getCourse()) + .put("grade", studentGrade.getGrade()) + .put("hours", studentGrade.getHours()); + JsonDocument doc = JsonDocument.create(id, content); + bucket.insert(doc); + return id; + } + + public List findAll() { + ViewQuery query = queryBuilder.findAll(); + ViewResult result = bucket.query(query); + return extractDocuments(result); + } + + private List extractDocuments(ViewResult result) { + List docs = new ArrayList<>(); + for(ViewRow row : result.allRows()) { + JsonDocument doc = row.document(); + docs.add(doc); + } + return docs; + } + + public List findByCourse(String course) { + ViewQuery query = queryBuilder.findByCourse(course); + ViewResult result = bucket.query(query); + return extractDocuments(result); + } + + public List findByCourses(String... courses) { + ViewQuery query = queryBuilder.findByCourses(courses); + ViewResult result = bucket.query(query); + return extractDocuments(result); + } + + public List findByGradeInRange(int lower, int upper, boolean inclusiveEnd) { + ViewQuery query = queryBuilder.findByGradeInRange(lower, upper, inclusiveEnd); + ViewResult result = bucket.query(query); + return extractDocuments(result); + } + + public List findByGradeLessThan(int upper) { + ViewQuery query = queryBuilder.findByGradeLessThan(upper); + ViewResult result = bucket.query(query); + return extractDocuments(result); + } + + public List findByGradeGreaterThan(int lower) { + ViewQuery query = queryBuilder.findByGradeGreaterThan(lower); + ViewResult result = bucket.query(query); + return extractDocuments(result); + } + + public List findByCourseAndGradeInRange(String course, int minGrade, int maxGrade, boolean inclusiveEnd) { + ViewQuery query = queryBuilder.findByCourseAndGradeInRange(course, minGrade, maxGrade, inclusiveEnd); + ViewResult result = bucket.query(query); + return extractDocuments(result); + } + + public List findTopGradesByCourse(String course, int limit) { + ViewQuery query = queryBuilder.findTopGradesByCourse(course, limit); + ViewResult result = bucket.query(query); + return extractDocuments(result); + } + + public Map countStudentsByCourse() { + ViewQuery query = ViewQuery.from("studentGrades", "countStudentsByCourse") + .reduce() + .groupLevel(1); + ViewResult result = bucket.query(query); + + Map numStudentsByCourse = new HashMap<>(); + for(ViewRow row : result.allRows()) { + JsonArray keyArray = (JsonArray) row.key(); + String course = keyArray.getString(0); + long count = Long.valueOf(row.value().toString()); + numStudentsByCourse.put(course, count); + } + + return numStudentsByCourse; + } + + public Map sumCreditHoursByStudent() { + ViewQuery query = ViewQuery.from("studentGrades", "sumHoursByStudent") + .reduce() + .groupLevel(1); + ViewResult result = bucket.query(query); + + Map creditHoursByStudent = new HashMap<>(); + for(ViewRow row : result.allRows()) { + String course = (String) row.key(); + long sum = Long.valueOf(row.value().toString()); + creditHoursByStudent.put(course, sum); + } + + return creditHoursByStudent; + } + + public Map sumGradePointsByStudent() { + ViewQuery query = ViewQuery.from("studentGrades", "sumGradePointsByStudent") + .reduce() + .groupLevel(1); + ViewResult result = bucket.query(query); + + Map gradePointsByStudent = new HashMap<>(); + for(ViewRow row : result.allRows()) { + String course = (String) row.key(); + long sum = Long.valueOf(row.value().toString()); + gradePointsByStudent.put(course, sum); + } + + return gradePointsByStudent; + } + + public Map calculateGpaByStudent() { + Map creditHoursByStudent = sumCreditHoursByStudent(); + Map gradePointsByStudent = sumGradePointsByStudent(); + + Map result = new HashMap<>(); + for(Entry creditHoursEntry : creditHoursByStudent.entrySet()) { + String name = creditHoursEntry.getKey(); + long totalHours = creditHoursEntry.getValue(); + long totalGradePoints = gradePointsByStudent.get(name); + result.put(name, ((float) totalGradePoints / totalHours)); + } + return result; + } +} diff --git a/couchbase-sdk/src/test/java/com/baeldung/couchbase/mapreduce/StudentGradeServiceIntegrationTest.java b/couchbase-sdk/src/test/java/com/baeldung/couchbase/mapreduce/StudentGradeServiceIntegrationTest.java new file mode 100644 index 0000000000..00d462e32a --- /dev/null +++ b/couchbase-sdk/src/test/java/com/baeldung/couchbase/mapreduce/StudentGradeServiceIntegrationTest.java @@ -0,0 +1,150 @@ +package com.baeldung.couchbase.mapreduce; + +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.couchbase.client.java.document.JsonDocument; +import com.couchbase.client.java.view.ViewResult; +import com.couchbase.client.java.view.ViewRow; + +public class StudentGradeServiceIntegrationTest { + private static final Logger logger = LoggerFactory.getLogger(StudentGradeServiceIntegrationTest.class); + + static StudentGradeService studentGradeService; + static Set gradeIds = new HashSet<>(); + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + studentGradeService = new StudentGradeService(new StudentGradeKeyGenerator()); + insertStudentGrade(new StudentGrade("John Doe", "History", 80, 3)); + insertStudentGrade(new StudentGrade("Jane Doe", "History", 89, 3)); + insertStudentGrade(new StudentGrade("Bob Smith", "History", 90, 3)); + insertStudentGrade(new StudentGrade("Mary Jones", "History", 92, 3)); + insertStudentGrade(new StudentGrade("Jane Doe", "Math", 59, 3)); + insertStudentGrade(new StudentGrade("Bob Smith", "Math", 91, 3)); + insertStudentGrade(new StudentGrade("Mary Jones", "Math", 86, 3)); + insertStudentGrade(new StudentGrade("John Doe", "Science", 85, 4)); + insertStudentGrade(new StudentGrade("Bob Smith", "Science", 97, 4)); + insertStudentGrade(new StudentGrade("Mary Jones", "Science", 84, 4)); + } + + private static void insertStudentGrade(StudentGrade studentGrade) { + try { + String id = studentGradeService.insert(studentGrade); + gradeIds.add(id); + } catch (DuplicateKeyException e) { + } + } + + @Test + public final void whenFindAll_thenSuccess() { + List docs = studentGradeService.findAll(); + printDocuments(docs); + } + + @Test + public final void whenFindByCourse_thenSuccess() { + List docs = studentGradeService.findByCourse("History"); + printDocuments(docs); + } + + @Test + public final void whenFindByCourses_thenSuccess() { + List docs = studentGradeService.findByCourses("History", "Science"); + printDocuments(docs); + } + + @Test + public final void whenFindByGradeInRange_thenSuccess() { + List docs = studentGradeService.findByGradeInRange(80, 89, true); + printDocuments(docs); + } + + @Test + public final void whenFindByGradeLessThan_thenSuccess() { + List docs = studentGradeService.findByGradeLessThan(60); + printDocuments(docs); + } + + @Test + public final void whenFindByGradeGreaterThan_thenSuccess() { + List docs = studentGradeService.findByGradeGreaterThan(90); + printDocuments(docs); + } + + @Test + public final void whenFindByCourseAndGradeInRange_thenSuccess() { + List docs = studentGradeService.findByCourseAndGradeInRange("Math", 80, 89, true); + printDocuments(docs); + } + + @Test + public final void whenFindTopGradesByCourse_thenSuccess() { + List docs = studentGradeService.findTopGradesByCourse("Science", 2); + printDocuments(docs); + } + + @Test + public final void whenCountStudentsByCourse_thenSuccess() { + Map map = studentGradeService.countStudentsByCourse(); + printMap(map); + } + + @Test + public final void whenSumCreditHoursByStudent_thenSuccess() { + Map map = studentGradeService.sumCreditHoursByStudent(); + printMap(map); + } + + @Test + public final void whenSumGradePointsByStudent_thenSuccess() { + Map map = studentGradeService.sumGradePointsByStudent(); + printMap(map); + } + + @Test + public final void whenCalculateGpaByStudent_thenSuccess() { + Map map = studentGradeService.calculateGpaByStudent(); + printGpaMap(map); + } + + private void printMap(Map map) { + for(Map.Entry entry : map.entrySet()) { + logger.info(entry.getKey() + "=" + entry.getValue()); + } + } + + private void printGpaMap(Map map) { + for(Map.Entry entry : map.entrySet()) { + logger.info(entry.getKey() + "=" + entry.getValue()); + } + } + + private void printDocuments(List docs) { + for(JsonDocument doc : docs) { + String key = doc.id(); + logger.info(key + " = " + doc.content().toString()); + } + } + + private void printViewResultDocuments(ViewResult result) { + for(ViewRow row : result.allRows()) { + JsonDocument doc = row.document(); + String key = doc.id(); + logger.info(key + "=" + doc.content().toString()); + } + } + + private void printViewResultRows(ViewResult result) { + for(ViewRow row : result.allRows()) { + logger.info(row.toString()); + } + } +} diff --git a/couchbase-sdk/src/test/resources/logback.xml b/couchbase-sdk/src/test/resources/logback.xml new file mode 100644 index 0000000000..efcc6fb4c7 --- /dev/null +++ b/couchbase-sdk/src/test/resources/logback.xml @@ -0,0 +1,17 @@ + + + + + web - %date [%thread] %-5level %logger{36} - %message%n + + + + + + + + + + + + \ No newline at end of file diff --git a/disruptor/README.md b/disruptor/README.md index e69de29bb2..779b1e89c4 100644 --- a/disruptor/README.md +++ b/disruptor/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Concurrency with LMAX Disruptor – An Introduction](http://www.baeldung.com/lmax-disruptor-concurrency) diff --git a/ejb/README.md b/ejb/README.md new file mode 100644 index 0000000000..08392bc80d --- /dev/null +++ b/ejb/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Guide to EJB Set-up](http://www.baeldung.com/ejb-intro) diff --git a/guava/README.md b/guava/README.md index 40e7f19f41..ee224bae5f 100644 --- a/guava/README.md +++ b/guava/README.md @@ -16,3 +16,11 @@ - [Guava – Sets](http://www.baeldung.com/guava-sets) - [Guava – Maps](http://www.baeldung.com/guava-maps) - [Guava Set + Function = Map](http://www.baeldung.com/guava-set-function-map-tutorial) +- [Guide to Guava’s Ordering](http://www.baeldung.com/guava-ordering) +- [Guide to Guava’s PreConditions](http://www.baeldung.com/guava-preconditions) +- [Introduction to Guava CacheLoader](http://www.baeldung.com/guava-cacheloader) +- [Guide to Guava’s EventBus](http://www.baeldung.com/guava-eventbus) +- [Guide to Guava Multimap](http://www.baeldung.com/guava-multimap) +- [Guide to Guava RangeSet](http://www.baeldung.com/guava-rangeset) +- [Guide to Guava RangeMap](http://www.baeldung.com/guava-rangemap) +- [Guide to Guava Table](http://www.baeldung.com/guava-table) diff --git a/guava/pom.xml b/guava/pom.xml index f65a9a2081..0edbb90efd 100644 --- a/guava/pom.xml +++ b/guava/pom.xml @@ -57,6 +57,32 @@ test + + + + org.slf4j + slf4j-api + ${org.slf4j.version} + + + ch.qos.logback + logback-classic + ${logback.version} + + + + org.slf4j + jcl-over-slf4j + ${org.slf4j.version} + + + + org.slf4j + log4j-over-slf4j + ${org.slf4j.version} + + + org.assertj assertj-core @@ -112,6 +138,9 @@ 3.6.0 2.19.1 + + 1.7.21 + 1.1.7 \ No newline at end of file diff --git a/guava/src/test/java/org/baeldung/guava/CustomEvent.java b/guava/src/main/java/org/baeldung/guava/CustomEvent.java similarity index 99% rename from guava/src/test/java/org/baeldung/guava/CustomEvent.java rename to guava/src/main/java/org/baeldung/guava/CustomEvent.java index 78348065b2..2d5c3382d4 100644 --- a/guava/src/test/java/org/baeldung/guava/CustomEvent.java +++ b/guava/src/main/java/org/baeldung/guava/CustomEvent.java @@ -1,6 +1,5 @@ package org.baeldung.guava; - public class CustomEvent { private String action; diff --git a/guava/src/main/java/org/baeldung/guava/EventListener.java b/guava/src/main/java/org/baeldung/guava/EventListener.java new file mode 100644 index 0000000000..438fcade63 --- /dev/null +++ b/guava/src/main/java/org/baeldung/guava/EventListener.java @@ -0,0 +1,38 @@ +package org.baeldung.guava; + +import com.google.common.eventbus.DeadEvent; +import com.google.common.eventbus.Subscribe; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class EventListener { + + private static int eventsHandled; + private static final Logger LOG = LoggerFactory.getLogger(EventListener.class); + + @Subscribe + public void stringEvent(String event) { + LOG.info("do event [" + event + "]"); + eventsHandled++; + } + + @Subscribe + public void someCustomEvent(CustomEvent customEvent) { + LOG.info("do event [" + customEvent.getAction() + "]"); + eventsHandled++; + } + + @Subscribe + public void handleDeadEvent(DeadEvent deadEvent) { + LOG.info("unhandled event [" + deadEvent.getEvent() + "]"); + eventsHandled++; + } + + public int getEventsHandled() { + return eventsHandled; + } + + public void resetEventsHandled() { + eventsHandled = 0; + } +} diff --git a/guava/src/test/java/org/baeldung/guava/EventBusWrapper.java b/guava/src/test/java/org/baeldung/guava/EventBusWrapper.java deleted file mode 100644 index eddaca0baf..0000000000 --- a/guava/src/test/java/org/baeldung/guava/EventBusWrapper.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.baeldung.guava; - -import com.google.common.eventbus.EventBus; - -class EventBusWrapper { - - private static EventBus eventBus = new EventBus(); - - static void register(Object object){ - eventBus.register(object); - } - - static void unregister(Object object){ - eventBus.unregister(object); - } - - static void post(Object object){ - eventBus.post(object); - } - - -} diff --git a/guava/src/test/java/org/baeldung/guava/EventListener.java b/guava/src/test/java/org/baeldung/guava/EventListener.java deleted file mode 100644 index 17a3ac093e..0000000000 --- a/guava/src/test/java/org/baeldung/guava/EventListener.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.baeldung.guava; -import com.google.common.eventbus.Subscribe; - -public class EventListener { - - private static int eventsHandled; - - /** - * Handles events of type String * - */ - @Subscribe - public void stringEvent(String event){ - System.out.println("do event ["+event+"]"); - eventsHandled++; - } - - /** - * Handles events of type CustomEvent - */ - @Subscribe - public void someEvent(CustomEvent customEvent){ - System.out.println("do event ["+ customEvent.getAction()+"]"); - eventsHandled++; - } - - public int getEventsHandled() { - return eventsHandled; - } - - public void resetEventsHandled(){ - eventsHandled = 0; - } -} diff --git a/guava/src/test/java/org/baeldung/guava/GuavaCacheLoaderTest.java b/guava/src/test/java/org/baeldung/guava/GuavaCacheLoaderTest.java new file mode 100644 index 0000000000..2aa2e6140b --- /dev/null +++ b/guava/src/test/java/org/baeldung/guava/GuavaCacheLoaderTest.java @@ -0,0 +1,71 @@ +package org.baeldung.guava; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; +import org.assertj.core.api.Assertions; +import org.junit.Test; + +import java.util.Map; +import java.util.concurrent.ExecutionException; + +import static com.google.common.collect.Iterables.cycle; +import static com.google.common.collect.Maps.newHashMap; +import static org.assertj.core.api.Assertions.assertThat; + +public class GuavaCacheLoaderTest { + int callCount = 0; + + @Test + public void givenAMap_whenAddingValues_thenCanTreatThemAsCache() { + Map cache = newHashMap(); + cache.put("foo", "cachedValueForFoo"); + cache.put("bar", "cachedValueForBar"); + + assertThat(cache.get("foo")).isEqualTo("cachedValueForFoo"); + assertThat(cache.get("bar")).isEqualTo("cachedValueForBar"); + } + + @Test + public void givenCacheLoader_whenGettingItemTwice_shouldOnlyCallOnce() throws ExecutionException { + + final LoadingCache loadingCache = CacheBuilder.newBuilder() + .build(new CacheLoader() { + @Override + public String load(final String s) throws Exception { + return slowMethod(s); + } + }); + + String value = loadingCache.get("key"); + value = loadingCache.get("key"); + + assertThat(callCount).isEqualTo(1); + assertThat(value).isEqualTo("key"); + } + + @Test + public void givenCacheLoader_whenRefreshingItem_shouldCallAgain() throws ExecutionException { + + final LoadingCache loadingCache = CacheBuilder.newBuilder() + .build(new CacheLoader() { + @Override + public String load(final String s) throws Exception { + return slowMethod(s); + } + }); + + String value = loadingCache.get("key"); + loadingCache.refresh("key"); + + assertThat(callCount).isEqualTo(2); + assertThat(value).isEqualTo("key"); + } + + private String slowMethod(final String s) { + callCount++; + return s; + } +} diff --git a/guava/src/test/java/org/baeldung/guava/GuavaEventBusTest.java b/guava/src/test/java/org/baeldung/guava/GuavaEventBusTest.java index bd966187ab..1390eb05aa 100644 --- a/guava/src/test/java/org/baeldung/guava/GuavaEventBusTest.java +++ b/guava/src/test/java/org/baeldung/guava/GuavaEventBusTest.java @@ -1,5 +1,6 @@ package org.baeldung.guava; +import com.google.common.eventbus.EventBus; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -9,34 +10,46 @@ import static org.junit.Assert.*; public class GuavaEventBusTest { private EventListener listener; + private EventBus eventBus; @Before - public void setUp() throws Exception { + public void setUp() { + eventBus = new EventBus(); listener = new EventListener(); - EventBusWrapper.register(listener); + + eventBus.register(listener); } @After - public void tearDown() throws Exception { - EventBusWrapper.unregister(listener); + public void tearDown() { + eventBus.unregister(listener); } @Test - public void givenStringEvent_whenEventHandled_thenSuccess() throws Exception { + public void givenStringEvent_whenEventHandled_thenSuccess() { listener.resetEventsHandled(); - EventBusWrapper.post("String Event"); + eventBus.post("String Event"); assertEquals(1, listener.getEventsHandled()); - } @Test - public void givenCustomEvent_whenEventHandled_thenSuccess() throws Exception { + public void givenCustomEvent_whenEventHandled_thenSuccess() { listener.resetEventsHandled(); CustomEvent customEvent = new CustomEvent("Custom Event"); - EventBusWrapper.post(customEvent); + eventBus.post(customEvent); assertEquals(1, listener.getEventsHandled()); } + + @Test + public void givenUnSubscribedEvent_whenEventHandledByDeadEvent_thenSuccess() throws InterruptedException { + listener.resetEventsHandled(); + + eventBus.post(12345); + + assertEquals(1, listener.getEventsHandled()); + } + } diff --git a/guava/src/test/java/org/baeldung/guava/GuavaPreConditionsTest.java b/guava/src/test/java/org/baeldung/guava/GuavaPreConditionsTest.java index 55e3c7db00..2d98418d48 100644 --- a/guava/src/test/java/org/baeldung/guava/GuavaPreConditionsTest.java +++ b/guava/src/test/java/org/baeldung/guava/GuavaPreConditionsTest.java @@ -3,7 +3,7 @@ package org.baeldung.guava; import static org.assertj.core.api.Assertions.assertThatThrownBy; import java.util.Arrays; import org.junit.Test; -import static com.google.common.base.Preconditions.*; +import com.google.common.base.*; public class GuavaPreConditionsTest { @@ -11,10 +11,7 @@ public class GuavaPreConditionsTest { public void whenCheckArgumentEvaluatesFalse_throwsException() { int age = -18; - assertThatThrownBy(() -> checkArgument(age > 0)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage(null) - .hasNoCause(); + assertThatThrownBy(() -> Preconditions.checkArgument(age > 0)).isInstanceOf(IllegalArgumentException.class).hasMessage(null).hasNoCause(); } @Test @@ -22,10 +19,7 @@ public class GuavaPreConditionsTest { final int age = -18; final String message = "Age can't be zero or less than zero"; - assertThatThrownBy(() -> checkArgument(age > 0, message)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage(message) - .hasNoCause(); + assertThatThrownBy(() -> Preconditions.checkArgument(age > 0, message)).isInstanceOf(IllegalArgumentException.class).hasMessage(message).hasNoCause(); } @Test @@ -33,19 +27,14 @@ public class GuavaPreConditionsTest { final int age = -18; final String message = "Age can't be zero or less than zero, you supplied %s."; - assertThatThrownBy(() -> checkArgument(age > 0, message, age)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage(message, age) - .hasNoCause(); + assertThatThrownBy(() -> Preconditions.checkArgument(age > 0, message, age)).isInstanceOf(IllegalArgumentException.class).hasMessage(message, age).hasNoCause(); } @Test public void givenArrayOfIntegers_whenCheckElementIndexEvaluatesFalse_throwsException() { final int[] numbers = { 1, 2, 3, 4, 5 }; - assertThatThrownBy(() -> checkElementIndex(6, numbers.length - 1)) - .isInstanceOf(IndexOutOfBoundsException.class) - .hasNoCause(); + assertThatThrownBy(() -> Preconditions.checkElementIndex(6, numbers.length - 1)).isInstanceOf(IndexOutOfBoundsException.class).hasNoCause(); } @Test @@ -53,20 +42,7 @@ public class GuavaPreConditionsTest { final int[] numbers = { 1, 2, 3, 4, 5 }; final String message = "Please check the bound of an array and retry"; - assertThatThrownBy(() -> checkElementIndex(6, numbers.length - 1, message)) - .isInstanceOf(IndexOutOfBoundsException.class) - .hasMessageStartingWith(message) - .hasNoCause(); - } - - @Test - public void givenNullString_whenCheckNotNullCalled_throwsException() { - final String nullObject = null; - - assertThatThrownBy(() -> checkNotNull(nullObject)) - .isInstanceOf(NullPointerException.class) - .hasMessage(null) - .hasNoCause(); + assertThatThrownBy(() -> Preconditions.checkElementIndex(6, numbers.length - 1, message)).isInstanceOf(IndexOutOfBoundsException.class).hasMessageStartingWith(message).hasNoCause(); } @Test @@ -74,10 +50,7 @@ public class GuavaPreConditionsTest { final String nullObject = null; final String message = "Please check the Object supplied, its null!"; - assertThatThrownBy(() -> checkNotNull(nullObject, message)) - .isInstanceOf(NullPointerException.class) - .hasMessage(message) - .hasNoCause(); + assertThatThrownBy(() -> Preconditions.checkNotNull(nullObject, message)).isInstanceOf(NullPointerException.class).hasMessage(message).hasNoCause(); } @Test @@ -85,19 +58,14 @@ public class GuavaPreConditionsTest { final String nullObject = null; final String message = "Please check the Object supplied, its %s!"; - assertThatThrownBy(() -> checkNotNull(nullObject, message, nullObject)) - .isInstanceOf(NullPointerException.class) - .hasMessage(message, nullObject) - .hasNoCause(); + assertThatThrownBy(() -> Preconditions.checkNotNull(nullObject, message, new Object[] { null })).isInstanceOf(NullPointerException.class).hasMessage(message, nullObject).hasNoCause(); } @Test public void givenArrayOfIntegers_whenCheckPositionIndexEvaluatesFalse_throwsException() { final int[] numbers = { 1, 2, 3, 4, 5 }; - assertThatThrownBy(() -> checkPositionIndex(6, numbers.length - 1)) - .isInstanceOf(IndexOutOfBoundsException.class) - .hasNoCause(); + assertThatThrownBy(() -> Preconditions.checkPositionIndex(6, numbers.length - 1)).isInstanceOf(IndexOutOfBoundsException.class).hasNoCause(); } @Test @@ -105,30 +73,14 @@ public class GuavaPreConditionsTest { final int[] numbers = { 1, 2, 3, 4, 5 }; final String message = "Please check the bound of an array and retry"; - assertThatThrownBy(() -> checkPositionIndex(6, numbers.length - 1, message)) - .isInstanceOf(IndexOutOfBoundsException.class) - .hasMessageStartingWith(message) - .hasNoCause(); + assertThatThrownBy(() -> Preconditions.checkPositionIndex(6, numbers.length - 1, message)).isInstanceOf(IndexOutOfBoundsException.class).hasMessageStartingWith(message).hasNoCause(); } @Test public void givenArrayOfIntegers_whenCheckPositionIndexesEvaluatesFalse_throwsException() { final int[] numbers = { 1, 2, 3, 4, 5 }; - assertThatThrownBy(() -> checkPositionIndexes(6, 0, numbers.length - 1)) - .isInstanceOf(IndexOutOfBoundsException.class) - .hasNoCause(); - } - - @Test - public void givenValidStates_whenCheckStateEvaluatesFalse_throwsException() { - final int[] validStates = { -1, 0, 1 }; - final int givenState = 10; - - assertThatThrownBy(() -> checkState(Arrays.binarySearch(validStates, givenState) > 0)) - .isInstanceOf(IllegalStateException.class) - .hasMessage(null) - .hasNoCause(); + assertThatThrownBy(() -> Preconditions.checkPositionIndexes(6, 0, numbers.length - 1)).isInstanceOf(IndexOutOfBoundsException.class).hasNoCause(); } @Test @@ -137,10 +89,7 @@ public class GuavaPreConditionsTest { final int givenState = 10; final String message = "You have entered an invalid state"; - assertThatThrownBy(() -> checkState(Arrays.binarySearch(validStates, givenState) > 0, message)) - .isInstanceOf(IllegalStateException.class) - .hasMessageStartingWith(message) - .hasNoCause(); + assertThatThrownBy(() -> Preconditions.checkState(Arrays.binarySearch(validStates, givenState) > 0, message)).isInstanceOf(IllegalStateException.class).hasMessageStartingWith(message).hasNoCause(); } @Test @@ -149,9 +98,7 @@ public class GuavaPreConditionsTest { final int givenState = 10; final String message = "State can't be %s, It can be one of %s."; - assertThatThrownBy(() -> checkState(Arrays.binarySearch(validStates, givenState) > 0, message, givenState, Arrays.toString(validStates))) - .isInstanceOf(IllegalStateException.class) - .hasMessage(message, givenState, Arrays.toString(validStates)) - .hasNoCause(); + assertThatThrownBy(() -> Preconditions.checkState(Arrays.binarySearch(validStates, givenState) > 0, message, givenState, Arrays.toString(validStates))).isInstanceOf(IllegalStateException.class) + .hasMessage(message, givenState, Arrays.toString(validStates)).hasNoCause(); } -} +} \ No newline at end of file diff --git a/httpclient/README.md b/httpclient/README.md index a848edfea6..2a98c2feac 100644 --- a/httpclient/README.md +++ b/httpclient/README.md @@ -19,3 +19,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Multipart Upload with HttpClient 4](http://www.baeldung.com/httpclient-multipart-upload) - [HttpAsyncClient Tutorial](http://www.baeldung.com/httpasyncclient-tutorial) - [HttpClient 4 Tutorial](http://www.baeldung.com/httpclient-guide) +- [Advanced HttpClient Configuration](http://www.baeldung.com/httpclient-advanced-config) diff --git a/httpclient/pom.xml b/httpclient/pom.xml index be0daae995..eec705b224 100644 --- a/httpclient/pom.xml +++ b/httpclient/pom.xml @@ -1,4 +1,5 @@ - + 4.0.0 com.baeldung httpclient @@ -113,6 +114,13 @@ ${mockito.version} test + + com.github.tomakehurst + wiremock + ${wiremock.version} + test + + @@ -145,7 +153,7 @@ **/*LiveTest.java - + @@ -202,6 +210,7 @@ 1.3 4.12 1.10.19 + 2.5.1 4.4.5 4.5.2 diff --git a/httpclient/src/test/java/org/baeldung/httpclient/advancedconfig/HttpClientAdvancedConfiguration.java b/httpclient/src/test/java/org/baeldung/httpclient/advancedconfig/HttpClientAdvancedConfiguration.java new file mode 100644 index 0000000000..9b5cb3f293 --- /dev/null +++ b/httpclient/src/test/java/org/baeldung/httpclient/advancedconfig/HttpClientAdvancedConfiguration.java @@ -0,0 +1,154 @@ +package org.baeldung.httpclient.advancedconfig; + + +import com.github.tomakehurst.wiremock.junit.WireMockRule; +import org.apache.http.HttpHeaders; +import org.apache.http.HttpHost; +import org.apache.http.HttpResponse; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.AuthCache; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.auth.BasicScheme; +import org.apache.http.impl.client.BasicAuthCache; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.DefaultProxyRoutePlanner; +import org.junit.Rule; +import org.junit.Test; + +import java.io.IOException; + +import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static org.junit.Assert.assertEquals; + +public class HttpClientAdvancedConfiguration { + + @Rule + public WireMockRule serviceMock = new WireMockRule(8089); + + @Rule + public WireMockRule proxyMock = new WireMockRule(8090); + + @Test + public void givenClientWithCustomUserAgentHeader_whenExecuteRequest_shouldReturn200() throws IOException { + //given + String userAgent = "BaeldungAgent/1.0"; + serviceMock.stubFor(get(urlEqualTo("/detail")) + .withHeader("User-Agent", equalTo(userAgent)) + .willReturn(aResponse() + .withStatus(200))); + + HttpClient httpClient = HttpClients.createDefault(); + HttpGet httpGet = new HttpGet("http://localhost:8089/detail"); + httpGet.setHeader(HttpHeaders.USER_AGENT, userAgent); + + //when + HttpResponse response = httpClient.execute(httpGet); + + //then + assertEquals(response.getStatusLine().getStatusCode(), 200); + } + + @Test + public void givenClientThatSendDataInBody_whenSendXmlInBody_shouldReturn200() throws IOException { + //given + String xmlBody = "1"; + serviceMock.stubFor(post(urlEqualTo("/person")) + .withHeader("Content-Type", equalTo("application/xml")) + .withRequestBody(equalTo(xmlBody)) + .willReturn(aResponse() + .withStatus(200))); + + HttpClient httpClient = HttpClients.createDefault(); + HttpPost httpPost = new HttpPost("http://localhost:8089/person"); + httpPost.setHeader("Content-Type", "application/xml"); + StringEntity xmlEntity = new StringEntity(xmlBody); + httpPost.setEntity(xmlEntity); + + //when + HttpResponse response = httpClient.execute(httpPost); + + //then + assertEquals(response.getStatusLine().getStatusCode(), 200); + + } + + @Test + public void givenServerThatIsBehindProxy_whenClientIsConfiguredToSendRequestViaProxy_shouldReturn200() throws IOException { + //given + proxyMock.stubFor(get(urlMatching(".*")) + .willReturn(aResponse().proxiedFrom("http://localhost:8089/"))); + + serviceMock.stubFor(get(urlEqualTo("/private")) + .willReturn(aResponse().withStatus(200))); + + + HttpHost proxy = new HttpHost("localhost", 8090); + DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy); + HttpClient httpclient = HttpClients.custom() + .setRoutePlanner(routePlanner) + .build(); + + //when + final HttpGet httpGet = new HttpGet("http://localhost:8089/private"); + HttpResponse response = httpclient.execute(httpGet); + + //then + assertEquals(response.getStatusLine().getStatusCode(), 200); + proxyMock.verify(getRequestedFor(urlEqualTo("/private"))); + serviceMock.verify(getRequestedFor(urlEqualTo("/private"))); + } + + @Test + public void givenServerThatIsBehindAuthorizationProxy_whenClientSendRequest_shouldAuthorizeProperly() throws IOException { + //given + proxyMock.stubFor(get(urlMatching("/private")) + .willReturn(aResponse().proxiedFrom("http://localhost:8089/"))); + serviceMock.stubFor(get(urlEqualTo("/private")) + .willReturn(aResponse().withStatus(200))); + + + HttpHost proxy = new HttpHost("localhost", 8090); + DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy); + + // Client credentials + CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials(new AuthScope(proxy), + new UsernamePasswordCredentials("username_admin", "secret_password")); + + + // Create AuthCache instance + AuthCache authCache = new BasicAuthCache(); + + // Generate BASIC scheme object and add it to the local auth cache + BasicScheme basicAuth = new BasicScheme(); + authCache.put(proxy, basicAuth); + HttpClientContext context = HttpClientContext.create(); + context.setCredentialsProvider(credentialsProvider); + context.setAuthCache(authCache); + + + HttpClient httpclient = HttpClients.custom() + .setRoutePlanner(routePlanner) + .setDefaultCredentialsProvider(credentialsProvider) + .build(); + + + //when + final HttpGet httpGet = new HttpGet("http://localhost:8089/private"); + HttpResponse response = httpclient.execute(httpGet, context); + + //then + assertEquals(response.getStatusLine().getStatusCode(), 200); + proxyMock.verify(getRequestedFor(urlEqualTo("/private")).withHeader("Authorization", containing("Basic"))); + serviceMock.verify(getRequestedFor(urlEqualTo("/private"))); + } + + +} diff --git a/hystrix/pom.xml b/hystrix/pom.xml index 5e050d726e..ba1a596631 100644 --- a/hystrix/pom.xml +++ b/hystrix/pom.xml @@ -11,7 +11,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/jackson/README.md b/jackson/README.md index 67a03589a8..d9faa377f1 100644 --- a/jackson/README.md +++ b/jackson/README.md @@ -25,3 +25,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [More Jackson Annotations](http://www.baeldung.com/jackson-advanced-annotations) - [Inheritance with Jackson](http://www.baeldung.com/jackson-inheritance) - [Guide to @JsonFormat in Jackson](http://www.baeldung.com/jackson-jsonformat) +- [A Guide to Optional with Jackson](http://www.baeldung.com/jackson-optional) diff --git a/jackson/pom.xml b/jackson/pom.xml index 53fb82c61e..881ba8e24c 100644 --- a/jackson/pom.xml +++ b/jackson/pom.xml @@ -67,6 +67,12 @@ ${jackson.version} + + com.fasterxml.jackson.datatype + jackson-datatype-jdk8 + ${jackson.version} + + joda-time joda-time @@ -128,8 +134,8 @@ ${mockito.version} test - - + + org.slf4j @@ -152,7 +158,7 @@ org.slf4j log4j-over-slf4j ${org.slf4j.version} - + @@ -189,7 +195,7 @@ - 2.8.5 + 2.8.6 1.7.21 @@ -198,7 +204,7 @@ 19.0 3.5 - 2.5 + 2.5 2.9.6 2.8.0 4.1 diff --git a/jackson/src/main/java/com/baeldung/jackson/entities/ActorJackson.java b/jackson/src/main/java/com/baeldung/jackson/entities/ActorJackson.java index f6a8b0cf61..76f87d80b3 100644 --- a/jackson/src/main/java/com/baeldung/jackson/entities/ActorJackson.java +++ b/jackson/src/main/java/com/baeldung/jackson/entities/ActorJackson.java @@ -4,6 +4,7 @@ import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; +import java.util.Locale; import java.util.TimeZone; public class ActorJackson { @@ -53,7 +54,7 @@ public class ActorJackson { } private String formatDateOfBirth() { - final DateFormat formatter = new SimpleDateFormat("EEE MMM dd hh:mm:ss zzz yyyy"); + final DateFormat formatter = new SimpleDateFormat("EEE MMM dd hh:mm:ss zzz yyyy", Locale.US); formatter.setTimeZone(TimeZone.getTimeZone("GMT")); return formatter.format(dateOfBirth); } diff --git a/jackson/src/main/java/com/baeldung/jackson/miscellaneous/mixin/Book.java b/jackson/src/main/java/com/baeldung/jackson/miscellaneous/mixin/Book.java new file mode 100644 index 0000000000..fb961efe85 --- /dev/null +++ b/jackson/src/main/java/com/baeldung/jackson/miscellaneous/mixin/Book.java @@ -0,0 +1,25 @@ +package com.baeldung.jackson.miscellaneous.mixin; + +import java.util.Optional; + +public class Book { + + private String title; + private Optional subTitle; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Optional getSubTitle() { + return subTitle; + } + + public void setSubTitle(Optional subTitle) { + this.subTitle = subTitle; + } +} diff --git a/jackson/src/test/java/com/baeldung/jackson/deserialization/JacksonDeserializeTest.java b/jackson/src/test/java/com/baeldung/jackson/deserialization/JacksonDeserializeTest.java index 7e91df5332..cb3bccb879 100644 --- a/jackson/src/test/java/com/baeldung/jackson/deserialization/JacksonDeserializeTest.java +++ b/jackson/src/test/java/com/baeldung/jackson/deserialization/JacksonDeserializeTest.java @@ -3,12 +3,10 @@ package com.baeldung.jackson.deserialization; import java.io.IOException; import java.text.DateFormat; import java.text.SimpleDateFormat; - import com.baeldung.jackson.entities.Movie; -import org.junit.Assert; import org.junit.Test; - import com.fasterxml.jackson.databind.ObjectMapper; +import static org.junit.Assert.assertEquals; public class JacksonDeserializeTest { @@ -20,7 +18,7 @@ public class JacksonDeserializeTest { final Movie movie = mapper.readValue(jsonInput, Movie.class); final String expectedOutput = "Movie [imdbId=tt0472043, director=null, actors=[ActorJackson [imdbId=nm2199632, dateOfBirth=Tue Sep 21 11:00:00 GMT 1982, filmography=[Apocalypto, Beatdown, Wind Walkers]]]]"; - Assert.assertEquals(movie.toString(), expectedOutput); + assertEquals(expectedOutput, movie.toString()); } @Test @@ -35,7 +33,7 @@ public class JacksonDeserializeTest { final Movie movie = mapper.readValue(jsonInput, Movie.class); final String expectedOutput = "Movie [imdbId=tt0472043, director=Mel Gibson, actors=[ActorJackson [imdbId=nm2199632, dateOfBirth=Tue Sep 21 11:00:00 GMT 1982, filmography=[Apocalypto, Beatdown, Wind Walkers]]]]"; - Assert.assertEquals(movie.toString(), expectedOutput); + assertEquals(expectedOutput, movie.toString()); } } diff --git a/jackson/src/test/java/com/baeldung/jackson/miscellaneous/mixin/OptionalTypeTest.java b/jackson/src/test/java/com/baeldung/jackson/miscellaneous/mixin/OptionalTypeTest.java new file mode 100644 index 0000000000..c6d51cd57f --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/miscellaneous/mixin/OptionalTypeTest.java @@ -0,0 +1,61 @@ +package com.baeldung.jackson.miscellaneous.mixin; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; +import static io.restassured.path.json.JsonPath.from; +import java.io.IOException; +import java.util.Optional; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; + +public class OptionalTypeTest { + + ObjectMapper mapper = new ObjectMapper().registerModule(new Jdk8Module()); + + @Test + public void givenPresentOptional_whenSerializing_thenValueInJson() throws JsonProcessingException { + + String subTitle = "The Parish Boy's Progress"; + Book book = new Book(); + book.setTitle("Oliver Twist"); + book.setSubTitle(Optional.of(subTitle)); + + String result = mapper.writeValueAsString(book); + + assertThat(from(result).getString("subTitle")).isEqualTo(subTitle); + } + + @Test + public void givenEmptyOptional_whenSerializing_thenNullValue() throws JsonProcessingException { + + Book book = new Book(); + book.setTitle("Oliver Twist"); + book.setSubTitle(Optional.empty()); + + String result = mapper.writeValueAsString(book); + + assertThat(from(result).getString("subTitle")).isNull(); + } + + @Test + public void givenField_whenDeserializingIntoOptional_thenIsPresentWithValue() throws IOException { + + String subTitle = "The Parish Boy's Progress"; + String book = "{ \"title\": \"Oliver Twist\", \"subTitle\": \"" + subTitle + "\" }"; + + Book result = mapper.readValue(book, Book.class); + + assertThat(result.getSubTitle()).isEqualTo(Optional.of(subTitle)); + } + + @Test + public void givenNullField_whenDeserializingIntoOptional_thenIsEmpty() throws IOException { + + String book = "{ \"title\": \"Oliver Twist\", \"subTitle\": null }"; + + Book result = mapper.readValue(book, Book.class); + + assertThat(result.getSubTitle()).isEmpty(); + } +} diff --git a/java-mongodb/README.md b/java-mongodb/README.md new file mode 100644 index 0000000000..01245ac6cf --- /dev/null +++ b/java-mongodb/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [A Guide to MongoDB with Java](http://www.baeldung.com/java-mongodb) diff --git a/javaslang/README.md b/javaslang/README.md index 334ac02f60..e451883516 100644 --- a/javaslang/README.md +++ b/javaslang/README.md @@ -1,2 +1,4 @@ ### Relevant Articles: - [Introduction to Javaslang](http://www.baeldung.com/javaslang) +- [Guide to Try in Javaslang](http://www.baeldung.com/javaslang-try) +- [Guide to Pattern Matching in Javaslang](http://www.baeldung.com/javaslang-pattern-matching) diff --git a/jee7/README.md b/jee7/README.md index 44ca9c2f6e..bc242c3340 100644 --- a/jee7/README.md +++ b/jee7/README.md @@ -1,2 +1,3 @@ ### Relevant Articles: - [Scheduling in Java EE](http://www.baeldung.com/scheduling-in-java-enterprise-edition) +- [JSON Processing in Java EE 7](http://www.baeldung.com/jee7-json) diff --git a/jee7/src/main/java/com/baeldung/javaeeannotations/AccountServlet.java b/jee7/src/main/java/com/baeldung/javaeeannotations/AccountServlet.java new file mode 100644 index 0000000000..e3f1667595 --- /dev/null +++ b/jee7/src/main/java/com/baeldung/javaeeannotations/AccountServlet.java @@ -0,0 +1,57 @@ +package com.baeldung.javaeeannotations; + +import java.io.IOException; +import java.io.PrintWriter; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.annotation.HttpConstraint; +import javax.servlet.annotation.HttpMethodConstraint; +import javax.servlet.annotation.ServletSecurity; +import javax.servlet.annotation.WebInitParam; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@WebServlet( + name = "BankAccountServlet", + description = "Represents a Bank Account and it's transactions", + urlPatterns = {"/account", "/bankAccount" }, + initParams = { @WebInitParam(name = "type", value = "savings") } + ) +@ServletSecurity( + value = @HttpConstraint(rolesAllowed = {"admin"}), + httpMethodConstraints = {@HttpMethodConstraint(value = "POST", rolesAllowed = {"admin"})} + ) +public class AccountServlet extends javax.servlet.http.HttpServlet { + + String accountType = null; + + @Override + public void init(ServletConfig config) throws ServletException { + accountType = config.getInitParameter("type"); + } + + public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { + PrintWriter writer = response.getWriter(); + writer.println("Hello, I am an AccountServlet!"); + writer.flush(); + } + + public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { + double accountBalance = 1000d; + double interestRate = Double.parseDouble(request.getAttribute("interest").toString()); + + String paramDepositAmt = request.getParameter("dep"); + double depositAmt = Double.parseDouble(paramDepositAmt); + + accountBalance = accountBalance + depositAmt; + + PrintWriter writer = response.getWriter(); + writer.println(" Balance of " + accountType + " account is: " + + accountBalance + "
This account bares an interest rate of " + interestRate + + " % "); + writer.flush(); + + } +} diff --git a/jee7/src/main/java/com/baeldung/javaeeannotations/BankAppServletContextListener.java b/jee7/src/main/java/com/baeldung/javaeeannotations/BankAppServletContextListener.java new file mode 100644 index 0000000000..6b43dd8a84 --- /dev/null +++ b/jee7/src/main/java/com/baeldung/javaeeannotations/BankAppServletContextListener.java @@ -0,0 +1,17 @@ +package com.baeldung.javaeeannotations; + +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.annotation.WebListener; + +@WebListener +public class BankAppServletContextListener implements ServletContextListener { + + public void contextInitialized(ServletContextEvent sce) { + sce.getServletContext().setAttribute("ATTR_DEFAULT_LANGUAGE", "english"); + } + + public void contextDestroyed(ServletContextEvent sce) { + System.out.println("CONTEXT DESTROYED"); + } +} diff --git a/jee7/src/main/java/com/baeldung/javaeeannotations/LoggingFilter.java b/jee7/src/main/java/com/baeldung/javaeeannotations/LoggingFilter.java new file mode 100644 index 0000000000..97de5ec0de --- /dev/null +++ b/jee7/src/main/java/com/baeldung/javaeeannotations/LoggingFilter.java @@ -0,0 +1,36 @@ +package com.baeldung.javaeeannotations; + +import java.io.IOException; + +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.annotation.WebFilter; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@WebFilter( + urlPatterns = "/bankAccount/*", + filterName = "LoggingFilter", + description = "Filter all account transaction URLs" + ) +public class LoggingFilter implements javax.servlet.Filter { + @Override + public void init(FilterConfig filterConfig) throws ServletException { + } + + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + HttpServletRequest req = (HttpServletRequest) request; + HttpServletResponse res = (HttpServletResponse) response; + + res.sendRedirect(req.getContextPath() + "/login.jsp"); + chain.doFilter(request, response); + } + + @Override + public void destroy() { + } + +} diff --git a/jee7/src/main/java/com/baeldung/javaeeannotations/UploadCustomerDocumentsServlet.java b/jee7/src/main/java/com/baeldung/javaeeannotations/UploadCustomerDocumentsServlet.java new file mode 100644 index 0000000000..8a6c709b81 --- /dev/null +++ b/jee7/src/main/java/com/baeldung/javaeeannotations/UploadCustomerDocumentsServlet.java @@ -0,0 +1,29 @@ +package com.baeldung.javaeeannotations; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.annotation.MultipartConfig; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.Part; + +@WebServlet(urlPatterns = { "/uploadCustDocs" }) +@MultipartConfig( + fileSizeThreshold = 1024 * 1024 * 20, + maxFileSize = 1024 * 1024 * 20, + maxRequestSize = 1024 * 1024 * 25, + location = "D:/custDocs" + ) +public class UploadCustomerDocumentsServlet extends HttpServlet { + + protected void doPost( + HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + for (Part part : request.getParts()) { + part.write("myFile"); + } + } + +} diff --git a/jee7/src/main/webapp/WEB-INF/web.xml b/jee7/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..0a3d84d2d4 --- /dev/null +++ b/jee7/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,11 @@ + + + + BASIC + default + + + \ No newline at end of file diff --git a/jee7/src/main/webapp/index.jsp b/jee7/src/main/webapp/index.jsp new file mode 100644 index 0000000000..0c389ef5b1 --- /dev/null +++ b/jee7/src/main/webapp/index.jsp @@ -0,0 +1,16 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + + + + +My Account + + +
+ Width: +    + +
+ + \ No newline at end of file diff --git a/jee7/src/main/webapp/login.jsp b/jee7/src/main/webapp/login.jsp new file mode 100644 index 0000000000..885df0c3d9 --- /dev/null +++ b/jee7/src/main/webapp/login.jsp @@ -0,0 +1,12 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + + + + +Login + + +Login Here... + + \ No newline at end of file diff --git a/jee7/src/main/webapp/upload.jsp b/jee7/src/main/webapp/upload.jsp new file mode 100644 index 0000000000..020483b99f --- /dev/null +++ b/jee7/src/main/webapp/upload.jsp @@ -0,0 +1,16 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + + + + +Insert title here + + +
+ +
+ +
+ + \ No newline at end of file diff --git a/jjwt/pom.xml b/jjwt/pom.xml index c1332fa2d7..982b24987b 100644 --- a/jjwt/pom.xml +++ b/jjwt/pom.xml @@ -14,7 +14,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/jooq/pom.xml b/jooq/pom.xml new file mode 100644 index 0000000000..ef287d0292 --- /dev/null +++ b/jooq/pom.xml @@ -0,0 +1,46 @@ + + + + parent-modules + com.baeldung + 1.0.0-SNAPSHOT + + 4.0.0 + + jooq + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + + + org.jooq + jool + ${jool.version} + + + junit + junit + ${junit.version} + test + + + + + 0.9.12 + 4.12 + + + + \ No newline at end of file diff --git a/jooq/src/test/java/com/baeldung/JOOLTest.java b/jooq/src/test/java/com/baeldung/JOOLTest.java new file mode 100644 index 0000000000..13bf1a3ec3 --- /dev/null +++ b/jooq/src/test/java/com/baeldung/JOOLTest.java @@ -0,0 +1,243 @@ +package com.baeldung; + + +import junit.framework.Assert; +import org.jooq.lambda.Seq; +import org.jooq.lambda.Unchecked; +import org.jooq.lambda.function.Function1; +import org.jooq.lambda.function.Function2; +import org.jooq.lambda.tuple.Tuple; +import org.jooq.lambda.tuple.Tuple2; +import org.jooq.lambda.tuple.Tuple3; +import org.jooq.lambda.tuple.Tuple4; +import org.junit.Test; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static junit.framework.Assert.assertTrue; +import static junit.framework.TestCase.assertEquals; +import static org.jooq.lambda.tuple.Tuple.tuple; + +public class JOOLTest { + @Test + public void givenSeq_whenCheckContains_shouldReturnTrue() { + List concat = Seq.of(1, 2, 3).concat(Seq.of(4, 5, 6)).toList(); + + assertEquals(concat, Arrays.asList(1, 2, 3, 4, 5, 6)); + + + assertTrue(Seq.of(1, 2, 3, 4).contains(2)); + + + assertTrue(Seq.of(1, 2, 3, 4).containsAll(2, 3)); + + + assertTrue(Seq.of(1, 2, 3, 4).containsAny(2, 5)); + } + + @Test + public void givenStreams_whenJoin_shouldHaveElementsFromTwoStreams() { + //given + Stream left = Stream.of(1, 2, 4); + Stream right = Stream.of(1, 2, 3); + + //when + List rightCollected = right.collect(Collectors.toList()); + List collect = left.filter(rightCollected::contains).collect(Collectors.toList()); + + //then + assertEquals(collect, Arrays.asList(1, 2)); + } + + @Test + public void givenSeq_whenJoin_shouldHaveElementsFromBothSeq() { + assertEquals( + Seq.of(1, 2, 4).innerJoin(Seq.of(1, 2, 3), (a, b) -> a == b).toList(), + Arrays.asList(tuple(1, 1), tuple(2, 2)) + ); + + + assertEquals( + Seq.of(1, 2, 4).leftOuterJoin(Seq.of(1, 2, 3), (a, b) -> a == b).toList(), + Arrays.asList(tuple(1, 1), tuple(2, 2), tuple(4, null)) + ); + + assertEquals( + Seq.of(1, 2, 4).rightOuterJoin(Seq.of(1, 2, 3), (a, b) -> a == b).toList(), + Arrays.asList(tuple(1, 1), tuple(2, 2), tuple(null, 3)) + ); + + assertEquals( + Seq.of(1, 2).crossJoin(Seq.of("A", "B")).toList(), + Arrays.asList(tuple(1, "A"), tuple(1, "B"), tuple(2, "A"), tuple(2, "B")) + ); + } + + @Test + public void givenSeq_whenManipulateSeq_seqShouldHaveNewElementsInIt() { + assertEquals( + Seq.of(1, 2, 3).cycle().limit(9).toList(), + Arrays.asList(1, 2, 3, 1, 2, 3, 1, 2, 3) + ); + + assertEquals( + Seq.of(1, 2, 3).duplicate().map((first, second) -> tuple(first.toList(), second.toList())), + tuple(Arrays.asList(1, 2, 3), Arrays.asList(1, 2, 3)) + ); + + assertEquals( + Seq.of(1, 2, 3, 4).intersperse(0).toList(), + Arrays.asList(1, 0, 2, 0, 3, 0, 4) + ); + + assertEquals( + Seq.of(1, 2, 3, 4, 5).shuffle().toList().size(), + 5 + ); + + assertEquals( + Seq.of(1, 2, 3, 4).partition(i -> i > 2).map((first, second) -> tuple(first.toList(), second.toList())), + tuple(Arrays.asList(3, 4), Arrays.asList(1, 2)) + + ); + + assertEquals( + Seq.of(1, 2, 3, 4).reverse().toList(), + Arrays.asList(4, 3, 2, 1) + ); + } + + @Test + public void givenSeq_whenGroupByAndFold_shouldReturnProperSeq() { + + Map> expectedAfterGroupBy = new HashMap<>(); + expectedAfterGroupBy.put(1, Arrays.asList(1, 3)); + expectedAfterGroupBy.put(0, Arrays.asList(2, 4)); + + assertEquals( + Seq.of(1, 2, 3, 4).groupBy(i -> i % 2), + expectedAfterGroupBy + ); + + + assertEquals( + Seq.of("a", "b", "c").foldLeft("!", (u, t) -> u + t), + "!abc" + ); + + + assertEquals( + Seq.of("a", "b", "c").foldRight("!", (t, u) -> t + u), + "abc!" + ); + } + + @Test + public void givenSeq_whenUsingSeqWhile_shouldBehaveAsWhileLoop() { + + assertEquals( + Seq.of(1, 2, 3, 4, 5).skipWhile(i -> i < 3).toList(), + Arrays.asList(3, 4, 5) + ); + + assertEquals( + Seq.of(1, 2, 3, 4, 5).skipUntil(i -> i == 3).toList(), + Arrays.asList(3, 4, 5) + ); + } + + @Test + public void givenSeq_whenZip_shouldHaveZippedSeq() { + + assertEquals( + Seq.of(1, 2, 3).zip(Seq.of("a", "b", "c")).toList(), + Arrays.asList(tuple(1, "a"), tuple(2, "b"), tuple(3, "c")) + ); + + assertEquals( + Seq.of(1, 2, 3).zip(Seq.of("a", "b", "c"), (x, y) -> x + ":" + y).toList(), + Arrays.asList("1:a", "2:b", "3:c") + ); + + + assertEquals( + Seq.of("a", "b", "c").zipWithIndex().toList(), + Arrays.asList(tuple("a", 0L), tuple("b", 1L), tuple("c", 2L)) + ); + } + + + public Integer methodThatThrowsChecked(String arg) throws Exception { + return arg.length(); + } + + @Test + public void givenOperationThatThrowsCheckedException_whenExecuteAndNeedToWrapCheckedIntoUnchecked_shouldPass() { + //when + List collect = Stream.of("a", "b", "c").map(elem -> { + try { + return methodThatThrowsChecked(elem); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + }).collect(Collectors.toList()); + + //then + assertEquals( + collect, + Arrays.asList(1, 1, 1) + ); + } + + + @Test + public void givenOperationThatThrowsCheckedException_whenExecuteUsingUncheckedFuction_shouldPass() { + //when + List collect = Stream.of("a", "b", "c") + .map(Unchecked.function(elem -> methodThatThrowsChecked(elem))) + .collect(Collectors.toList()); + + //then + assertEquals( + collect, + Arrays.asList(1, 1, 1) + ); + } + + @Test + public void givenFunction_whenAppliedPartially_shouldAddNumberToPartialArgument() { + //given + Function2 addTwoNumbers = (v1, v2) -> v1 + v2; + addTwoNumbers.toBiFunction(); + Function1 addToTwo = addTwoNumbers.applyPartially(2); + + //when + Integer result = addToTwo.apply(5); + + //then + assertEquals(result, (Integer) 7); + } + + @Test + public void givenSeqOfTuples_whenTransformToLowerNumberOfTuples_shouldHaveProperResult() { + //given + Seq> personDetails = Seq.of(tuple("michael", "similar", 49), tuple("jodie", "variable", 43)); + Tuple2 tuple = tuple("winter", "summer"); + + //when + List> result = personDetails.map(t -> t.limit2().concat(tuple)).toList(); + + //then + assertEquals( + result, + Arrays.asList(tuple("michael", "similar", "winter", "summer"), tuple("jodie", "variable", "winter", "summer")) + ); + } + +} diff --git a/kotlin/README.md b/kotlin/README.md new file mode 100644 index 0000000000..6447a26f5c --- /dev/null +++ b/kotlin/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Introduction to the Kotlin Language](http://www.baeldung.com/kotlin) diff --git a/libraries/pom.xml b/libraries/pom.xml new file mode 100644 index 0000000000..ee93ee934f --- /dev/null +++ b/libraries/pom.xml @@ -0,0 +1,48 @@ + + + + parent-modules + com.baeldung + 1.0.0-SNAPSHOT + + 4.0.0 + + libraries + libraries + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + + + + cglib + cglib + ${cglib.version} + + + junit + junit + ${junit.version} + test + + + + + 3.2.4 + 4.12 + + + + \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/cglib/mixin/Class1.java b/libraries/src/main/java/com/baeldung/cglib/mixin/Class1.java new file mode 100644 index 0000000000..fa0cba5b78 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/cglib/mixin/Class1.java @@ -0,0 +1,8 @@ +package com.baeldung.cglib.mixin; + +public class Class1 implements Interface1 { + @Override + public String first() { + return "first behaviour"; + } +} \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/cglib/mixin/Class2.java b/libraries/src/main/java/com/baeldung/cglib/mixin/Class2.java new file mode 100644 index 0000000000..0db0620ab8 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/cglib/mixin/Class2.java @@ -0,0 +1,8 @@ +package com.baeldung.cglib.mixin; + +public class Class2 implements Interface2 { + @Override + public String second() { + return "second behaviour"; + } +} \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/cglib/mixin/Interface1.java b/libraries/src/main/java/com/baeldung/cglib/mixin/Interface1.java new file mode 100644 index 0000000000..56ad679cad --- /dev/null +++ b/libraries/src/main/java/com/baeldung/cglib/mixin/Interface1.java @@ -0,0 +1,5 @@ +package com.baeldung.cglib.mixin; + +public interface Interface1 { + String first(); +} \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/cglib/mixin/Interface2.java b/libraries/src/main/java/com/baeldung/cglib/mixin/Interface2.java new file mode 100644 index 0000000000..0dfb8737ab --- /dev/null +++ b/libraries/src/main/java/com/baeldung/cglib/mixin/Interface2.java @@ -0,0 +1,5 @@ +package com.baeldung.cglib.mixin; + +public interface Interface2 { + String second(); +} \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/cglib/mixin/MixinInterface.java b/libraries/src/main/java/com/baeldung/cglib/mixin/MixinInterface.java new file mode 100644 index 0000000000..e7ed362a25 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/cglib/mixin/MixinInterface.java @@ -0,0 +1,4 @@ +package com.baeldung.cglib.mixin; + +public interface MixinInterface extends Interface1, Interface2 { +} \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/cglib/proxy/PersonService.java b/libraries/src/main/java/com/baeldung/cglib/proxy/PersonService.java new file mode 100644 index 0000000000..9085e6c49a --- /dev/null +++ b/libraries/src/main/java/com/baeldung/cglib/proxy/PersonService.java @@ -0,0 +1,11 @@ +package com.baeldung.cglib.proxy; + +public class PersonService { + public String sayHello(String name) { + return "Hello " + name; + } + + public Integer lengthOfName(String name) { + return name.length(); + } +} \ No newline at end of file diff --git a/libraries/src/test/java/com/baeldung/cglib/proxy/BeanGeneratorTest.java b/libraries/src/test/java/com/baeldung/cglib/proxy/BeanGeneratorTest.java new file mode 100644 index 0000000000..1e49536065 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/cglib/proxy/BeanGeneratorTest.java @@ -0,0 +1,32 @@ +package com.baeldung.cglib.proxy; + + +import net.sf.cglib.beans.BeanGenerator; +import org.junit.Test; + +import java.lang.reflect.Method; + +import static junit.framework.TestCase.assertEquals; + +public class BeanGeneratorTest { + + @Test + public void givenBeanCreator_whenAddProperty_thenClassShouldHaveFieldValue() throws Exception { + //given + BeanGenerator beanGenerator = new BeanGenerator(); + + //when + beanGenerator.addProperty("name", String.class); + Object myBean = beanGenerator.create(); + Method setter = myBean + .getClass() + .getMethod("setName", String.class); + setter.invoke(myBean, "some string value set by a cglib"); + + //then + Method getter = myBean + .getClass() + .getMethod("getName"); + assertEquals("some string value set by a cglib", getter.invoke(myBean)); + } +} diff --git a/libraries/src/test/java/com/baeldung/cglib/proxy/MixinTest.java b/libraries/src/test/java/com/baeldung/cglib/proxy/MixinTest.java new file mode 100644 index 0000000000..db8453e6c1 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/cglib/proxy/MixinTest.java @@ -0,0 +1,24 @@ +package com.baeldung.cglib.proxy; + +import com.baeldung.cglib.mixin.*; +import net.sf.cglib.proxy.Mixin; +import org.junit.Test; + +import static junit.framework.TestCase.assertEquals; + +public class MixinTest { + + @Test + public void givenTwoClasses_whenMixedIntoOne_thenMixinShouldHaveMethodsFromBothClasses() throws Exception { + //when + Mixin mixin = Mixin.create( + new Class[]{Interface1.class, Interface2.class, MixinInterface.class}, + new Object[]{new Class1(), new Class2()} + ); + MixinInterface mixinDelegate = (MixinInterface) mixin; + + //then + assertEquals("first behaviour", mixinDelegate.first()); + assertEquals("second behaviour", mixinDelegate.second()); + } +} diff --git a/libraries/src/test/java/com/baeldung/cglib/proxy/ProxyTest.java b/libraries/src/test/java/com/baeldung/cglib/proxy/ProxyTest.java new file mode 100644 index 0000000000..195c4b903d --- /dev/null +++ b/libraries/src/test/java/com/baeldung/cglib/proxy/ProxyTest.java @@ -0,0 +1,60 @@ +package com.baeldung.cglib.proxy; + +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.FixedValue; +import net.sf.cglib.proxy.MethodInterceptor; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class ProxyTest { + @Test + public void givenPersonService_whenSayHello_thenReturnResult() { + //given + PersonService personService = new PersonService(); + + //when + String res = personService.sayHello("Tom"); + + //then + assertEquals(res, "Hello Tom"); + } + + @Test + public void givenEnhancerProxy_whenExtendPersonService_thenInterceptMethod() throws Exception { + //given + Enhancer enhancer = new Enhancer(); + enhancer.setSuperclass(PersonService.class); + enhancer.setCallback((FixedValue) () -> "Hello Tom!"); + PersonService proxy = (PersonService) enhancer.create(); + + //when + String res = proxy.sayHello(null); + + //then + assertEquals("Hello Tom!", res); + } + + @Test + public void givenEnhancer_whenExecuteMethodOnProxy_thenInterceptOnlyStringReturnTypeMethod() throws Exception { + //given + Enhancer enhancer = new Enhancer(); + enhancer.setSuperclass(PersonService.class); + enhancer.setCallback((MethodInterceptor) (obj, method, args, proxy) -> { + if (method.getDeclaringClass() != Object.class && method.getReturnType() == String.class) { + return "Hello Tom!"; + } else { + return proxy.invokeSuper(obj, args); + } + }); + + //when + PersonService proxy = (PersonService) enhancer.create(); + + //then + assertEquals("Hello Tom!", proxy.sayHello(null)); + int lengthOfName = proxy.lengthOfName("Mary"); + assertEquals(4, lengthOfName); + } + +} \ No newline at end of file diff --git a/log-mdc/pom.xml b/log-mdc/pom.xml index 28c8bb820e..931e68a178 100644 --- a/log-mdc/pom.xml +++ b/log-mdc/pom.xml @@ -2,9 +2,9 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 com.baeldung - logmdc + log-mdc 0.0.1-SNAPSHOT - logmdc + log-mdc war tutorial on logging with MDC and NDC diff --git a/log-mdc/src/main/java/com/baeldung/mdc/TransactionFactory.java b/log-mdc/src/main/java/com/baeldung/mdc/TransactionFactory.java index ec1887eea6..0904e4603f 100644 --- a/log-mdc/src/main/java/com/baeldung/mdc/TransactionFactory.java +++ b/log-mdc/src/main/java/com/baeldung/mdc/TransactionFactory.java @@ -7,15 +7,15 @@ import java.util.UUID; public class TransactionFactory { - private static final String[] NAMES = {"John", "Susan", "Marc", "Samantha"}; - private static long nextId = 1; - - public Transfer newInstance() { - String transactionId = String.valueOf( nextId++ ); - String owner = NAMES[ (int) floor(random()*NAMES.length) ]; - long amount = (long) (random()*1500 + 500); - Transfer tx = new Transfer(transactionId, owner, amount); - return tx; - } - + private static final String[] NAMES = { "John", "Susan", "Marc", "Samantha" }; + private static long nextId = 1; + + public Transfer newInstance() { + String transactionId = String.valueOf(nextId++); + String owner = NAMES[(int) floor(random() * NAMES.length)]; + long amount = (long) (random() * 1500 + 500); + Transfer tx = new Transfer(transactionId, owner, amount); + return tx; + } + } diff --git a/log-mdc/src/main/java/com/baeldung/mdc/TransferDemo.java b/log-mdc/src/main/java/com/baeldung/mdc/TransferDemo.java index daf256007c..259e9a8c5c 100644 --- a/log-mdc/src/main/java/com/baeldung/mdc/TransferDemo.java +++ b/log-mdc/src/main/java/com/baeldung/mdc/TransferDemo.java @@ -18,11 +18,11 @@ public class TransferDemo { for (int i = 0; i < 10; i++) { Transfer tx = transactionFactory.newInstance(); - - //Runnable task = new Log4JRunnable(tx); - //Runnable task = new Log4J2Runnable(tx); + + // Runnable task = new Log4JRunnable(tx); + // Runnable task = new Log4J2Runnable(tx); Runnable task = new Slf4jRunnable(tx); - + executor.submit(task); } diff --git a/log-mdc/src/main/java/com/baeldung/ndc/controller/JBossLoggingController.java b/log-mdc/src/main/java/com/baeldung/ndc/controller/JBossLoggingController.java index b024f3ec81..e581c45cd3 100644 --- a/log-mdc/src/main/java/com/baeldung/ndc/controller/JBossLoggingController.java +++ b/log-mdc/src/main/java/com/baeldung/ndc/controller/JBossLoggingController.java @@ -13,7 +13,6 @@ import org.springframework.web.bind.annotation.RestController; import com.baeldung.ndc.Investment; import com.baeldung.ndc.service.InvestmentService; - @RestController public class JBossLoggingController { @Autowired diff --git a/log-mdc/src/test/java/com/baeldung/mdc/log4j/Demo.java b/log-mdc/src/test/java/com/baeldung/mdc/log4j/Demo.java index f9a210606f..665168452a 100644 --- a/log-mdc/src/test/java/com/baeldung/mdc/log4j/Demo.java +++ b/log-mdc/src/test/java/com/baeldung/mdc/log4j/Demo.java @@ -17,7 +17,7 @@ public class Demo { TransactionFactory transactionFactory = new TransactionFactory(); for (int i = 0; i < 10; i++) { Transfer tx = transactionFactory.newInstance(); - Runnable task = new Log4JRunnable(tx); + Runnable task = new Log4JRunnable(tx); executor.submit(task); } executor.shutdown(); diff --git a/log-mdc/src/test/java/com/baeldung/mdc/log4j2/Demo.java b/log-mdc/src/test/java/com/baeldung/mdc/log4j2/Demo.java index 3f7c1d37d5..78c48c2a83 100644 --- a/log-mdc/src/test/java/com/baeldung/mdc/log4j2/Demo.java +++ b/log-mdc/src/test/java/com/baeldung/mdc/log4j2/Demo.java @@ -21,7 +21,7 @@ public class Demo { TransactionFactory transactionFactory = new TransactionFactory(); for (int i = 0; i < 10; i++) { Transfer tx = transactionFactory.newInstance(); - Runnable task = new Log4J2Runnable(tx); + Runnable task = new Log4J2Runnable(tx); executor.submit(task); } executor.shutdown(); diff --git a/log-mdc/src/test/java/com/baeldung/mdc/slf4j/Demo.java b/log-mdc/src/test/java/com/baeldung/mdc/slf4j/Demo.java index 98db698f47..de890f9f5d 100644 --- a/log-mdc/src/test/java/com/baeldung/mdc/slf4j/Demo.java +++ b/log-mdc/src/test/java/com/baeldung/mdc/slf4j/Demo.java @@ -21,7 +21,7 @@ public class Demo { TransactionFactory transactionFactory = new TransactionFactory(); for (int i = 0; i < 10; i++) { Transfer tx = transactionFactory.newInstance(); - Runnable task = new Slf4jRunnable(tx); + Runnable task = new Slf4jRunnable(tx); executor.submit(task); } executor.shutdown(); diff --git a/log4j2/pom.xml b/log4j2/pom.xml index 893c79be72..a4c8f19f69 100644 --- a/log4j2/pom.xml +++ b/log4j2/pom.xml @@ -1,105 +1,104 @@ - 4.0.0 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 - log4j2 + log4j2 - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - .. - + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + .. + - - - - org.apache.logging.log4j - log4j-core - ${log4j-core.version} - + + + + org.apache.logging.log4j + log4j-core + ${log4j-core.version} + - - - com.fasterxml.jackson.core - jackson-databind - ${jackson.version} - + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + - - - com.fasterxml.jackson.dataformat - jackson-dataformat-xml - ${jackson.version} - + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${jackson.version} + - - - com.h2database - h2 - ${h2.version} - - - org.apache.commons - commons-dbcp2 - ${commons-dbcp2.version} - + + + com.h2database + h2 + ${h2.version} + + + org.apache.commons + commons-dbcp2 + ${commons-dbcp2.version} + - - - org.apache.logging.log4j - log4j-core - ${log4j-core.version} - test-jar - test - - - junit - junit - ${junit.version} - test - - + + + org.apache.logging.log4j + log4j-core + ${log4j-core.version} + test-jar + test + + + junit + junit + ${junit.version} + test + + - - + + - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} - - 1.8 - 1.8 - - - - org.apache.maven.plugins - maven-surefire-plugin - ${maven-surefire-plugin.version} - - - **/*IntegrationTest.java - **/*LongRunningUnitTest.java - **/*ManualTest.java - - true - - + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + **/*IntegrationTest.java + **/*LongRunningUnitTest.java + **/*ManualTest.java + + true + + - - + + - - 2.8.5 - 1.4.193 - 2.1.1 - 2.7 - 4.12 - - 3.6.0 - 2.19.1 - + + 2.8.5 + 1.4.193 + 2.1.1 + 2.7 + 4.12 + 3.6.0 + 2.19.1 + diff --git a/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/AsyncFileAppenderUsingJsonLayoutTest.java b/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/AsyncFileAppenderUsingJsonLayoutTest.java deleted file mode 100644 index 0472c2219e..0000000000 --- a/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/AsyncFileAppenderUsingJsonLayoutTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.baeldung.logging.log4j2.tests; - -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.junit.LoggerContextRule; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -import java.nio.file.Files; -import java.nio.file.Paths; - -import static org.junit.Assert.assertTrue; - -@RunWith(JUnit4.class) -public class AsyncFileAppenderUsingJsonLayoutTest { - @Rule - public LoggerContextRule contextRule = - new LoggerContextRule("log4j2-async-file-appender_json-layout.xml"); - - @Test - public void givenLoggerWithAsyncConfig_shouldLogToJsonFile() - throws Exception { - Logger logger = contextRule.getLogger(getClass().getSimpleName()); - final int count = 88; - for (int i = 0; i < count; i++) { - logger.info("This is async JSON message #{} at INFO level.", count); - } - long logEventsCount = Files.lines(Paths.get("target/logfile.json")).count(); - assertTrue(logEventsCount > 0 && logEventsCount <= count); - } -} diff --git a/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/ConsoleAppenderUsingDefaultLayoutTest.java b/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/ConsoleAppenderUsingDefaultLayoutTest.java deleted file mode 100644 index 9831030d02..0000000000 --- a/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/ConsoleAppenderUsingDefaultLayoutTest.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.baeldung.logging.log4j2.tests; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class ConsoleAppenderUsingDefaultLayoutTest { - @Test - public void givenLoggerWithDefaultConfig_shouldLogToConsole() - throws Exception { - Logger logger = LogManager.getLogger(getClass()); - Exception e = new RuntimeException("This is only a test!"); - logger.info("This is a simple message at INFO level. " + - "It will be hidden."); - logger.error("This is a simple message at ERROR level. " + - "This is the minimum visible level.", e); - } -} diff --git a/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/ConsoleAppenderUsingPatternLayoutWithColorsTest.java b/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/ConsoleAppenderUsingPatternLayoutWithColorsTest.java deleted file mode 100644 index 86b005538f..0000000000 --- a/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/ConsoleAppenderUsingPatternLayoutWithColorsTest.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.baeldung.logging.log4j2.tests; - -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.Marker; -import org.apache.logging.log4j.MarkerManager; -import org.apache.logging.log4j.ThreadContext; -import org.apache.logging.log4j.junit.LoggerContextRule; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class ConsoleAppenderUsingPatternLayoutWithColorsTest { - @Rule - public LoggerContextRule contextRule = - new LoggerContextRule("log4j2-console-appender_pattern-layout.xml"); - - @Test - public void givenLoggerWithConsoleConfig_shouldLogToConsoleInColors() - throws Exception { - Logger logger = contextRule.getLogger(getClass().getSimpleName()); - logger.trace("This is a colored message at TRACE level."); - logger.debug("This is a colored message at DEBUG level. " + - "This is the minimum visible level."); - logger.info("This is a colored message at INFO level."); - logger.warn("This is a colored message at WARN level."); - Exception e = new RuntimeException("This is only a test!"); - logger.error("This is a colored message at ERROR level.", e); - logger.fatal("This is a colored message at FATAL level."); - } - - @Test - public void givenLoggerWithConsoleConfig_shouldFilterByMarker() throws Exception { - Logger logger = contextRule.getLogger("ConnTrace"); - Marker appError = MarkerManager.getMarker("APP_ERROR"); - logger.error(appError, "This marker message at ERROR level should be hidden."); - Marker connectionTrace = MarkerManager.getMarker("CONN_TRACE"); - logger.trace(connectionTrace, "This is a marker message at TRACE level."); - } - - @Test - public void givenLoggerWithConsoleConfig_shouldFilterByThreadContext() throws Exception { - Logger logger = contextRule.getLogger("UserAudit"); - ThreadContext.put("userId", "1000"); - logger.info("This is a log-visible user login. Maybe from an admin account?"); - ThreadContext.put("userId", "1001"); - logger.info("This is a log-invisible user login."); - boolean b = true; - } -} diff --git a/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/CustomLoggingTest.java b/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/CustomLoggingTest.java new file mode 100644 index 0000000000..1562b67068 --- /dev/null +++ b/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/CustomLoggingTest.java @@ -0,0 +1,122 @@ +package com.baeldung.logging.log4j2.tests; + +import static org.junit.Assert.assertTrue; + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.sql.Connection; +import java.sql.ResultSet; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.Marker; +import org.apache.logging.log4j.MarkerManager; +import org.apache.logging.log4j.ThreadContext; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import com.baeldung.logging.log4j2.tests.jdbc.ConnectionFactory; + +@RunWith(JUnit4.class) +public class CustomLoggingTest { + + @BeforeClass + public static void setup() throws Exception { + Connection connection = ConnectionFactory.getConnection(); + connection.createStatement() + .execute("CREATE TABLE logs(" + "when TIMESTAMP," + "logger VARCHAR(255)," + "level VARCHAR(255)," + "message VARCHAR(4096)," + "throwable TEXT)"); + connection.commit(); + } + + @Test + public void givenLoggerWithDefaultConfig_shouldLogToConsole() throws Exception { + Logger logger = LogManager.getLogger(getClass()); + Exception e = new RuntimeException("This is only a test!"); + logger.info("This is a simple message at INFO level. " + "It will be hidden."); + logger.error("This is a simple message at ERROR level. " + "This is the minimum visible level.", e); + } + + @Test + public void givenLoggerWithConsoleConfig_shouldLogToConsoleInColors() throws Exception { + Logger logger = LogManager.getLogger("CONSOLE_PATTERN_APPENDER_MARKER"); + logger.trace("This is a colored message at TRACE level."); + logger.debug("This is a colored message at DEBUG level. " + "This is the minimum visible level."); + logger.info("This is a colored message at INFO level."); + logger.warn("This is a colored message at WARN level."); + Exception e = new RuntimeException("This is only a test!"); + logger.error("This is a colored message at ERROR level.", e); + logger.fatal("This is a colored message at FATAL level."); + } + + @Test + public void givenLoggerWithConsoleConfig_shouldFilterByMarker() throws Exception { + Logger logger = LogManager.getLogger("CONSOLE_PATTERN_APPENDER_MARKER"); + Marker appError = MarkerManager.getMarker("APP_ERROR"); + logger.error(appError, "This marker message at ERROR level should be hidden."); + Marker connectionTrace = MarkerManager.getMarker("CONN_TRACE"); + logger.trace(connectionTrace, "This is a marker message at TRACE level."); + } + + @Test + public void givenLoggerWithConsoleConfig_shouldFilterByThreadContext() throws Exception { + Logger logger = LogManager.getLogger("CONSOLE_PATTERN_APPENDER_THREAD_CONTEXT"); + ThreadContext.put("userId", "1000"); + logger.info("This is a log-visible user login. Maybe from an admin account?"); + ThreadContext.put("userId", "1001"); + logger.info("This is a log-invisible user login."); + + } + + @Test + public void givenLoggerWithAsyncConfig_shouldLogToJsonFile() throws Exception { + Logger logger = LogManager.getLogger("ASYNC_JSON_FILE_APPENDER"); + final int count = 88; + for (int i = 0; i < count; i++) { + logger.info("This is async JSON message #{} at INFO level.", count); + } + long logEventsCount = Files.lines(Paths.get("target/logfile.json")) + .count(); + assertTrue(logEventsCount > 0 && logEventsCount <= count); + } + + @Test + public void givenLoggerWithFailoverConfig_shouldLog() throws Exception { + Logger logger = LogManager.getLogger("FAIL_OVER_SYSLOG_APPENDER"); + logger.trace("This is a syslog message at TRACE level."); + logger.debug("This is a syslog message at DEBUG level."); + logger.info("This is a syslog message at INFO level. This is the minimum visible level."); + logger.warn("This is a syslog message at WARN level."); + Exception e = new RuntimeException("This is only a test!"); + logger.error("This is a syslog message at ERROR level.", e); + logger.fatal("This is a syslog message at FATAL level."); + } + + @Test + public void givenLoggerWithJdbcConfig_shouldLogToDataSource() throws Exception { + Logger logger = LogManager.getLogger("JDBC_APPENDER"); + final int count = 88; + for (int i = 0; i < count; i++) { + logger.info("This is JDBC message #{} at INFO level.", count); + } + Connection connection = ConnectionFactory.getConnection(); + ResultSet resultSet = connection.createStatement() + .executeQuery("SELECT COUNT(*) AS ROW_COUNT FROM logs"); + int logCount = 0; + if (resultSet.next()) { + logCount = resultSet.getInt("ROW_COUNT"); + } + assertTrue(logCount == count); + } + + @Test + public void givenLoggerWithRollingFileConfig_shouldLogToXMLFile() throws Exception { + Logger logger = LogManager.getLogger("XML_ROLLING_FILE_APPENDER"); + final int count = 88; + for (int i = 0; i < count; i++) { + logger.info("This is rolling file XML message #{} at INFO level.", i); + } + } + +} diff --git a/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/FailoverSyslogConsoleAppenderTest.java b/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/FailoverSyslogConsoleAppenderTest.java deleted file mode 100644 index 0653394e5a..0000000000 --- a/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/FailoverSyslogConsoleAppenderTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.baeldung.logging.log4j2.tests; - -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.junit.LoggerContextRule; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class FailoverSyslogConsoleAppenderTest { - @Rule - public LoggerContextRule contextRule = - new LoggerContextRule("log4j2-failover-syslog-console-appender_pattern-layout.xml"); - - @Test - public void givenLoggerWithFailoverConfig_shouldLog() throws Exception { - Logger logger = contextRule.getLogger(getClass().getSimpleName()); - logger.trace("This is a syslog message at TRACE level."); - logger.debug("This is a syslog message at DEBUG level."); - logger.info("This is a syslog message at INFO level. This is the minimum visible level."); - logger.warn("This is a syslog message at WARN level."); - Exception e = new RuntimeException("This is only a test!"); - logger.error("This is a syslog message at ERROR level.", e); - logger.fatal("This is a syslog message at FATAL level."); - } -} diff --git a/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/JDBCAppenderTest.java b/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/JDBCAppenderTest.java deleted file mode 100644 index 1b8d33e2bf..0000000000 --- a/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/JDBCAppenderTest.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.baeldung.logging.log4j2.tests; - -import com.baeldung.logging.log4j2.tests.jdbc.ConnectionFactory; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.junit.LoggerContextRule; -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -import java.sql.Connection; -import java.sql.ResultSet; - -import static org.junit.Assert.assertTrue; - -@RunWith(JUnit4.class) -public class JDBCAppenderTest { - @Rule - public LoggerContextRule contextRule = new LoggerContextRule("log4j2-jdbc-appender.xml"); - - @BeforeClass - public static void setup() throws Exception { - Connection connection = ConnectionFactory.getConnection(); - connection.createStatement() - .execute("CREATE TABLE logs(" + - "when TIMESTAMP," + - "logger VARCHAR(255)," + - "level VARCHAR(255)," + - "message VARCHAR(4096)," + - "throwable TEXT)"); - //connection.commit(); - } - - @Test - public void givenLoggerWithJdbcConfig_shouldLogToDataSource() throws Exception { - Logger logger = contextRule.getLogger(getClass().getSimpleName()); - final int count = 88; - for (int i = 0; i < count; i++) { - logger.info("This is JDBC message #{} at INFO level.", count); - } - Connection connection = ConnectionFactory.getConnection(); - ResultSet resultSet = connection.createStatement() - .executeQuery("SELECT COUNT(*) AS ROW_COUNT FROM logs"); - int logCount = 0; - if (resultSet.next()) { - logCount = resultSet.getInt("ROW_COUNT"); - } - assertTrue(logCount == count); - } -} diff --git a/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/RollingFileAppenderUsingXMLLayoutTest.java b/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/RollingFileAppenderUsingXMLLayoutTest.java deleted file mode 100644 index 3ab69d263c..0000000000 --- a/log4j2/src/test/java/com/baeldung/logging/log4j2/tests/RollingFileAppenderUsingXMLLayoutTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.baeldung.logging.log4j2.tests; - -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.junit.LoggerContextRule; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.stream.Collectors; - -import static org.junit.Assert.assertTrue; - -@RunWith(JUnit4.class) -public class RollingFileAppenderUsingXMLLayoutTest { - @Rule - public LoggerContextRule contextRule = - new LoggerContextRule("log4j2-rolling-file-appender_xml-layout.xml"); - - @Test - public void givenLoggerWithRollingFileConfig_shouldLogToXMLFile() throws Exception { - Logger logger = contextRule.getLogger(getClass().getSimpleName()); - final int count = 88; - for (int i = 0; i < count; i++) { - logger.info("This is rolling file XML message #{} at INFO level.", i); - } - String[] logEvents = Files.readAllLines(Paths.get("target/logfile.xml")).stream() - .collect(Collectors.joining(System.lineSeparator())) - .split("\\n\\n+"); - assertTrue(logEvents.length == 39); - } -} diff --git a/log4j2/src/test/resources/log4j2-async-file-appender_json-layout.xml b/log4j2/src/test/resources/log4j2-async-file-appender_json-layout.xml deleted file mode 100644 index c291eacd59..0000000000 --- a/log4j2/src/test/resources/log4j2-async-file-appender_json-layout.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/log4j2/src/test/resources/log4j2-console-appender_pattern-layout.xml b/log4j2/src/test/resources/log4j2-console-appender_pattern-layout.xml deleted file mode 100644 index d6621f9166..0000000000 --- a/log4j2/src/test/resources/log4j2-console-appender_pattern-layout.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/log4j2/src/test/resources/log4j2-failover-syslog-console-appender_pattern-layout.xml b/log4j2/src/test/resources/log4j2-failover-syslog-console-appender_pattern-layout.xml deleted file mode 100644 index 62ba37f28c..0000000000 --- a/log4j2/src/test/resources/log4j2-failover-syslog-console-appender_pattern-layout.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/log4j2/src/test/resources/log4j2-includes/console-appender_pattern-layout_colored.xml b/log4j2/src/test/resources/log4j2-includes/console-appender_pattern-layout_colored.xml index c2b9c65430..fd61e4581f 100644 --- a/log4j2/src/test/resources/log4j2-includes/console-appender_pattern-layout_colored.xml +++ b/log4j2/src/test/resources/log4j2-includes/console-appender_pattern-layout_colored.xml @@ -1,4 +1,5 @@ - + diff --git a/log4j2/src/test/resources/log4j2-jdbc-appender.xml b/log4j2/src/test/resources/log4j2-jdbc-appender.xml deleted file mode 100644 index 6b50f7d5a4..0000000000 --- a/log4j2/src/test/resources/log4j2-jdbc-appender.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/log4j2/src/test/resources/log4j2-rolling-file-appender_xml-layout.xml b/log4j2/src/test/resources/log4j2-rolling-file-appender_xml-layout.xml deleted file mode 100644 index 9de1a29186..0000000000 --- a/log4j2/src/test/resources/log4j2-rolling-file-appender_xml-layout.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/log4j2/src/test/resources/log4j2.xml b/log4j2/src/test/resources/log4j2.xml index 8f7608aa78..83c1184f1f 100644 --- a/log4j2/src/test/resources/log4j2.xml +++ b/log4j2/src/test/resources/log4j2.xml @@ -1,13 +1,69 @@ - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + - + \ No newline at end of file diff --git a/mesos-marathon/Dockerfile b/mesos-marathon/Dockerfile new file mode 100644 index 0000000000..ca79f2dc82 --- /dev/null +++ b/mesos-marathon/Dockerfile @@ -0,0 +1,4 @@ +FROM openjdk:8-jre-alpine +ADD target/mesos-marathon-0.0.1-SNAPSHOT.jar app.jar +EXPOSE 8082 +ENTRYPOINT ["java","-jar","/app.jar"] \ No newline at end of file diff --git a/mesos-marathon/dockerise.sh b/mesos-marathon/dockerise.sh new file mode 100755 index 0000000000..50f5d38306 --- /dev/null +++ b/mesos-marathon/dockerise.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -e +docker login -u mogronalol -p $DOCKER_PASSWORD +docker build -t baeldung/mesos-marathon-demo:$BUILD_NUMBER . +docker push baeldung/mesos-marathon-demo:$BUILD_NUMBER diff --git a/mesos-marathon/marathon.json b/mesos-marathon/marathon.json new file mode 100644 index 0000000000..6471259e92 --- /dev/null +++ b/mesos-marathon/marathon.json @@ -0,0 +1,14 @@ +{ + "id": "mesos-marathon-demo", + "container": { + "type": "DOCKER", + "docker": { + "image": "", + "network": "BRIDGE", + "portMappings": [ + { "containerPort": 8082, "hostPort": 0 } + ] + }, + "volumes": [] + } +} \ No newline at end of file diff --git a/mesos-marathon/pom.xml b/mesos-marathon/pom.xml new file mode 100644 index 0000000000..ca17a5c4c4 --- /dev/null +++ b/mesos-marathon/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + + com.baeldung + mesos-marathon + 0.0.1-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + 1.5.1.RELEASE + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 1.5.1.RELEASE + + + + repackage + + + + + + + + \ No newline at end of file diff --git a/mesos-marathon/src/main/java/com/mogronalol/DemoApplication.java b/mesos-marathon/src/main/java/com/mogronalol/DemoApplication.java new file mode 100644 index 0000000000..f757178026 --- /dev/null +++ b/mesos-marathon/src/main/java/com/mogronalol/DemoApplication.java @@ -0,0 +1,14 @@ +package com.mogronalol; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +import javax.annotation.PostConstruct; + +@SpringBootApplication +public class DemoApplication { + + public static void main(String[] args) { + SpringApplication.run(DemoApplication.class, args); + } +} diff --git a/mesos-marathon/src/main/java/com/mogronalol/HelloController.java b/mesos-marathon/src/main/java/com/mogronalol/HelloController.java new file mode 100644 index 0000000000..2059280ba0 --- /dev/null +++ b/mesos-marathon/src/main/java/com/mogronalol/HelloController.java @@ -0,0 +1,17 @@ +package com.mogronalol; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController(value = "/") +public class HelloController { + + @GetMapping + @ResponseBody + public String getMapping() { + return "Hello world"; + } + +} diff --git a/mesos-marathon/src/main/resources/application.properties b/mesos-marathon/src/main/resources/application.properties new file mode 100644 index 0000000000..8d51d0c619 --- /dev/null +++ b/mesos-marathon/src/main/resources/application.properties @@ -0,0 +1 @@ +server.port=8082 \ No newline at end of file diff --git a/mesos-marathon/src/test/java/com/mogronalol/DemoApplicationTests.java b/mesos-marathon/src/test/java/com/mogronalol/DemoApplicationTests.java new file mode 100644 index 0000000000..5e88f9a70f --- /dev/null +++ b/mesos-marathon/src/test/java/com/mogronalol/DemoApplicationTests.java @@ -0,0 +1,34 @@ +package com.mogronalol; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.context.embedded.LocalServerPort; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.web.client.RestTemplate; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = {DemoApplication.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class DemoApplicationTests { + + private RestTemplate restTemplate; + + @LocalServerPort + private int port; + + @Before + public void setUp() { + restTemplate = new RestTemplate(); + } + + @Test + public void contextLoads() { + final String result = restTemplate.getForObject("http://localhost:" + port + "/", String.class); + assertThat(result).isEqualTo("Hello world"); + } + +} diff --git a/metrics/README.md b/metrics/README.md new file mode 100644 index 0000000000..c98024c479 --- /dev/null +++ b/metrics/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Intro to Dropwizard Metrics](http://www.baeldung.com/dropwizard-metrics) diff --git a/metrics/src/test/java/com/baeldung/metrics/core/MetricsTest.java b/metrics/src/test/java/com/baeldung/metrics/core/MetricsTest.java index f670acfaef..e876de6e65 100644 --- a/metrics/src/test/java/com/baeldung/metrics/core/MetricsTest.java +++ b/metrics/src/test/java/com/baeldung/metrics/core/MetricsTest.java @@ -138,15 +138,15 @@ public class MetricsTest { long elapsed1 = context1.stop(); - assertEquals(5000000000L, elapsed1, 10000000); + assertEquals(5000000000L, elapsed1, 1000000000); assertThat(timer.getCount(), equalTo(1L)); - assertEquals(0.2, timer.getMeanRate(), 0.1); + assertEquals(0.2, timer.getMeanRate(), 0.2); Timer.Context context2 = timer.time(); TimeUnit.SECONDS.sleep(2); context2.close(); assertThat(timer.getCount(), equalTo(2L)); - assertEquals(0.3, timer.getMeanRate(), 0.1); + assertEquals(0.3, timer.getMeanRate(), 0.2); } } diff --git a/pdf/README.md b/pdf/README.md index 7160df4081..5454d2b2de 100644 --- a/pdf/README.md +++ b/pdf/README.md @@ -1,2 +1,3 @@ ### Relevant Articles: - [PDF Conversions in Java](http://www.baeldung.com/pdf-conversions-java) +- [Creating PDF Files in Java](http://www.baeldung.com/java-pdf-creation) diff --git a/pom.xml b/pom.xml index 41235dcc26..9d6c5931e3 100644 --- a/pom.xml +++ b/pom.xml @@ -8,9 +8,10 @@ parent-modules pom - UTF-8 + refs/heads/master + false @@ -63,6 +64,7 @@ jaxb jee7 jjwt + jooq jpa-storedprocedure jsf json-path @@ -72,6 +74,7 @@ kotlin + libraries log-mdc log4j log4j2 @@ -79,6 +82,7 @@ mapstruct metrics + mesos-marathon mockito mocks @@ -106,6 +110,7 @@ spring-autowire spring-batch spring-boot + spring-boot-servlet spring-cloud-data-flow spring-cloud spring-core @@ -147,6 +152,7 @@ spring-rest-docs spring-rest spring-security-basic-auth + spring-security-cache-control spring-security-client/spring-security-jsp-authentication spring-security-client/spring-security-jsp-authorize spring-security-client/spring-security-jsp-config @@ -155,7 +161,7 @@ spring-security-client/spring-security-thymeleaf-authorize spring-security-client/spring-security-thymeleaf-config spring-security-core - spring-security-custom-permission + spring-security-mvc-boot spring-security-mvc-custom spring-security-mvc-digest-auth spring-security-mvc-ldap @@ -178,6 +184,7 @@ spring-reactor testing + testng video-tutorials @@ -188,7 +195,21 @@ xstream struts2 + apache-velocity + apache-solrj - + rabbitmq + + + + + + + + diff --git a/rabbitmq/pom.xml b/rabbitmq/pom.xml new file mode 100644 index 0000000000..03f192e4e1 --- /dev/null +++ b/rabbitmq/pom.xml @@ -0,0 +1,43 @@ + + + + 4.0.0 + com.baeldung + rabbitmq + 0.1-SNAPSHOT + + rabbitmq + http://maven.apache.org + + + + com.rabbitmq + amqp-client + 3.6.6 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + + + + + + UTF-8 + + 3.6.0 + + + \ No newline at end of file diff --git a/rabbitmq/src/main/java/com/baeldung/consumer/Receiver.java b/rabbitmq/src/main/java/com/baeldung/consumer/Receiver.java new file mode 100644 index 0000000000..d0612406e9 --- /dev/null +++ b/rabbitmq/src/main/java/com/baeldung/consumer/Receiver.java @@ -0,0 +1,31 @@ +package com.baeldung.consumer; + +import com.rabbitmq.client.*; + +import java.io.IOException; +import java.util.concurrent.TimeoutException; + +public class Receiver { + + private static final String QUEUE_NAME = "products_queue"; + + public static void main (String[] args) throws IOException, TimeoutException { + ConnectionFactory factory = new ConnectionFactory(); + factory.setHost("localhost"); + Connection connection = factory.newConnection(); + Channel channel = connection.createChannel(); + + channel.queueDeclare(QUEUE_NAME, false, false, false, null); + + Consumer consumer = new DefaultConsumer(channel) { + @Override + public void handleDelivery(String consumerTag, + Envelope envelope, AMQP.BasicProperties properties, + byte[] body) throws IOException { + String message = new String(body, "UTF-8"); + System.out.println(" [x] Received '" + message + "'"); + } + }; + channel.basicConsume(QUEUE_NAME, true, consumer); + } +} diff --git a/rabbitmq/src/main/java/com/baeldung/producer/Publisher.java b/rabbitmq/src/main/java/com/baeldung/producer/Publisher.java new file mode 100644 index 0000000000..f9130c5d86 --- /dev/null +++ b/rabbitmq/src/main/java/com/baeldung/producer/Publisher.java @@ -0,0 +1,27 @@ +package com.baeldung.producer; + +import com.rabbitmq.client.*; + +import java.io.IOException; +import java.util.concurrent.TimeoutException; + +public class Publisher { + + private final static String QUEUE_NAME = "products_queue"; + + public static void main(String[]args) throws IOException, TimeoutException { + ConnectionFactory factory = new ConnectionFactory(); + factory.setHost("localhost"); + Connection connection = factory.newConnection(); + Channel channel = connection.createChannel(); + + String message = "product details"; + channel.queueDeclare(QUEUE_NAME, false, false, false, null); + + channel.basicPublish("", QUEUE_NAME, null, message.getBytes()); + System.out.println(" [x] Sent '" + message + "'"); + + channel.close(); + connection.close(); + } +} diff --git a/rxjava/README.md b/rxjava/README.md new file mode 100644 index 0000000000..7670dd4ed3 --- /dev/null +++ b/rxjava/README.md @@ -0,0 +1,4 @@ +## Relevant articles: + +- [Dealing with Backpressure with RxJava](http://www.baeldung.com/rxjava-backpressure) +- [How to Test RxJava?](http://www.baeldung.com/rxjava-testing) diff --git a/rxjava/pom.xml b/rxjava/pom.xml index 63aa1f127e..b3936bf78d 100644 --- a/rxjava/pom.xml +++ b/rxjava/pom.xml @@ -26,10 +26,25 @@ rxjava ${rx.java.version} + + junit + junit + ${junit.version} + + + org.hamcrest + hamcrest-all + ${hamcrest.version} + test + + + + 4.12 1.2.5 + 1.3 \ No newline at end of file diff --git a/rxjava/src/main/java/com/baelding/rxjava/ColdObservableBackpressure.java b/rxjava/src/main/java/com/baelding/rxjava/ColdObservableBackpressure.java deleted file mode 100644 index 9855123a3b..0000000000 --- a/rxjava/src/main/java/com/baelding/rxjava/ColdObservableBackpressure.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.baelding.rxjava; - -import rx.Observable; -import rx.schedulers.Schedulers; - -public class ColdObservableBackpressure { - public static void main(String[] args) throws InterruptedException { - Observable.range(1, 1_000_000).observeOn(Schedulers.computation()).subscribe(v -> ComputeFunction.compute(v), Throwable::printStackTrace); - - Thread.sleep(10_000); - - // Observable.range(1, 1_000_000) //implementation of reactive pull backpressure on cold observable - // .subscribe(new Subscriber() { - // @Override - // public void onStart() { - // request(1); - // } - // - // public void onNext(Integer v) { - // compute(v); - // - // request(1); - // } - // - // @Override - // public void onError(Throwable ex) { - // ex.printStackTrace(); - // } - // - // @Override - // public void onCompleted() { - // System.out.println("Done!"); - // } - // }); - - } - -} diff --git a/rxjava/src/main/java/com/baelding/rxjava/HotObservableBackpressureBatching.java b/rxjava/src/main/java/com/baelding/rxjava/HotObservableBackpressureBatching.java deleted file mode 100644 index 6acda7eaad..0000000000 --- a/rxjava/src/main/java/com/baelding/rxjava/HotObservableBackpressureBatching.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.baelding.rxjava; - -import rx.schedulers.Schedulers; -import rx.subjects.PublishSubject; - -public class HotObservableBackpressureBatching { - public static void main(String[] args) throws InterruptedException { - PublishSubject source = PublishSubject.create(); - - source.window(500).observeOn(Schedulers.computation()).subscribe(ComputeFunction::compute, Throwable::printStackTrace); - - for (int i = 0; i < 1_000_000; i++) { - source.onNext(i); - } - Thread.sleep(10_000); - } - -} diff --git a/rxjava/src/main/java/com/baelding/rxjava/HotObservableBackpressureBuffering.java b/rxjava/src/main/java/com/baelding/rxjava/HotObservableBackpressureBuffering.java deleted file mode 100644 index 50638f4c8a..0000000000 --- a/rxjava/src/main/java/com/baelding/rxjava/HotObservableBackpressureBuffering.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.baelding.rxjava; - -import rx.schedulers.Schedulers; -import rx.subjects.PublishSubject; - -public class HotObservableBackpressureBuffering { - public static void main(String[] args) throws InterruptedException { - PublishSubject source = PublishSubject.create(); - - source.buffer(1024).observeOn(Schedulers.computation()).subscribe(ComputeFunction::compute, Throwable::printStackTrace); - - for (int i = 0; i < 1_000_000; i++) { - source.onNext(i); - } - Thread.sleep(10_000); - } -} diff --git a/rxjava/src/main/java/com/baelding/rxjava/HotObservableBackpressureSkipping.java b/rxjava/src/main/java/com/baelding/rxjava/HotObservableBackpressureSkipping.java deleted file mode 100644 index f6f8b9f563..0000000000 --- a/rxjava/src/main/java/com/baelding/rxjava/HotObservableBackpressureSkipping.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.baelding.rxjava; - -import rx.schedulers.Schedulers; -import rx.subjects.PublishSubject; - -import java.util.concurrent.TimeUnit; - -public class HotObservableBackpressureSkipping { - public static void main(String[] args) throws InterruptedException { - PublishSubject source = PublishSubject.create(); - - source.sample(100, TimeUnit.MILLISECONDS) - // .throttleFirst(100, TimeUnit.MILLISECONDS) - .observeOn(Schedulers.computation()).subscribe(ComputeFunction::compute, Throwable::printStackTrace); - - for (int i = 0; i < 1_000_000; i++) { - source.onNext(i); - } - Thread.sleep(10_000); - } -} diff --git a/rxjava/src/main/java/com/baelding/rxjava/HotObservableOnBackpressure.java b/rxjava/src/main/java/com/baelding/rxjava/HotObservableOnBackpressure.java deleted file mode 100644 index afef8027bf..0000000000 --- a/rxjava/src/main/java/com/baelding/rxjava/HotObservableOnBackpressure.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.baelding.rxjava; - -import rx.BackpressureOverflow; -import rx.Observable; -import rx.schedulers.Schedulers; - -public class HotObservableOnBackpressure { - public static void main(String[] args) throws InterruptedException { - Observable.range(1, 1_000_000).onBackpressureBuffer(16, () -> { - }, BackpressureOverflow.ON_OVERFLOW_DROP_OLDEST).observeOn(Schedulers.computation()).subscribe(e -> { - }, Throwable::printStackTrace); - - Observable.range(1, 1_000_000).onBackpressureDrop().observeOn(Schedulers.io()).doOnNext(ComputeFunction::compute).subscribe(v -> { - }, Throwable::printStackTrace); - Thread.sleep(10_000); - - } -} diff --git a/rxjava/src/main/java/com/baelding/rxjava/HotObservableWithoutBackpressure.java b/rxjava/src/main/java/com/baelding/rxjava/HotObservableWithoutBackpressure.java deleted file mode 100644 index 7745dbe5c4..0000000000 --- a/rxjava/src/main/java/com/baelding/rxjava/HotObservableWithoutBackpressure.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.baelding.rxjava; - - -import rx.schedulers.Schedulers; -import rx.subjects.PublishSubject; - -public class HotObservableWithoutBackpressure { - public static void main(String[] args) throws InterruptedException { - PublishSubject source = PublishSubject.create(); - - source.observeOn(Schedulers.computation()) - .subscribe(ComputeFunction::compute, Throwable::printStackTrace); - - - for (int i = 0; i < 1_000_000; i++) { - source.onNext(i); - } - Thread.sleep(10_000); - } -} diff --git a/rxjava/src/test/java/com/baeldung/rxjava/RxJavaBackpressureTest.java b/rxjava/src/test/java/com/baeldung/rxjava/RxJavaBackpressureTest.java new file mode 100644 index 0000000000..8a495650b3 --- /dev/null +++ b/rxjava/src/test/java/com/baeldung/rxjava/RxJavaBackpressureTest.java @@ -0,0 +1,130 @@ +package com.baeldung.rxjava; + +import org.junit.Test; +import rx.BackpressureOverflow; +import rx.Observable; +import rx.exceptions.MissingBackpressureException; +import rx.observers.TestSubscriber; +import rx.schedulers.Schedulers; +import rx.subjects.PublishSubject; + +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.stream.IntStream; + +import static org.junit.Assert.assertTrue; + +public class RxJavaBackpressureTest { + + @Test + public void givenColdObservable_shouldNotThrowException() { + // given + TestSubscriber testSubscriber = new TestSubscriber<>(); + + // when + Observable.range(1, 1_000_000).observeOn(Schedulers.computation()).subscribe(testSubscriber); + + // then + testSubscriber.awaitTerminalEvent(); + assertTrue(testSubscriber.getOnErrorEvents().size() == 0); + + } + + @Test + public void givenHotObservable_whenBackpressureNotDefined_shouldTrowException() { + // given + TestSubscriber testSubscriber = new TestSubscriber<>(); + PublishSubject source = PublishSubject. create(); + + source.observeOn(Schedulers.computation()).subscribe(testSubscriber); + + // when + IntStream.range(0, 1_000_000).forEach(source::onNext); + + // then + testSubscriber.awaitTerminalEvent(); + testSubscriber.assertError(MissingBackpressureException.class); + } + + @Test + public void givenHotObservable_whenWindowIsDefined_shouldNotThrowException() { + // given + TestSubscriber> testSubscriber = new TestSubscriber<>(); + PublishSubject source = PublishSubject. create(); + + // when + source.window(500).observeOn(Schedulers.computation()).subscribe(testSubscriber); + + IntStream.range(0, 1_000).forEach(source::onNext); + + // then + testSubscriber.awaitTerminalEvent(2, TimeUnit.SECONDS); + assertTrue(testSubscriber.getOnErrorEvents().size() == 0); + + } + + @Test + public void givenHotObservable_whenBufferIsDefined_shouldNotThrowException() { + // given + TestSubscriber> testSubscriber = new TestSubscriber<>(); + PublishSubject source = PublishSubject. create(); + + // when + source.buffer(1024).observeOn(Schedulers.computation()).subscribe(testSubscriber); + + IntStream.range(0, 1_000).forEach(source::onNext); + + // then + testSubscriber.awaitTerminalEvent(2, TimeUnit.SECONDS); + assertTrue(testSubscriber.getOnErrorEvents().size() == 0); + + } + + @Test + public void givenHotObservable_whenSkippingOperationIsDefined_shouldNotThrowException() { + // given + TestSubscriber testSubscriber = new TestSubscriber<>(); + PublishSubject source = PublishSubject. create(); + + // when + source.sample(100, TimeUnit.MILLISECONDS) + // .throttleFirst(100, TimeUnit.MILLISECONDS) + .observeOn(Schedulers.computation()).subscribe(testSubscriber); + + IntStream.range(0, 1_000).forEach(source::onNext); + + // then + testSubscriber.awaitTerminalEvent(2, TimeUnit.SECONDS); + assertTrue(testSubscriber.getOnErrorEvents().size() == 0); + + } + + @Test + public void givenHotObservable_whenOnBackpressureBufferDefined_shouldNotThrowException() { + // given + TestSubscriber testSubscriber = new TestSubscriber<>(); + + // when + Observable.range(1, 1_000_000).onBackpressureBuffer(16, () -> { + }, BackpressureOverflow.ON_OVERFLOW_DROP_OLDEST).observeOn(Schedulers.computation()).subscribe(testSubscriber); + + // then + testSubscriber.awaitTerminalEvent(2, TimeUnit.SECONDS); + assertTrue(testSubscriber.getOnErrorEvents().size() == 0); + + } + + @Test + public void givenHotObservable_whenOnBackpressureDropDefined_shouldNotThrowException() { + // given + TestSubscriber testSubscriber = new TestSubscriber<>(); + + // when + Observable.range(1, 1_000_000).onBackpressureDrop().observeOn(Schedulers.computation()).subscribe(testSubscriber); + + // then + testSubscriber.awaitTerminalEvent(2, TimeUnit.SECONDS); + assertTrue(testSubscriber.getOnErrorEvents().size() == 0); + + } +} diff --git a/rxjava/src/test/java/com/baeldung/rxjava/RxJavaTesting.java b/rxjava/src/test/java/com/baeldung/rxjava/RxJavaTesting.java new file mode 100644 index 0000000000..91c8ed540e --- /dev/null +++ b/rxjava/src/test/java/com/baeldung/rxjava/RxJavaTesting.java @@ -0,0 +1,98 @@ +package com.baeldung.rxjava; + +import org.junit.Test; +import rx.Observable; +import rx.observers.TestSubscriber; +import rx.schedulers.TestScheduler; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.assertThat; + +public class RxJavaTesting { + @Test + public void givenObservable_whenZip_shouldAssertBlockingInASameThread() { + // given + List letters = Arrays.asList("A", "B", "C", "D", "E"); + List results = new ArrayList<>(); + Observable observable = Observable.from(letters).zipWith(Observable.range(1, Integer.MAX_VALUE), (string, index) -> index + "-" + string); + + // when + observable.subscribe(results::add); + + // then + assertThat(results, notNullValue()); + assertThat(results, hasSize(5)); + assertThat(results, hasItems("1-A", "2-B", "3-C", "4-D", "5-E")); + } + + @Test + public void givenObservable_whenZip_shouldAssertOnTestSubscriber() { + // given + List letters = Arrays.asList("A", "B", "C", "D", "E"); + TestSubscriber subscriber = new TestSubscriber<>(); + + Observable observable = Observable.from(letters).zipWith(Observable.range(1, Integer.MAX_VALUE), ((string, index) -> index + "-" + string)); + + // when + observable.subscribe(subscriber); + + // then + subscriber.assertCompleted(); + subscriber.assertNoErrors(); + subscriber.assertValueCount(5); + assertThat(subscriber.getOnNextEvents(), hasItems("1-A", "2-B", "3-C", "4-D", "5-E")); + } + + @Test + public void givenTestObserver_whenExceptionWasThrowsOnObservable_observerShouldGetError() { + // given + List letters = Arrays.asList("A", "B", "C", "D", "E"); + TestSubscriber subscriber = new TestSubscriber<>(); + + Observable observable = Observable.from(letters).zipWith(Observable.range(1, Integer.MAX_VALUE), ((string, index) -> index + "-" + string)).concatWith(Observable.error(new RuntimeException("error in Observable"))); + + // when + observable.subscribe(subscriber); + + // then + subscriber.assertError(RuntimeException.class); + subscriber.assertNotCompleted(); + } + + @Test + public void givenObservableThatEmitsEventPerSecond_whenUseAdvanceByTime_shouldEmitEventPerSecond() { + // given + List letters = Arrays.asList("A", "B", "C", "D", "E"); + TestScheduler scheduler = new TestScheduler(); + TestSubscriber subscriber = new TestSubscriber<>(); + Observable tick = Observable.interval(1, TimeUnit.SECONDS, scheduler); + + Observable observable = Observable.from(letters).zipWith(tick, (string, index) -> index + "-" + string); + + observable.subscribeOn(scheduler).subscribe(subscriber); + + // expect + subscriber.assertNoValues(); + subscriber.assertNotCompleted(); + + // when + scheduler.advanceTimeBy(1, TimeUnit.SECONDS); + + // then + subscriber.assertNoErrors(); + subscriber.assertValueCount(1); + subscriber.assertValues("0-A"); + + // when + scheduler.advanceTimeTo(6, TimeUnit.SECONDS); + subscriber.assertCompleted(); + subscriber.assertNoErrors(); + subscriber.assertValueCount(5); + assertThat(subscriber.getOnNextEvents(), hasItems("0-A", "1-B", "2-C", "3-D", "4-E")); + } +} diff --git a/spring-5/.gitignore b/spring-5/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/spring-5/.gitignore @@ -0,0 +1,13 @@ +*.class + +#folders# +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* + +# Packaged files # +*.jar +*.war +*.ear \ No newline at end of file diff --git a/spring-5/README.md b/spring-5/README.md new file mode 100644 index 0000000000..0914388b49 --- /dev/null +++ b/spring-5/README.md @@ -0,0 +1,6 @@ +## Spring REST Example Project + +###The Course +The "REST With Spring" Classes: http://bit.ly/restwithspring + +### Relevant Articles: diff --git a/spring-5/pom.xml b/spring-5/pom.xml new file mode 100644 index 0000000000..ab05918ae4 --- /dev/null +++ b/spring-5/pom.xml @@ -0,0 +1,116 @@ + + + 4.0.0 + + com.baeldung + spring-5 + 0.0.1-SNAPSHOT + jar + + spring-5 + + + + org.springframework.boot + spring-boot-starter-parent + 2.0.0.BUILD-SNAPSHOT + + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.boot + spring-boot-starter-web + + + + + org.apache.commons + commons-lang3 + + + + + + org.springframework.boot + spring-boot-devtools + runtime + + + com.h2database + h2 + runtime + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + true + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + false + + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + true + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + false + + + + + + UTF-8 + UTF-8 + 1.8 + + + diff --git a/spring-5/src/main/java/com/baeldung/Spring5Application.java b/spring-5/src/main/java/com/baeldung/Spring5Application.java new file mode 100644 index 0000000000..41b5c1eed1 --- /dev/null +++ b/spring-5/src/main/java/com/baeldung/Spring5Application.java @@ -0,0 +1,13 @@ +package com.baeldung; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Spring5Application { + + public static void main(String[] args) { + SpringApplication.run(Spring5Application.class, args); + } + +} diff --git a/spring-5/src/main/java/com/baeldung/persistence/DataSetupBean.java b/spring-5/src/main/java/com/baeldung/persistence/DataSetupBean.java new file mode 100644 index 0000000000..7936a2b7af --- /dev/null +++ b/spring-5/src/main/java/com/baeldung/persistence/DataSetupBean.java @@ -0,0 +1,26 @@ +package com.baeldung.persistence; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; + +import java.util.stream.IntStream; + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.baeldung.web.Foo; + +@Component +public class DataSetupBean implements InitializingBean { + + @Autowired + private FooRepository repo; + + // + + @Override + public void afterPropertiesSet() throws Exception { + IntStream.range(1, 20).forEach(i -> repo.save(new Foo(randomAlphabetic(8)))); + } + +} diff --git a/spring-5/src/main/java/com/baeldung/persistence/FooRepository.java b/spring-5/src/main/java/com/baeldung/persistence/FooRepository.java new file mode 100644 index 0000000000..1f1e071158 --- /dev/null +++ b/spring-5/src/main/java/com/baeldung/persistence/FooRepository.java @@ -0,0 +1,10 @@ +package com.baeldung.persistence; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +import com.baeldung.web.Foo; + +public interface FooRepository extends JpaRepository, JpaSpecificationExecutor { + +} diff --git a/spring-5/src/main/java/com/baeldung/web/Foo.java b/spring-5/src/main/java/com/baeldung/web/Foo.java new file mode 100644 index 0000000000..c4868a9958 --- /dev/null +++ b/spring-5/src/main/java/com/baeldung/web/Foo.java @@ -0,0 +1,84 @@ +package com.baeldung.web; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class Foo { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + private String name; + + public Foo() { + super(); + } + + public Foo(final String name) { + super(); + + this.name = name; + } + + public Foo(final long id, final String name) { + super(); + + this.id = id; + this.name = name; + } + + // API + + public long getId() { + return id; + } + + public void setId(final long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + // + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Foo other = (Foo) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + + @Override + public String toString() { + return "Foo [name=" + name + "]"; + } + +} \ No newline at end of file diff --git a/spring-5/src/main/java/com/baeldung/web/FooController.java b/spring-5/src/main/java/com/baeldung/web/FooController.java new file mode 100644 index 0000000000..de6928033e --- /dev/null +++ b/spring-5/src/main/java/com/baeldung/web/FooController.java @@ -0,0 +1,62 @@ +package com.baeldung.web; + +import java.util.List; + +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.http.HttpStatus; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.persistence.FooRepository; + +@RestController("/foos") +public class FooController { + + @Autowired + private FooRepository repo; + + // API - read + + @RequestMapping(method = RequestMethod.GET, value = "/foos/{id}") + @ResponseBody + @Validated + public Foo findById(@PathVariable @Min(0) final long id) { + return repo.findOne(id); + } + + @RequestMapping(method = RequestMethod.GET) + @ResponseBody + public List findAll() { + return repo.findAll(); + } + + @RequestMapping(params = { "page", "size" }, method = RequestMethod.GET) + @ResponseBody + @Validated + public List findPaginated(@RequestParam("page") @Min(0) final int page, @Max(100) @RequestParam("size") final int size) { + final Page resultPage = repo.findAll(new PageRequest(page, size)); + return resultPage.getContent(); + } + + // API - write + + @RequestMapping(method = RequestMethod.PUT, value = "/foos/{id}") + @ResponseStatus(HttpStatus.OK) + @ResponseBody + public Foo update(@PathVariable("id") final String id, @RequestBody final Foo foo) { + return foo; + } + +} diff --git a/spring-5/src/main/resources/application.properties b/spring-5/src/main/resources/application.properties new file mode 100644 index 0000000000..886ea1978b --- /dev/null +++ b/spring-5/src/main/resources/application.properties @@ -0,0 +1,6 @@ +server.port=8081 + +security.user.name=user +security.user.password=pass + +logging.level.root=INFO \ No newline at end of file diff --git a/spring-5/src/test/java/com/baeldung/IntegrationTestExample1.java b/spring-5/src/test/java/com/baeldung/IntegrationTestExample1.java new file mode 100644 index 0000000000..0a27be4a95 --- /dev/null +++ b/spring-5/src/test/java/com/baeldung/IntegrationTestExample1.java @@ -0,0 +1,29 @@ +package com.baeldung; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class IntegrationTestExample1 { + + @Test + public void test1a() { + block(3000); + } + + @Test + public void test1b() { + block(3000); + } + + public static void block(long ms) { + try { + Thread.sleep(ms); + } catch (InterruptedException e) { + System.out.println("Thread interrupted"); + } + } +} diff --git a/spring-5/src/test/java/com/baeldung/IntegrationTestExample2.java b/spring-5/src/test/java/com/baeldung/IntegrationTestExample2.java new file mode 100644 index 0000000000..0bb2d47ef5 --- /dev/null +++ b/spring-5/src/test/java/com/baeldung/IntegrationTestExample2.java @@ -0,0 +1,29 @@ +package com.baeldung; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class IntegrationTestExample2 { + + @Test + public void test1a() { + block(3000); + } + + @Test + public void test1b() { + block(3000); + } + + public static void block(long ms) { + try { + Thread.sleep(ms); + } catch (InterruptedException e) { + System.out.println("Thread Interrupted"); + } + } +} diff --git a/spring-5/src/test/java/com/baeldung/ParallelTestExample.java b/spring-5/src/test/java/com/baeldung/ParallelTestExample.java new file mode 100644 index 0000000000..e73b8d4649 --- /dev/null +++ b/spring-5/src/test/java/com/baeldung/ParallelTestExample.java @@ -0,0 +1,24 @@ +package com.baeldung; + +import org.junit.Test; +import org.junit.experimental.ParallelComputer; +import org.junit.runner.Computer; +import org.junit.runner.JUnitCore; + +public class ParallelTestExample { + + @Test + public void runTests() { + final Class[] classes = { IntegrationTestExample1.class, IntegrationTestExample2.class }; + + JUnitCore.runClasses(new Computer(), classes); + } + + @Test + public void runTestsInParallel() { + final Class[] classes = { IntegrationTestExample1.class, IntegrationTestExample2.class }; + + JUnitCore.runClasses(new ParallelComputer(true, true), classes); + } + +} \ No newline at end of file diff --git a/spring-5/src/test/java/com/baeldung/Spring5ApplicationTests.java b/spring-5/src/test/java/com/baeldung/Spring5ApplicationTests.java new file mode 100644 index 0000000000..537ec56a89 --- /dev/null +++ b/spring-5/src/test/java/com/baeldung/Spring5ApplicationTests.java @@ -0,0 +1,16 @@ +package com.baeldung; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class Spring5ApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/spring-all/README.md b/spring-all/README.md index 90ae69300a..a8ea7c58c7 100644 --- a/spring-all/README.md +++ b/spring-all/README.md @@ -16,3 +16,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Quick Guide to Spring Controllers](http://www.baeldung.com/spring-controllers) - [Quick Guide to Spring Bean Scopes](http://www.baeldung.com/spring-bean-scopes) - [Introduction To Ehcache](http://www.baeldung.com/ehcache) +- [A Guide to the Spring Task Scheduler](http://www.baeldung.com/spring-task-scheduler) +- [Guide to Spring Retry](http://www.baeldung.com/spring-retry) diff --git a/spring-all/pom.xml b/spring-all/pom.xml index deb6bd6f6a..f28fe1f10d 100644 --- a/spring-all/pom.xml +++ b/spring-all/pom.xml @@ -11,7 +11,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-all/src/test/java/org/baeldung/properties/external/ExternalPropertiesWithXmlIntegrationTest.java b/spring-all/src/test/java/org/baeldung/properties/external/ExternalPropertiesWithXmlManualTest.java similarity index 95% rename from spring-all/src/test/java/org/baeldung/properties/external/ExternalPropertiesWithXmlIntegrationTest.java rename to spring-all/src/test/java/org/baeldung/properties/external/ExternalPropertiesWithXmlManualTest.java index 2ea2822b9a..a8a7bda91c 100644 --- a/spring-all/src/test/java/org/baeldung/properties/external/ExternalPropertiesWithXmlIntegrationTest.java +++ b/spring-all/src/test/java/org/baeldung/properties/external/ExternalPropertiesWithXmlManualTest.java @@ -13,7 +13,7 @@ import org.springframework.test.context.support.AnnotationConfigContextLoader; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = { ExternalPropertiesWithXmlConfig.class }, loader = AnnotationConfigContextLoader.class) @Ignore("manual only") -public class ExternalPropertiesWithXmlIntegrationTest { +public class ExternalPropertiesWithXmlManualTest { @Autowired private Environment env; diff --git a/spring-all/src/test/java/org/baeldung/springretry/SpringRetryTest.java b/spring-all/src/test/java/org/baeldung/springretry/SpringRetryIntegrationTest.java similarity index 96% rename from spring-all/src/test/java/org/baeldung/springretry/SpringRetryTest.java rename to spring-all/src/test/java/org/baeldung/springretry/SpringRetryIntegrationTest.java index 2f3411957e..d7d0943e6b 100644 --- a/spring-all/src/test/java/org/baeldung/springretry/SpringRetryTest.java +++ b/spring-all/src/test/java/org/baeldung/springretry/SpringRetryIntegrationTest.java @@ -12,7 +12,7 @@ import java.sql.SQLException; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = AppConfig.class, loader = AnnotationConfigContextLoader.class) -public class SpringRetryTest { +public class SpringRetryIntegrationTest { @Autowired private MyService myService; diff --git a/spring-all/src/test/java/org/baeldung/taskscheduler/ThreadPoolTaskSchedulerTest.java b/spring-all/src/test/java/org/baeldung/taskscheduler/ThreadPoolTaskSchedulerIntegrationTest.java similarity index 90% rename from spring-all/src/test/java/org/baeldung/taskscheduler/ThreadPoolTaskSchedulerTest.java rename to spring-all/src/test/java/org/baeldung/taskscheduler/ThreadPoolTaskSchedulerIntegrationTest.java index cc247cb384..d95857d384 100644 --- a/spring-all/src/test/java/org/baeldung/taskscheduler/ThreadPoolTaskSchedulerTest.java +++ b/spring-all/src/test/java/org/baeldung/taskscheduler/ThreadPoolTaskSchedulerIntegrationTest.java @@ -8,7 +8,8 @@ import org.springframework.test.context.support.AnnotationConfigContextLoader; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = { ThreadPoolTaskSchedulerConfig.class }, loader = AnnotationConfigContextLoader.class) -public class ThreadPoolTaskSchedulerTest { +public class ThreadPoolTaskSchedulerIntegrationTest { + @Test public void testThreadPoolTaskSchedulerAnnotation() throws InterruptedException { Thread.sleep(2550); diff --git a/spring-all/src/test/java/org/baeldung/test/IntegrationTestSuite.java b/spring-all/src/test/java/org/baeldung/test/IntegrationTestSuite.java index f9845f42a7..470ae9e538 100644 --- a/spring-all/src/test/java/org/baeldung/test/IntegrationTestSuite.java +++ b/spring-all/src/test/java/org/baeldung/test/IntegrationTestSuite.java @@ -5,7 +5,7 @@ import org.baeldung.properties.basic.PropertiesWithMultipleXmlsIntegrationTest; import org.baeldung.properties.basic.PropertiesWithXmlIntegrationTest; import org.baeldung.properties.external.ExternalPropertiesWithJavaIntegrationTest; import org.baeldung.properties.external.ExternalPropertiesWithMultipleXmlsIntegrationTest; -import org.baeldung.properties.external.ExternalPropertiesWithXmlIntegrationTest; +import org.baeldung.properties.external.ExternalPropertiesWithXmlManualTest; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; @@ -15,7 +15,7 @@ import org.junit.runners.Suite.SuiteClasses; PropertiesWithXmlIntegrationTest.class, ExternalPropertiesWithJavaIntegrationTest.class, ExternalPropertiesWithMultipleXmlsIntegrationTest.class, - ExternalPropertiesWithXmlIntegrationTest.class, + ExternalPropertiesWithXmlManualTest.class, ExtendedPropertiesWithJavaIntegrationTest.class, PropertiesWithMultipleXmlsIntegrationTest.class, })// @formatter:on diff --git a/spring-amqp/README.md b/spring-amqp/README.md new file mode 100644 index 0000000000..b0d16c9305 --- /dev/null +++ b/spring-amqp/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Messaging With Spring AMQP](http://www.baeldung.com/spring-amqp) diff --git a/spring-boot-servlet/.gitignore b/spring-boot-servlet/.gitignore new file mode 100644 index 0000000000..60be5b80aa --- /dev/null +++ b/spring-boot-servlet/.gitignore @@ -0,0 +1,4 @@ +/target/ +.settings/ +.classpath +.project diff --git a/spring-boot-servlet/README.md b/spring-boot-servlet/README.md new file mode 100644 index 0000000000..262a11fc36 --- /dev/null +++ b/spring-boot-servlet/README.md @@ -0,0 +1,2 @@ +###Relevant Articles: +- [How to Register a Servlet in a Java Web Application](http://www.baeldung.com/how-to-register-a-servlet-in-a-java-web-application/) \ No newline at end of file diff --git a/spring-boot-servlet/pom.xml b/spring-boot-servlet/pom.xml new file mode 100644 index 0000000000..3818e3468f --- /dev/null +++ b/spring-boot-servlet/pom.xml @@ -0,0 +1,55 @@ + + 4.0.0 + com.baeldung + spring-boot-servlet + 0.0.1-SNAPSHOT + war + spring-boot-servlet + + + org.springframework.boot + spring-boot-dependencies + 1.5.1.RELEASE + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + + org.apache.tomcat.embed + tomcat-embed-core + ${tomcat.version} + + + org.apache.tomcat.embed + tomcat-embed-jasper + ${tomcat.version} + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + UTF-8 + 1.8 + 8.5.11 + + + diff --git a/spring-boot-servlet/src/main/java/META-INF/MANIFEST.MF b/spring-boot-servlet/src/main/java/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..69ebae1751 --- /dev/null +++ b/spring-boot-servlet/src/main/java/META-INF/MANIFEST.MF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 +Main-Class: com.baeldung.ApplicationMain diff --git a/spring-boot-servlet/src/main/java/com/baeldung/ApplicationMain.java b/spring-boot-servlet/src/main/java/com/baeldung/ApplicationMain.java new file mode 100644 index 0000000000..66f2e85999 --- /dev/null +++ b/spring-boot-servlet/src/main/java/com/baeldung/ApplicationMain.java @@ -0,0 +1,19 @@ +package com.baeldung; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.support.SpringBootServletInitializer; + +@SpringBootApplication +public class ApplicationMain extends SpringBootServletInitializer { + + public static void main(String[] args) { + SpringApplication.run(ApplicationMain.class, args); + } + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(ApplicationMain.class); + } +} \ No newline at end of file diff --git a/spring-boot-servlet/src/main/java/com/baeldung/configuration/WebAppInitializer.java b/spring-boot-servlet/src/main/java/com/baeldung/configuration/WebAppInitializer.java new file mode 100644 index 0000000000..b7e22500f4 --- /dev/null +++ b/spring-boot-servlet/src/main/java/com/baeldung/configuration/WebAppInitializer.java @@ -0,0 +1,32 @@ +package com.baeldung.configuration; + +import org.springframework.web.WebApplicationInitializer; +import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; +import org.springframework.web.context.support.XmlWebApplicationContext; +import org.springframework.web.servlet.DispatcherServlet; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRegistration; + +public class WebAppInitializer implements WebApplicationInitializer { + + public void onStartup(ServletContext container) throws ServletException { + + AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); + ctx.register(WebMvcConfigure.class); + ctx.setServletContext(container); + + ServletRegistration.Dynamic servletOne = container.addServlet("SpringProgrammaticDispatcherServlet", new DispatcherServlet(ctx)); + servletOne.setLoadOnStartup(1); + servletOne.addMapping("/"); + + XmlWebApplicationContext xctx = new XmlWebApplicationContext(); + xctx.setConfigLocation("/WEB-INF/context.xml"); + xctx.setServletContext(container); + + ServletRegistration.Dynamic servletTwo = container.addServlet("SpringProgrammaticXMLDispatcherServlet", new DispatcherServlet(xctx)); + servletTwo.setLoadOnStartup(1); + servletTwo.addMapping("/"); + } + +} \ No newline at end of file diff --git a/spring-boot-servlet/src/main/java/com/baeldung/configuration/WebMvcConfigure.java b/spring-boot-servlet/src/main/java/com/baeldung/configuration/WebMvcConfigure.java new file mode 100644 index 0000000000..de9067de6e --- /dev/null +++ b/spring-boot-servlet/src/main/java/com/baeldung/configuration/WebMvcConfigure.java @@ -0,0 +1,40 @@ +package com.baeldung.configuration; + +import org.springframework.boot.web.support.ErrorPageFilter; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.resource.PathResourceResolver; +import org.springframework.web.servlet.view.InternalResourceViewResolver; + +@Configuration +public class WebMvcConfigure extends WebMvcConfigurerAdapter { + + @Bean + public ViewResolver getViewResolver() { + InternalResourceViewResolver resolver = new InternalResourceViewResolver(); + resolver.setPrefix("/WEB-INF/"); + resolver.setSuffix(".jsp"); + return resolver; + } + + @Override + public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { + configurer.enable(); + } + + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/resources/**").addResourceLocations("/resources/").setCachePeriod(3600).resourceChain(true).addResolver(new PathResourceResolver()); + } + + @Bean + public ErrorPageFilter errorPageFilter() { + return new ErrorPageFilter(); + } +} + diff --git a/spring-boot-servlet/src/main/java/com/baeldung/props/Constants.java b/spring-boot-servlet/src/main/java/com/baeldung/props/Constants.java new file mode 100644 index 0000000000..421401eec7 --- /dev/null +++ b/spring-boot-servlet/src/main/java/com/baeldung/props/Constants.java @@ -0,0 +1,20 @@ +package com.baeldung.props; + +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.Properties; + +public final class Constants { + + @Autowired + PropertySourcesLoader psl; + + public static final String breakLine = System.getProperty("line.separator"); + private static final PropertyLoader pl = new PropertyLoader(); + private static final Properties mainProps = pl.getProperties("custom.properties"); + public static final String DISPATCHER_SERVLET_NAME = mainProps.getProperty("dispatcher.servlet.name"); + public static final String DISPATCHER_SERVLET_MAPPING = mainProps.getProperty("dispatcher.servlet.mapping"); + private final String EXAMPLE_SERVLET_NAME = psl.getProperty("example.servlet.name"); + private final String EXAMPLE_SERVLET_MAPPING = psl.getProperty("example.servlet.mapping"); + +} diff --git a/spring-boot-servlet/src/main/java/com/baeldung/props/PropertyLoader.java b/spring-boot-servlet/src/main/java/com/baeldung/props/PropertyLoader.java new file mode 100644 index 0000000000..5d890d96fa --- /dev/null +++ b/spring-boot-servlet/src/main/java/com/baeldung/props/PropertyLoader.java @@ -0,0 +1,27 @@ +package com.baeldung.props; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +public class PropertyLoader { + private static final Logger log = LoggerFactory.getLogger(PropertyLoader.class); + + public Properties getProperties(String file) { + Properties prop = new Properties(); + InputStream input = null; + try { + input = getClass().getResourceAsStream(file); + prop.load(input); + if (input != null) { + input.close(); + } + } catch (IOException ex) { + log.error("IOException: " + ex); + } + return prop; + } +} diff --git a/spring-boot-servlet/src/main/java/com/baeldung/props/PropertySourcesLoader.java b/spring-boot-servlet/src/main/java/com/baeldung/props/PropertySourcesLoader.java new file mode 100644 index 0000000000..8c7b3a4af5 --- /dev/null +++ b/spring-boot-servlet/src/main/java/com/baeldung/props/PropertySourcesLoader.java @@ -0,0 +1,23 @@ +package com.baeldung.props; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.ConfigurableEnvironment; + +@Configuration +@ComponentScan(basePackages = { "com.baeldung.*" }) +@PropertySource("classpath:custom.properties") public class PropertySourcesLoader { + + private static final Logger log = LoggerFactory.getLogger(PropertySourcesLoader.class); + + @Autowired + ConfigurableEnvironment env; + + public String getProperty(String key) { + return env.getProperty(key); + } +} diff --git a/spring-boot-servlet/src/main/java/com/baeldung/servlets/GenericCustomServlet.java b/spring-boot-servlet/src/main/java/com/baeldung/servlets/GenericCustomServlet.java new file mode 100644 index 0000000000..c6543c9eef --- /dev/null +++ b/spring-boot-servlet/src/main/java/com/baeldung/servlets/GenericCustomServlet.java @@ -0,0 +1,18 @@ +package com.baeldung.servlets; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; + +public class GenericCustomServlet extends HttpServlet { + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + response.setContentType("text/html"); + PrintWriter out = response.getWriter(); + out.println("

Hello World

"); + } +} diff --git a/spring-boot-servlet/src/main/java/com/baeldung/servlets/javaee/AnnotationServlet.java b/spring-boot-servlet/src/main/java/com/baeldung/servlets/javaee/AnnotationServlet.java new file mode 100644 index 0000000000..d971e68cfa --- /dev/null +++ b/spring-boot-servlet/src/main/java/com/baeldung/servlets/javaee/AnnotationServlet.java @@ -0,0 +1,20 @@ +package com.baeldung.servlets.javaee; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@WebServlet(name = "AnnotationServlet", + description = "Example Servlet Using Annotations", + urlPatterns = { "/annotationservlet" }) +public class AnnotationServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + request.getRequestDispatcher("/annotationservlet.jsp").forward(request, response); + } +} diff --git a/spring-boot-servlet/src/main/java/com/baeldung/servlets/javaee/EEWebXmlServlet.java b/spring-boot-servlet/src/main/java/com/baeldung/servlets/javaee/EEWebXmlServlet.java new file mode 100644 index 0000000000..4209e815cd --- /dev/null +++ b/spring-boot-servlet/src/main/java/com/baeldung/servlets/javaee/EEWebXmlServlet.java @@ -0,0 +1,20 @@ +package com.baeldung.servlets.javaee; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; + +public class EEWebXmlServlet extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + response.setContentType("text/html"); + PrintWriter out = response.getWriter(); + out.println("

Hello World

"); + } +} \ No newline at end of file diff --git a/spring-boot-servlet/src/main/java/com/baeldung/servlets/springboot/SpringRegistrationBeanServlet.java b/spring-boot-servlet/src/main/java/com/baeldung/servlets/springboot/SpringRegistrationBeanServlet.java new file mode 100644 index 0000000000..4a34465894 --- /dev/null +++ b/spring-boot-servlet/src/main/java/com/baeldung/servlets/springboot/SpringRegistrationBeanServlet.java @@ -0,0 +1,19 @@ +package com.baeldung.servlets.springboot; + +import com.baeldung.servlets.GenericCustomServlet; +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class SpringRegistrationBeanServlet { + + @Bean + public ServletRegistrationBean genericCustomServlet() { + ServletRegistrationBean bean = new ServletRegistrationBean(new GenericCustomServlet(), "/springregistrationbeanservlet/*"); + bean.setLoadOnStartup(1); + return bean; + } +} + + diff --git a/spring-boot-servlet/src/main/java/com/baeldung/servlets/springboot/embedded/EmbeddedTomcatExample.java b/spring-boot-servlet/src/main/java/com/baeldung/servlets/springboot/embedded/EmbeddedTomcatExample.java new file mode 100644 index 0000000000..b2458f33c7 --- /dev/null +++ b/spring-boot-servlet/src/main/java/com/baeldung/servlets/springboot/embedded/EmbeddedTomcatExample.java @@ -0,0 +1,16 @@ +package com.baeldung.servlets.springboot.embedded; + +import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; +import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class EmbeddedTomcatExample { + + @Bean + public EmbeddedServletContainerFactory servletContainer() { + TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory(); + return tomcat; + } +} diff --git a/spring-boot-servlet/src/main/resources/application.properties b/spring-boot-servlet/src/main/resources/application.properties new file mode 100644 index 0000000000..4e9e2b4cf1 --- /dev/null +++ b/spring-boot-servlet/src/main/resources/application.properties @@ -0,0 +1,10 @@ +#Server Configuration +#server.port=8080 +#server.context-path=/javabootdata +#Resource Handling +#spring.resources.static-locations=classpath:/WEB-INF/resources +#spring.mvc.view.prefix=/WEB-INF/ +#spring.mvc.view.suffix=.jsp +#spring.resources.cache-period=3600 +servlet.name=dispatcherExample +servlet.mapping=/dispatcherExampleURL \ No newline at end of file diff --git a/spring-boot-servlet/src/main/resources/custom.properties b/spring-boot-servlet/src/main/resources/custom.properties new file mode 100644 index 0000000000..34f31bcd50 --- /dev/null +++ b/spring-boot-servlet/src/main/resources/custom.properties @@ -0,0 +1,4 @@ +dispatcher.servlet.name=dispatcherExample +dispatcher.servlet.mapping=/dispatcherExampleURL +example.servlet.name=dispatcherExample +example.servlet.mapping=/dispatcherExampleURL \ No newline at end of file diff --git a/spring-boot-servlet/src/main/webapp/WEB-INF/context.xml b/spring-boot-servlet/src/main/webapp/WEB-INF/context.xml new file mode 100644 index 0000000000..263bed4430 --- /dev/null +++ b/spring-boot-servlet/src/main/webapp/WEB-INF/context.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/spring-boot-servlet/src/main/webapp/WEB-INF/dispatcher.xml b/spring-boot-servlet/src/main/webapp/WEB-INF/dispatcher.xml new file mode 100644 index 0000000000..ade8e66777 --- /dev/null +++ b/spring-boot-servlet/src/main/webapp/WEB-INF/dispatcher.xml @@ -0,0 +1,16 @@ + + + + + + + + + \ No newline at end of file diff --git a/spring-boot-servlet/src/main/webapp/WEB-INF/web.xml b/spring-boot-servlet/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..60a4b079de --- /dev/null +++ b/spring-boot-servlet/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,40 @@ + + + JSP + + index.html + index.htm + index.jsp + + + + + EEWebXmlServlet + com.baeldung.servlets.javaee.EEWebXmlServlet + + + + EEWebXmlServlet + /eewebxmlservlet + + + + + SpringBootWebXmlServlet + org.springframework.web.servlet.DispatcherServlet + + contextConfigLocation + /WEB-INF/dispatcher.xml + + 1 + + + + SpringBootWebXmlServlet + / + + + + diff --git a/spring-boot-servlet/src/main/webapp/annotationservlet.jsp b/spring-boot-servlet/src/main/webapp/annotationservlet.jsp new file mode 100644 index 0000000000..f21748df50 --- /dev/null +++ b/spring-boot-servlet/src/main/webapp/annotationservlet.jsp @@ -0,0 +1 @@ +

Annotation Servlet!

\ No newline at end of file diff --git a/spring-boot-servlet/src/main/webapp/index.jsp b/spring-boot-servlet/src/main/webapp/index.jsp new file mode 100644 index 0000000000..e534282777 --- /dev/null +++ b/spring-boot-servlet/src/main/webapp/index.jsp @@ -0,0 +1 @@ +

Hello!

\ No newline at end of file diff --git a/spring-boot/README.MD b/spring-boot/README.MD index 05173ef318..d0a02c69fc 100644 --- a/spring-boot/README.MD +++ b/spring-boot/README.MD @@ -7,3 +7,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [A Guide to Spring in Eclipse STS](http://www.baeldung.com/eclipse-sts-spring) - [Introduction to WebJars](http://www.baeldung.com/maven-webjars) - [Create a Fat Jar App with Spring Boot](http://www.baeldung.com/deployable-fat-jar-spring-boot) +- [The @ServletComponentScan Annotation in Spring Boot](http://www.baeldung.com/spring-servletcomponentscan) +- [A Custom Data Binder in Spring MVC](http://www.baeldung.com/spring-mvc-custom-data-binder) +- [Intro to Building an Application with Spring Boot](http://www.baeldung.com/intro-to-spring-boot) diff --git a/spring-boot/pom.xml b/spring-boot/pom.xml index 68a5857865..e77ab10aff 100644 --- a/spring-boot/pom.xml +++ b/spring-boot/pom.xml @@ -1,5 +1,5 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 com.baeldung spring-boot @@ -12,8 +12,8 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE - + 1.5.1.RELEASE + @@ -87,6 +87,14 @@ jquery ${jquery.version} + + + org.apache.tomcat + tomcat-servlet-api + ${tomee-servlet-api.version} + provided + + @@ -166,7 +174,7 @@ - json + json @@ -186,6 +194,7 @@ 3.1.1 3.3.7-1 3.1.7 + 8.5.11
diff --git a/spring-boot/src/main/java/com/baeldung/annotation/servletcomponentscan/SpringBootAnnotatedApp.java b/spring-boot/src/main/java/com/baeldung/annotation/servletcomponentscan/SpringBootAnnotatedApp.java new file mode 100644 index 0000000000..b4d416dd96 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/annotation/servletcomponentscan/SpringBootAnnotatedApp.java @@ -0,0 +1,25 @@ +package com.baeldung.annotation.servletcomponentscan; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.servlet.ServletComponentScan; + +/** + * using the following annotations are equivalent: + *
  • + * @ServletComponentScan + *
  • + * @ServletComponentScan(basePackages = "com.baeldung.annotation.servletcomponentscan.components") + *
  • + * @ServletComponentScan(basePackageClasses = {AttrListener.class, HelloFilter.class, HelloServlet.class, EchoServlet.class}) + *
+ */ +@SpringBootApplication +@ServletComponentScan("com.baeldung.annotation.servletcomponentscan.components") +public class SpringBootAnnotatedApp { + + public static void main(String[] args) { + SpringApplication.run(SpringBootAnnotatedApp.class, args); + } + +} diff --git a/spring-boot/src/main/java/com/baeldung/annotation/servletcomponentscan/SpringBootPlainApp.java b/spring-boot/src/main/java/com/baeldung/annotation/servletcomponentscan/SpringBootPlainApp.java new file mode 100644 index 0000000000..8a39078aac --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/annotation/servletcomponentscan/SpringBootPlainApp.java @@ -0,0 +1,13 @@ +package com.baeldung.annotation.servletcomponentscan; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +@SpringBootApplication +@ComponentScan(basePackages = "com.baeldung.annotation.servletcomponentscan.components") +public class SpringBootPlainApp { + + public static void main(String[] args) { + } + +} diff --git a/spring-boot/src/main/java/com/baeldung/annotation/servletcomponentscan/components/AttrListener.java b/spring-boot/src/main/java/com/baeldung/annotation/servletcomponentscan/components/AttrListener.java new file mode 100644 index 0000000000..bad39c52c4 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/annotation/servletcomponentscan/components/AttrListener.java @@ -0,0 +1,23 @@ +package com.baeldung.annotation.servletcomponentscan.components; + +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.annotation.WebListener; + +@WebListener +public class AttrListener implements ServletContextListener { + + @Override + public void contextInitialized(ServletContextEvent servletContextEvent) { + servletContextEvent + .getServletContext() + .setAttribute("servlet-context-attr", "test"); + System.out.println("context init"); + } + + @Override + public void contextDestroyed(ServletContextEvent servletContextEvent) { + System.out.println("context destroy"); + } + +} diff --git a/spring-boot/src/main/java/com/baeldung/annotation/servletcomponentscan/components/EchoServlet.java b/spring-boot/src/main/java/com/baeldung/annotation/servletcomponentscan/components/EchoServlet.java new file mode 100644 index 0000000000..3419cd0eaf --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/annotation/servletcomponentscan/components/EchoServlet.java @@ -0,0 +1,29 @@ +package com.baeldung.annotation.servletcomponentscan.components; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; + +@WebServlet(name = "echo servlet", urlPatterns = "/echo") +public class EchoServlet extends HttpServlet { + + @Override + public void doPost(HttpServletRequest request, HttpServletResponse response) { + try { + Path path = File + .createTempFile("echo", "tmp") + .toPath(); + Files.copy(request.getInputStream(), path, StandardCopyOption.REPLACE_EXISTING); + Files.copy(path, response.getOutputStream()); + Files.delete(path); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/spring-boot/src/main/java/com/baeldung/annotation/servletcomponentscan/components/HelloFilter.java b/spring-boot/src/main/java/com/baeldung/annotation/servletcomponentscan/components/HelloFilter.java new file mode 100644 index 0000000000..dc2368c5b2 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/annotation/servletcomponentscan/components/HelloFilter.java @@ -0,0 +1,32 @@ +package com.baeldung.annotation.servletcomponentscan.components; + +import javax.servlet.*; +import javax.servlet.annotation.WebFilter; +import javax.servlet.annotation.WebInitParam; +import java.io.IOException; + +@WebFilter(urlPatterns = "/hello", description = "a filter for hello servlet", initParams = { @WebInitParam(name = "msg", value = "filtering ") }, filterName = "hello filter", servletNames = { "echo servlet" }) +public class HelloFilter implements Filter { + + private FilterConfig filterConfig; + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + System.out.println("filter init"); + this.filterConfig = filterConfig; + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + servletResponse + .getOutputStream() + .print(filterConfig.getInitParameter("msg")); + filterChain.doFilter(servletRequest, servletResponse); + } + + @Override + public void destroy() { + System.out.println("filter destroy"); + } + +} diff --git a/spring-boot/src/main/java/com/baeldung/annotation/servletcomponentscan/components/HelloServlet.java b/spring-boot/src/main/java/com/baeldung/annotation/servletcomponentscan/components/HelloServlet.java new file mode 100644 index 0000000000..aeae7aecc9 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/annotation/servletcomponentscan/components/HelloServlet.java @@ -0,0 +1,32 @@ +package com.baeldung.annotation.servletcomponentscan.components; + +import javax.servlet.ServletConfig; +import javax.servlet.annotation.WebInitParam; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@WebServlet(urlPatterns = "/hello", initParams = { @WebInitParam(name = "msg", value = "hello")}) +public class HelloServlet extends HttpServlet { + + private ServletConfig servletConfig; + + @Override + public void init(ServletConfig servletConfig){ + this.servletConfig = servletConfig; + } + + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) { + try { + response + .getOutputStream() + .write(servletConfig.getInitParameter("msg").getBytes()); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/spring-boot/src/main/java/com/baeldung/utils/Application.java b/spring-boot/src/main/java/com/baeldung/utils/Application.java new file mode 100644 index 0000000000..a3d9f9130c --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/utils/Application.java @@ -0,0 +1,18 @@ +package com.baeldung.utils; + +import javax.annotation.security.RolesAllowed; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +@SpringBootApplication +@ComponentScan(basePackages="com.baeldung.utils") +public class Application { + + @RolesAllowed("*") + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/spring-boot/src/main/java/com/baeldung/utils/controller/UtilsController.java b/spring-boot/src/main/java/com/baeldung/utils/controller/UtilsController.java new file mode 100644 index 0000000000..7b4827cdf2 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/utils/controller/UtilsController.java @@ -0,0 +1,49 @@ +package com.baeldung.utils.controller; + +import javax.servlet.http.HttpServletRequest; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.ServletRequestBindingException; +import org.springframework.web.bind.ServletRequestUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.util.WebUtils; + +@Controller +public class UtilsController { + + @GetMapping("/utils") + public String webUtils(Model model) { + return "utils"; + } + + @PostMapping("/setParam") + public String post(HttpServletRequest request, Model model) { + String param = ServletRequestUtils.getStringParameter(request, "param", "DEFAULT"); + +// Long param = ServletRequestUtils.getLongParameter(request, "param",1L); +// boolean param = ServletRequestUtils.getBooleanParameter(request, "param", true); +// double param = ServletRequestUtils.getDoubleParameter(request, "param", 1000); +// float param = ServletRequestUtils.getFloatParameter(request, "param", (float) 1.00); +// int param = ServletRequestUtils.getIntParameter(request, "param", 100); + +// try { +// ServletRequestUtils.getRequiredStringParameter(request, "param"); +// } catch (ServletRequestBindingException e) { +// e.printStackTrace(); +// } + + WebUtils.setSessionAttribute(request, "parameter", param); + model.addAttribute("parameter", "You set: "+(String) WebUtils.getSessionAttribute(request, "parameter")); + return "utils"; + } + + @GetMapping("/other") + public String other(HttpServletRequest request, Model model) { + String param = (String) WebUtils.getSessionAttribute(request, "parameter"); + model.addAttribute("parameter", param); + return "other"; + } + +} diff --git a/spring-boot/src/main/java/com/baeldung/TestController.java b/spring-boot/src/main/java/com/baeldung/webjar/TestController.java similarity index 91% rename from spring-boot/src/main/java/com/baeldung/TestController.java rename to spring-boot/src/main/java/com/baeldung/webjar/TestController.java index 0e28ca67f8..e8e7fd5ce9 100644 --- a/spring-boot/src/main/java/com/baeldung/TestController.java +++ b/spring-boot/src/main/java/com/baeldung/webjar/TestController.java @@ -1,4 +1,4 @@ -package com.baeldung; +package com.baeldung.webjar; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; diff --git a/spring-boot/src/main/java/com/baeldung/WebjarsdemoApplication.java b/spring-boot/src/main/java/com/baeldung/webjar/WebjarsdemoApplication.java similarity index 77% rename from spring-boot/src/main/java/com/baeldung/WebjarsdemoApplication.java rename to spring-boot/src/main/java/com/baeldung/webjar/WebjarsdemoApplication.java index 35490131c6..d2135754c9 100644 --- a/spring-boot/src/main/java/com/baeldung/WebjarsdemoApplication.java +++ b/spring-boot/src/main/java/com/baeldung/webjar/WebjarsdemoApplication.java @@ -1,7 +1,8 @@ -package com.baeldung; +package com.baeldung.webjar; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; @SpringBootApplication public class WebjarsdemoApplication { diff --git a/spring-boot/src/main/java/org/baeldung/common/error/SpringHelloServletRegistrationBean.java b/spring-boot/src/main/java/org/baeldung/common/error/SpringHelloServletRegistrationBean.java index 78680baf7d..723afddd06 100644 --- a/spring-boot/src/main/java/org/baeldung/common/error/SpringHelloServletRegistrationBean.java +++ b/spring-boot/src/main/java/org/baeldung/common/error/SpringHelloServletRegistrationBean.java @@ -1,8 +1,8 @@ package org.baeldung.common.error; -import javax.servlet.Servlet; +import org.springframework.boot.web.servlet.ServletRegistrationBean; -import org.springframework.boot.context.embedded.ServletRegistrationBean; +import javax.servlet.Servlet; public class SpringHelloServletRegistrationBean extends ServletRegistrationBean { diff --git a/spring-boot/src/main/java/org/baeldung/common/properties/MyServletContainerCustomizationBean.java b/spring-boot/src/main/java/org/baeldung/common/properties/MyServletContainerCustomizationBean.java index 97130bed6a..9b5a0aa948 100644 --- a/spring-boot/src/main/java/org/baeldung/common/properties/MyServletContainerCustomizationBean.java +++ b/spring-boot/src/main/java/org/baeldung/common/properties/MyServletContainerCustomizationBean.java @@ -2,7 +2,7 @@ package org.baeldung.common.properties; import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer; import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer; -import org.springframework.boot.context.embedded.ErrorPage; +import org.springframework.boot.web.servlet.ErrorPage; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; diff --git a/spring-boot/src/main/java/org/baeldung/controller/GenericEntityController.java b/spring-boot/src/main/java/org/baeldung/controller/GenericEntityController.java index 7d6293056a..7d1ad7d899 100644 --- a/spring-boot/src/main/java/org/baeldung/controller/GenericEntityController.java +++ b/spring-boot/src/main/java/org/baeldung/controller/GenericEntityController.java @@ -54,8 +54,6 @@ public class GenericEntityController { @GetMapping("/entity/findbyversion") public ResponseEntity findByVersion(@Version String version) { - return version != null - ? new ResponseEntity(entityList.stream().findFirst().get(), HttpStatus.OK) - : new ResponseEntity(HttpStatus.NOT_FOUND); + return version != null ? new ResponseEntity(entityList.stream().findFirst().get(), HttpStatus.OK) : new ResponseEntity(HttpStatus.NOT_FOUND); } } diff --git a/spring-boot/src/main/resources/templates/other.html b/spring-boot/src/main/resources/templates/other.html new file mode 100644 index 0000000000..d13373f9fe --- /dev/null +++ b/spring-boot/src/main/resources/templates/other.html @@ -0,0 +1,16 @@ + + + + +Spring Utils Demo + + + + Parameter set by you:

+ + \ No newline at end of file diff --git a/spring-boot/src/main/resources/templates/utils.html b/spring-boot/src/main/resources/templates/utils.html new file mode 100644 index 0000000000..93030f424f --- /dev/null +++ b/spring-boot/src/main/resources/templates/utils.html @@ -0,0 +1,23 @@ + + + + +Spring Utils Demo + + + +

+

Set Parameter:

+

+ + +

+
+Another Page + + \ No newline at end of file diff --git a/spring-boot/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithServletComponentIntegrationTest.java b/spring-boot/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithServletComponentIntegrationTest.java new file mode 100644 index 0000000000..8d5eb56bf4 --- /dev/null +++ b/spring-boot/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithServletComponentIntegrationTest.java @@ -0,0 +1,65 @@ +package com.baeldung.annotation.servletcomponentscan; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.servlet.FilterRegistration; +import javax.servlet.ServletContext; + +import static org.junit.Assert.*; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = SpringBootAnnotatedApp.class) +@AutoConfigureMockMvc +@TestPropertySource(properties = { "security.basic.enabled=false" }) +public class SpringBootWithServletComponentIntegrationTest { + + @Autowired private ServletContext servletContext; + + @Test + public void givenServletContext_whenAccessAttrs_thenFoundAttrsPutInServletListner() { + assertNotNull(servletContext); + assertNotNull(servletContext.getAttribute("servlet-context-attr")); + assertEquals("test", servletContext.getAttribute("servlet-context-attr")); + } + + @Test + public void givenServletContext_whenCheckHelloFilterMappings_thenCorrect() { + assertNotNull(servletContext); + FilterRegistration filterRegistration = servletContext.getFilterRegistration("hello filter"); + + assertNotNull(filterRegistration); + assertTrue(filterRegistration + .getServletNameMappings() + .contains("echo servlet")); + } + + @Autowired private TestRestTemplate restTemplate; + + @Test + public void givenServletFilter_whenGetHello_thenRequestFiltered() { + ResponseEntity responseEntity = this.restTemplate.getForEntity("/hello", String.class); + assertEquals(HttpStatus.OK, responseEntity.getStatusCode()); + assertEquals("filtering hello", responseEntity.getBody()); + } + + @Test + public void givenFilterAndServlet_whenPostEcho_thenEchoFiltered() { + ResponseEntity responseEntity = this.restTemplate.postForEntity("/echo", "echo", String.class); + assertEquals(HttpStatus.OK, responseEntity.getStatusCode()); + assertEquals("filtering echo", responseEntity.getBody()); + } + + + +} + + diff --git a/spring-boot/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithoutServletComponentIntegrationTest.java b/spring-boot/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithoutServletComponentIntegrationTest.java new file mode 100644 index 0000000000..64507ad02c --- /dev/null +++ b/spring-boot/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithoutServletComponentIntegrationTest.java @@ -0,0 +1,50 @@ +package com.baeldung.annotation.servletcomponentscan; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.servlet.FilterRegistration; +import javax.servlet.ServletContext; + +import static org.junit.Assert.*; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = SpringBootPlainApp.class) +@AutoConfigureMockMvc +@TestPropertySource(properties = { "security.basic.enabled=false" }) +public class SpringBootWithoutServletComponentIntegrationTest { + + @Autowired private ServletContext servletContext; + + @Autowired private TestRestTemplate restTemplate; + + @Test + public void givenServletContext_whenAccessAttrs_thenNotFound() { + assertNull(servletContext.getAttribute("servlet-context-attr")); + } + + @Test + public void givenServletFilter_whenGetHello_thenEndpointNotFound() { + ResponseEntity responseEntity = this.restTemplate.getForEntity("/hello", String.class); + assertEquals(HttpStatus.NOT_FOUND, responseEntity.getStatusCode()); + } + + @Test + public void givenServletContext_whenCheckFilterMappings_thenEmpty() { + assertNotNull(servletContext); + FilterRegistration filterRegistration = servletContext.getFilterRegistration("hello filter"); + + assertNull(filterRegistration); + } + +} + + diff --git a/spring-boot/src/test/java/com/baeldung/intro/AppTest.java b/spring-boot/src/test/java/com/baeldung/intro/AppLiveTest.java similarity index 89% rename from spring-boot/src/test/java/com/baeldung/intro/AppTest.java rename to spring-boot/src/test/java/com/baeldung/intro/AppLiveTest.java index 749fe68838..af46fe0423 100644 --- a/spring-boot/src/test/java/com/baeldung/intro/AppTest.java +++ b/spring-boot/src/test/java/com/baeldung/intro/AppLiveTest.java @@ -1,39 +1,41 @@ -package com.baeldung.intro; - -import static org.hamcrest.Matchers.equalTo; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.http.MediaType; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; - -@RunWith(SpringRunner.class) -@SpringBootTest -@AutoConfigureMockMvc -public class AppTest { - - @Autowired - private MockMvc mvc; - - @Test - public void getIndex() throws Exception { - mvc.perform(MockMvcRequestBuilders.get("/").accept(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andExpect(content().string(equalTo("Index Page"))); - } - - @Test - public void getLocal() throws Exception { - mvc.perform(MockMvcRequestBuilders.get("/local").accept(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andExpect(content().string(equalTo("/local"))); - } - +package com.baeldung.intro; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +import static org.hamcrest.Matchers.equalTo; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringRunner.class) +@SpringBootTest +@AutoConfigureMockMvc +@TestPropertySource(properties = { "security.basic.enabled=false" }) +public class AppLiveTest { + + @Autowired + private MockMvc mvc; + + @Test + public void getIndex() throws Exception { + mvc.perform(MockMvcRequestBuilders.get("/").accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().string(equalTo("Index Page"))); + } + + @Test + public void getLocal() throws Exception { + mvc.perform(MockMvcRequestBuilders.get("/local").accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().string(equalTo("/local"))); + } + } \ No newline at end of file diff --git a/spring-boot/src/test/java/com/baeldung/utils/UtilsControllerTest.java b/spring-boot/src/test/java/com/baeldung/utils/UtilsControllerTest.java new file mode 100644 index 0000000000..7aed45dbb0 --- /dev/null +++ b/spring-boot/src/test/java/com/baeldung/utils/UtilsControllerTest.java @@ -0,0 +1,41 @@ +package com.baeldung.utils; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.MockitoAnnotations; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + + +import com.baeldung.utils.controller.UtilsController; + +public class UtilsControllerTest { + + @InjectMocks + private UtilsController utilsController; + + private MockMvc mockMvc; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + this.mockMvc = MockMvcBuilders.standaloneSetup(utilsController) + .build(); + + } + + @Test + public void givenParameter_setRequestParam_andSetSessionAttribute() throws Exception { + String param = "testparam"; + this.mockMvc.perform( + post("/setParam") + .param("param", param) + .sessionAttr("parameter", param)) + .andExpect(status().isOk()); + } + +} diff --git a/spring-boot/src/test/java/com/baeldung/WebjarsdemoApplicationIntegrationTest.java b/spring-boot/src/test/java/com/baeldung/webjar/WebjarsdemoApplicationIntegrationTest.java similarity index 68% rename from spring-boot/src/test/java/com/baeldung/WebjarsdemoApplicationIntegrationTest.java rename to spring-boot/src/test/java/com/baeldung/webjar/WebjarsdemoApplicationIntegrationTest.java index 3558682b97..d6e71dcf6b 100644 --- a/spring-boot/src/test/java/com/baeldung/WebjarsdemoApplicationIntegrationTest.java +++ b/spring-boot/src/test/java/com/baeldung/webjar/WebjarsdemoApplicationIntegrationTest.java @@ -1,13 +1,13 @@ -package com.baeldung; +package com.baeldung.webjar; import org.junit.Test; import org.junit.runner.RunWith; -import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; @RunWith(SpringJUnit4ClassRunner.class) -@SpringApplicationConfiguration(classes = WebjarsdemoApplication.class) +@SpringBootTest(classes = WebjarsdemoApplication.class) @WebAppConfiguration public class WebjarsdemoApplicationIntegrationTest { diff --git a/spring-boot/src/test/java/org/baeldung/SpringBootApplicationIntegrationTest.java b/spring-boot/src/test/java/org/baeldung/SpringBootApplicationIntegrationTest.java index 8cdcdb2216..87c59a4662 100644 --- a/spring-boot/src/test/java/org/baeldung/SpringBootApplicationIntegrationTest.java +++ b/spring-boot/src/test/java/org/baeldung/SpringBootApplicationIntegrationTest.java @@ -9,7 +9,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.MediaType; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; @@ -22,7 +22,7 @@ import org.springframework.web.context.WebApplicationContext; import java.nio.charset.Charset; @RunWith(SpringJUnit4ClassRunner.class) -@SpringApplicationConfiguration(classes = Application.class) +@SpringBootTest(classes = Application.class) @WebAppConfiguration public class SpringBootApplicationIntegrationTest { @Autowired @@ -45,29 +45,22 @@ public class SpringBootApplicationIntegrationTest { public void givenRequestHasBeenMade_whenMeetsFindByDateOfGivenConditions_thenCorrect() throws Exception { MediaType contentType = new MediaType(MediaType.APPLICATION_JSON.getType(), MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8")); - mockMvc.perform(MockMvcRequestBuilders.get("/entity/findbydate/{date}", "2011-12-03T10:15:30")) - .andExpect(MockMvcResultMatchers.status().isOk()) - .andExpect(MockMvcResultMatchers.content().contentType(contentType)) - .andExpect(jsonPath("$.id", equalTo(1))); + mockMvc.perform(MockMvcRequestBuilders.get("/entity/findbydate/{date}", "2011-12-03T10:15:30")).andExpect(MockMvcResultMatchers.status().isOk()).andExpect(MockMvcResultMatchers.content().contentType(contentType)) + .andExpect(jsonPath("$.id", equalTo(1))); } @Test public void givenRequestHasBeenMade_whenMeetsFindByModeOfGivenConditions_thenCorrect() throws Exception { MediaType contentType = new MediaType(MediaType.APPLICATION_JSON.getType(), MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8")); - mockMvc.perform(MockMvcRequestBuilders.get("/entity/findbymode/{mode}", Modes.ALPHA.name())) - .andExpect(MockMvcResultMatchers.status().isOk()) - .andExpect(MockMvcResultMatchers.content().contentType(contentType)) - .andExpect(jsonPath("$.id", equalTo(1))); + mockMvc.perform(MockMvcRequestBuilders.get("/entity/findbymode/{mode}", Modes.ALPHA.name())).andExpect(MockMvcResultMatchers.status().isOk()).andExpect(MockMvcResultMatchers.content().contentType(contentType)).andExpect(jsonPath("$.id", equalTo(1))); } @Test public void givenRequestHasBeenMade_whenMeetsFindByVersionOfGivenConditions_thenCorrect() throws Exception { MediaType contentType = new MediaType(MediaType.APPLICATION_JSON.getType(), MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8")); - mockMvc.perform(MockMvcRequestBuilders.get("/entity/findbyversion").header("Version", "1.0.0")) - .andExpect(MockMvcResultMatchers.status().isOk()) - .andExpect(MockMvcResultMatchers.content().contentType(contentType)) - .andExpect(jsonPath("$.id", equalTo(1))); + mockMvc.perform(MockMvcRequestBuilders.get("/entity/findbyversion").header("Version", "1.0.0")).andExpect(MockMvcResultMatchers.status().isOk()).andExpect(MockMvcResultMatchers.content().contentType(contentType)) + .andExpect(jsonPath("$.id", equalTo(1))); } } diff --git a/spring-boot/src/test/java/org/baeldung/SpringBootJPAIntegrationTest.java b/spring-boot/src/test/java/org/baeldung/SpringBootJPAIntegrationTest.java index 233684bc24..d4b19e6a1d 100644 --- a/spring-boot/src/test/java/org/baeldung/SpringBootJPAIntegrationTest.java +++ b/spring-boot/src/test/java/org/baeldung/SpringBootJPAIntegrationTest.java @@ -5,14 +5,14 @@ import org.baeldung.repository.GenericEntityRepository; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @RunWith(SpringJUnit4ClassRunner.class) -@SpringApplicationConfiguration(classes = Application.class) +@SpringBootTest(classes = Application.class) public class SpringBootJPAIntegrationTest { @Autowired private GenericEntityRepository genericEntityRepository; diff --git a/spring-boot/src/test/java/org/baeldung/SpringBootMailIntegrationTest.java b/spring-boot/src/test/java/org/baeldung/SpringBootMailIntegrationTest.java index cec25f20f9..10e3d6d60b 100644 --- a/spring-boot/src/test/java/org/baeldung/SpringBootMailIntegrationTest.java +++ b/spring-boot/src/test/java/org/baeldung/SpringBootMailIntegrationTest.java @@ -5,7 +5,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -23,7 +23,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; @RunWith(SpringJUnit4ClassRunner.class) -@SpringApplicationConfiguration(classes = Application.class) +@SpringBootTest(classes = Application.class) public class SpringBootMailIntegrationTest { @Autowired private JavaMailSender javaMailSender; diff --git a/spring-cloud-data-flow/batch-job/pom.xml b/spring-cloud-data-flow/batch-job/pom.xml index 3d05732027..5e519e9a35 100644 --- a/spring-cloud-data-flow/batch-job/pom.xml +++ b/spring-cloud-data-flow/batch-job/pom.xml @@ -14,7 +14,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-cloud-data-flow/data-flow-server/pom.xml b/spring-cloud-data-flow/data-flow-server/pom.xml index b1f920c94e..1ed2d4fb74 100644 --- a/spring-cloud-data-flow/data-flow-server/pom.xml +++ b/spring-cloud-data-flow/data-flow-server/pom.xml @@ -14,7 +14,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-cloud-data-flow/data-flow-shell/pom.xml b/spring-cloud-data-flow/data-flow-shell/pom.xml index 55fa995052..d3bd297152 100644 --- a/spring-cloud-data-flow/data-flow-shell/pom.xml +++ b/spring-cloud-data-flow/data-flow-shell/pom.xml @@ -14,7 +14,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-cloud-data-flow/log-sink/pom.xml b/spring-cloud-data-flow/log-sink/pom.xml index 6443ed88c8..dc21132b9f 100644 --- a/spring-cloud-data-flow/log-sink/pom.xml +++ b/spring-cloud-data-flow/log-sink/pom.xml @@ -14,7 +14,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-cloud-data-flow/time-processor/pom.xml b/spring-cloud-data-flow/time-processor/pom.xml index d7553b110f..51a66014e0 100644 --- a/spring-cloud-data-flow/time-processor/pom.xml +++ b/spring-cloud-data-flow/time-processor/pom.xml @@ -14,7 +14,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-cloud-data-flow/time-source/pom.xml b/spring-cloud-data-flow/time-source/pom.xml index 2523dfabea..57933c2833 100644 --- a/spring-cloud-data-flow/time-source/pom.xml +++ b/spring-cloud-data-flow/time-source/pom.xml @@ -14,7 +14,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-cloud/spring-cloud-bootstrap/application-config/resource.properties b/spring-cloud/spring-cloud-bootstrap/application-config/book-service.properties similarity index 91% rename from spring-cloud/spring-cloud-bootstrap/application-config/resource.properties rename to spring-cloud/spring-cloud-bootstrap/application-config/book-service.properties index 9fb610d655..e1244a0cf0 100644 --- a/spring-cloud/spring-cloud-bootstrap/application-config/resource.properties +++ b/spring-cloud/spring-cloud-bootstrap/application-config/book-service.properties @@ -1,4 +1,4 @@ -spring.application.name=resource +spring.application.name=book-service server.port=8083 resource.returnString=hello cloud diff --git a/spring-cloud/spring-cloud-bootstrap/application-config/gateway.properties b/spring-cloud/spring-cloud-bootstrap/application-config/gateway.properties index 6f52a59db9..09f7f3bf4a 100644 --- a/spring-cloud/spring-cloud-bootstrap/application-config/gateway.properties +++ b/spring-cloud/spring-cloud-bootstrap/application-config/gateway.properties @@ -6,9 +6,13 @@ eureka.client.registryFetchIntervalSeconds = 5 management.security.sessions=always -zuul.routes.resource.path=/resource/** -zuul.routes.resource.sensitive-headers=Set-Cookie,Authorization -hystrix.command.resource.execution.isolation.thread.timeoutInMilliseconds=600000 +zuul.routes.book-service.path=/book-service/** +zuul.routes.book-service.sensitive-headers=Set-Cookie,Authorization +hystrix.command.book-service.execution.isolation.thread.timeoutInMilliseconds=600000 + +zuul.routes.rating-service.path=/rating-service/** +zuul.routes.rating-service.sensitive-headers=Set-Cookie,Authorization +hystrix.command.rating-service.execution.isolation.thread.timeoutInMilliseconds=600000 zuul.routes.discovery.path=/discovery/** zuul.routes.discovery.sensitive-headers=Set-Cookie,Authorization diff --git a/spring-cloud/spring-cloud-bootstrap/application-config/rating-service.properties b/spring-cloud/spring-cloud-bootstrap/application-config/rating-service.properties new file mode 100644 index 0000000000..4817d12c83 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/application-config/rating-service.properties @@ -0,0 +1,17 @@ +spring.application.name=rating-service +server.port=8084 + +resource.returnString=hello cloud +resource.user.returnString=hello cloud user +resource.admin.returnString=hello cloud admin + +eureka.client.region = default +eureka.client.registryFetchIntervalSeconds = 5 + +management.security.sessions=never + +logging.level.org.springframework.web.=debug +logging.level.org.springframework.security=debug + +spring.redis.host=localhost +spring.redis.port=6379 diff --git a/spring-cloud/spring-cloud-bootstrap/config/pom.xml b/spring-cloud/spring-cloud-bootstrap/config/pom.xml index 24d054a87b..2c8ad65102 100644 --- a/spring-cloud/spring-cloud-bootstrap/config/pom.xml +++ b/spring-cloud/spring-cloud-bootstrap/config/pom.xml @@ -10,7 +10,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-cloud/spring-cloud-bootstrap/discovery/pom.xml b/spring-cloud/spring-cloud-bootstrap/discovery/pom.xml index be3bfbb0be..40a186350c 100644 --- a/spring-cloud/spring-cloud-bootstrap/discovery/pom.xml +++ b/spring-cloud/spring-cloud-bootstrap/discovery/pom.xml @@ -10,7 +10,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml b/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml index 9186f12226..044730ba22 100644 --- a/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml +++ b/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml @@ -10,7 +10,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/SecurityConfig.java b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/SecurityConfig.java index 60dccf9042..9e5c424403 100644 --- a/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/SecurityConfig.java +++ b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/SecurityConfig.java @@ -22,14 +22,14 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() - .antMatchers("/resource/hello/cloud").permitAll() + .antMatchers("/book-service/books").permitAll() .antMatchers("/eureka/**").hasRole("ADMIN") .anyRequest().authenticated() .and() .formLogin() .and() .logout().permitAll() - .logoutSuccessUrl("/resource/hello/cloud").permitAll() + .logoutSuccessUrl("/book-service/books").permitAll() .and() .csrf() .disable(); diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/src/test/java/com/baeldung/spring/cloud/bootstrap/gateway/GatewayApplicationLiveTest.java b/spring-cloud/spring-cloud-bootstrap/gateway/src/test/java/com/baeldung/spring/cloud/bootstrap/gateway/GatewayApplicationLiveTest.java deleted file mode 100644 index cea431d461..0000000000 --- a/spring-cloud/spring-cloud-bootstrap/gateway/src/test/java/com/baeldung/spring/cloud/bootstrap/gateway/GatewayApplicationLiveTest.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.baeldung.spring.cloud.bootstrap.gateway; - -import org.junit.Assert; -import org.junit.Test; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.http.*; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; - -public class GatewayApplicationLiveTest { - - @Test - public void testAccess() throws Exception { - TestRestTemplate testRestTemplate = new TestRestTemplate(); - String testUrl = "http://localhost:8080"; - - ResponseEntity response = testRestTemplate.getForEntity(testUrl + "/resource/hello/cloud", String.class); - Assert.assertEquals(HttpStatus.OK, response.getStatusCode()); - Assert.assertEquals("hello cloud", response.getBody()); - - //try the protected resource and confirm the redirect to login - response = testRestTemplate.getForEntity(testUrl + "/resource/hello/user", String.class); - Assert.assertEquals(HttpStatus.FOUND, response.getStatusCode()); - Assert.assertEquals("http://localhost:8080/login", response.getHeaders().get("Location").get(0)); - - //login as user/password - MultiValueMap form = new LinkedMultiValueMap<>(); - form.add("username", "user"); - form.add("password", "password"); - response = testRestTemplate.postForEntity(testUrl + "/login", form, String.class); - - //extract the session from the cookie and propagate it to the next request - String sessionCookie = response.getHeaders().get("Set-Cookie").get(0).split(";")[0]; - HttpHeaders headers = new HttpHeaders(); - headers.add("Cookie", sessionCookie); - HttpEntity httpEntity = new HttpEntity<>(headers); - - //request the protected resource - response = testRestTemplate.exchange(testUrl + "/resource/hello/user", HttpMethod.GET, httpEntity, String.class); - Assert.assertEquals(HttpStatus.OK, response.getStatusCode()); - Assert.assertEquals("hello cloud user", response.getBody()); - - //request the admin protected resource to determine it is still protected - response = testRestTemplate.exchange(testUrl + "/resource/hello/admin", HttpMethod.GET, httpEntity, String.class); - Assert.assertEquals(HttpStatus.FORBIDDEN, response.getStatusCode()); - - //login as the admin - form.clear(); - form.add("username", "admin"); - form.add("password", "admin"); - response = testRestTemplate.postForEntity(testUrl + "/login", form, String.class); - - //extract the session from the cookie and propagate it to the next request - sessionCookie = response.getHeaders().get("Set-Cookie").get(0).split(";")[0]; - headers = new HttpHeaders(); - headers.add("Cookie", sessionCookie); - httpEntity = new HttpEntity<>(headers); - - //request the protected resource - response = testRestTemplate.exchange(testUrl + "/resource/hello/admin", HttpMethod.GET, httpEntity, String.class); - Assert.assertEquals(HttpStatus.OK, response.getStatusCode()); - Assert.assertEquals("hello cloud admin", response.getBody()); - - //request the discovery resources as the admin - response = testRestTemplate.exchange(testUrl + "/discovery", HttpMethod.GET, httpEntity, String.class); - Assert.assertEquals(HttpStatus.OK, response.getStatusCode()); - } - -} \ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/src/test/java/com/baeldung/spring/cloud/bootstrap/gateway/IntegrationLiveTest.java b/spring-cloud/spring-cloud-bootstrap/gateway/src/test/java/com/baeldung/spring/cloud/bootstrap/gateway/IntegrationLiveTest.java new file mode 100644 index 0000000000..47a4b744eb --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/gateway/src/test/java/com/baeldung/spring/cloud/bootstrap/gateway/IntegrationLiveTest.java @@ -0,0 +1,201 @@ +package com.baeldung.spring.cloud.bootstrap.gateway; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import org.apache.http.entity.ContentType; +import org.junit.Assert; +import org.junit.Test; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.http.*; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; + +public class IntegrationLiveTest { + + private TestRestTemplate testRestTemplate = new TestRestTemplate(); + private String testUrl = "http://localhost:8080"; + + @Test + public void testAccess() throws Exception { + ResponseEntity response = testRestTemplate.getForEntity(testUrl + "/book-service/books", String.class); + Assert.assertEquals(HttpStatus.OK, response.getStatusCode()); + Assert.assertNotNull(response.getBody()); + + //try the protected resource and confirm the redirect to login + response = testRestTemplate.getForEntity(testUrl + "/book-service/books/1", String.class); + Assert.assertEquals(HttpStatus.FOUND, response.getStatusCode()); + Assert.assertEquals("http://localhost:8080/login", response.getHeaders().get("Location").get(0)); + + //login as user/password + MultiValueMap form = new LinkedMultiValueMap<>(); + form.add("username", "user"); + form.add("password", "password"); + response = testRestTemplate.postForEntity(testUrl + "/login", form, String.class); + + //extract the session from the cookie and propagate it to the next request + String sessionCookie = response.getHeaders().get("Set-Cookie").get(0).split(";")[0]; + HttpHeaders headers = new HttpHeaders(); + headers.add("Cookie", sessionCookie); + HttpEntity httpEntity = new HttpEntity<>(headers); + + addBook(); + + //request the protected resource + response = testRestTemplate.exchange(testUrl + "/book-service/books/1", HttpMethod.GET, httpEntity, String.class); + Assert.assertEquals(HttpStatus.OK, response.getStatusCode()); + Assert.assertNotNull(response.getBody()); + + addRatings(); + + //request the admin protected resource to determine it is still protected + response = testRestTemplate.exchange(testUrl + "/rating-service/ratings", HttpMethod.GET, httpEntity, String.class); + Assert.assertEquals(HttpStatus.FORBIDDEN, response.getStatusCode()); + + //login as the admin + form.clear(); + form.add("username", "admin"); + form.add("password", "admin"); + response = testRestTemplate.postForEntity(testUrl + "/login", form, String.class); + + //extract the session from the cookie and propagate it to the next request + sessionCookie = response.getHeaders().get("Set-Cookie").get(0).split(";")[0]; + headers = new HttpHeaders(); + headers.add("Cookie", sessionCookie); + httpEntity = new HttpEntity<>(headers); + + //request the protected resource + response = testRestTemplate.exchange(testUrl + "/rating-service/ratings", HttpMethod.GET, httpEntity, String.class); + Assert.assertEquals(HttpStatus.OK, response.getStatusCode()); + Assert.assertNotNull(response.getBody()); + + //request the discovery resources as the admin + response = testRestTemplate.exchange(testUrl + "/discovery", HttpMethod.GET, httpEntity, String.class); + Assert.assertEquals(HttpStatus.OK, response.getStatusCode()); + } + + private void addRatings() { + //login as user/password + MultiValueMap form = new LinkedMultiValueMap<>(); + form.add("username", "user"); + form.add("password", "password"); + ResponseEntity response = testRestTemplate.postForEntity(testUrl + "/login", form, String.class); + + //extract the session from the cookie and propagate it to the next request + String sessionCookie = response.getHeaders().get("Set-Cookie").get(0).split(";")[0]; + HttpHeaders headers = new HttpHeaders(); + headers.add("Cookie", sessionCookie); + headers.add("ContentType", ContentType.APPLICATION_JSON.getMimeType()); + Rating rating = new Rating(1L, 4); + + HttpEntity httpEntity = new HttpEntity<>(rating, headers); + + //request the protected resource + ResponseEntity bookResponse = testRestTemplate.postForEntity(testUrl + "/rating-service/ratings", httpEntity, Rating.class); + Assert.assertEquals(HttpStatus.OK, bookResponse.getStatusCode()); + Assert.assertEquals(rating.getBookId(), bookResponse.getBody().getBookId()); + Assert.assertEquals(rating.getStars(), bookResponse.getBody().getStars()); + } + + private void addBook(){ + //login as user/password + MultiValueMap form = new LinkedMultiValueMap<>(); + form.add("username", "admin"); + form.add("password", "admin"); + ResponseEntity response = testRestTemplate.postForEntity(testUrl + "/login", form, String.class); + + //extract the session from the cookie and propagate it to the next request + String sessionCookie = response.getHeaders().get("Set-Cookie").get(0).split(";")[0]; + HttpHeaders headers = new HttpHeaders(); + headers.add("Cookie", sessionCookie); + headers.add("ContentType", ContentType.APPLICATION_JSON.getMimeType()); + Book book = new Book("Baeldung", "How to spring cloud"); + + HttpEntity httpEntity = new HttpEntity<>(book, headers); + + //request the protected resource + ResponseEntity bookResponse = testRestTemplate.postForEntity(testUrl + "/book-service/books", httpEntity, Book.class); + Assert.assertEquals(HttpStatus.OK, bookResponse.getStatusCode()); + Assert.assertEquals(book.getAuthor(), bookResponse.getBody().getAuthor()); + Assert.assertEquals(book.getTitle(), bookResponse.getBody().getTitle()); + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Book { + + private Long id; + private String author; + private String title; + + public Book() { + } + + public Book(String author, String title) { + this.author = author; + this.title = title; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Rating { + private Long id; + private Long bookId; + private int stars; + + public Rating() { + } + + public Rating(Long bookId, int stars) { + this.bookId = bookId; + this.stars = stars; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getBookId() { + return bookId; + } + + public void setBookId(Long bookId) { + this.bookId = bookId; + } + + public int getStars() { + return stars; + } + + public void setStars(int stars) { + this.stars = stars; + } + } + + +} \ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/pom.xml b/spring-cloud/spring-cloud-bootstrap/pom.xml index 9a1b2e6d0e..ccfbdb9735 100644 --- a/spring-cloud/spring-cloud-bootstrap/pom.xml +++ b/spring-cloud/spring-cloud-bootstrap/pom.xml @@ -14,7 +14,8 @@ config discovery gateway - resource + svc-book + svc-rating diff --git a/spring-cloud/spring-cloud-bootstrap/resource/src/main/java/com/baeldung/spring/cloud/bootstrap/resource/ResourceApplication.java b/spring-cloud/spring-cloud-bootstrap/resource/src/main/java/com/baeldung/spring/cloud/bootstrap/resource/ResourceApplication.java deleted file mode 100644 index accef18a14..0000000000 --- a/spring-cloud/spring-cloud-bootstrap/resource/src/main/java/com/baeldung/spring/cloud/bootstrap/resource/ResourceApplication.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.baeldung.spring.cloud.bootstrap.resource; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.netflix.eureka.EnableEurekaClient; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@SpringBootApplication -@EnableEurekaClient -@RestController -public class ResourceApplication { - public static void main(String[] args) { - SpringApplication.run(ResourceApplication.class, args); - } - - @Value("${resource.returnString}") - private String returnString; - - @Value("${resource.user.returnString}") - private String userReturnString; - - @Value("${resource.admin.returnString}") - private String adminReturnString; - - @RequestMapping("/hello/cloud") - public String getString() { - return returnString; - } - - @RequestMapping("/hello/user") - public String getUserString() { - return userReturnString; - } - - @RequestMapping("/hello/admin") - public String getAdminString() { - return adminReturnString; - } -} diff --git a/spring-cloud/spring-cloud-bootstrap/resource/pom.xml b/spring-cloud/spring-cloud-bootstrap/svc-book/pom.xml similarity index 86% rename from spring-cloud/spring-cloud-bootstrap/resource/pom.xml rename to spring-cloud/spring-cloud-bootstrap/svc-book/pom.xml index 1472693de8..c351c444f6 100644 --- a/spring-cloud/spring-cloud-bootstrap/resource/pom.xml +++ b/spring-cloud/spring-cloud-bootstrap/svc-book/pom.xml @@ -4,13 +4,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - resource + com.baeldung.spring.cloud + svc-book 1.0.0-SNAPSHOT org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE @@ -41,6 +42,17 @@ spring-boot-starter-data-redis + + org.springframework.boot + spring-boot-starter-data-jpa + + + + com.h2database + h2 + runtime + + org.springframework.boot spring-boot-starter-test diff --git a/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/BookServiceApplication.java b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/BookServiceApplication.java new file mode 100644 index 0000000000..c5499cd924 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/BookServiceApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.spring.cloud.bootstrap.svcbook; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.eureka.EnableEurekaClient; + +@SpringBootApplication +@EnableEurekaClient +public class BookServiceApplication { + public static void main(String[] args) { + SpringApplication.run(BookServiceApplication.class, args); + } +} diff --git a/spring-cloud/spring-cloud-bootstrap/resource/src/main/java/com/baeldung/spring/cloud/bootstrap/resource/SecurityConfig.java b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/SecurityConfig.java similarity index 72% rename from spring-cloud/spring-cloud-bootstrap/resource/src/main/java/com/baeldung/spring/cloud/bootstrap/resource/SecurityConfig.java rename to spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/SecurityConfig.java index 0b0de6ec20..6aa996c575 100644 --- a/spring-cloud/spring-cloud-bootstrap/resource/src/main/java/com/baeldung/spring/cloud/bootstrap/resource/SecurityConfig.java +++ b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/SecurityConfig.java @@ -1,7 +1,8 @@ -package com.baeldung.spring.cloud.bootstrap.resource; +package com.baeldung.spring.cloud.bootstrap.svcbook; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; @@ -22,9 +23,11 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { http.httpBasic() .disable() .authorizeRequests() - .antMatchers("/hello/cloud").permitAll() - .antMatchers("/hello/user").hasAnyRole("USER", "ADMIN") - .antMatchers("/hello/admin").hasRole("ADMIN") + .antMatchers(HttpMethod.GET, "/books").permitAll() + .antMatchers(HttpMethod.GET, "/books/*").permitAll() + .antMatchers(HttpMethod.POST, "/books").hasRole("ADMIN") + .antMatchers(HttpMethod.PATCH, "/books/*").hasRole("ADMIN") + .antMatchers(HttpMethod.DELETE, "/books/*").hasRole("ADMIN") .anyRequest().authenticated() .and() .csrf() diff --git a/spring-cloud/spring-cloud-bootstrap/resource/src/main/java/com/baeldung/spring/cloud/bootstrap/resource/SessionConfig.java b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/SessionConfig.java similarity index 87% rename from spring-cloud/spring-cloud-bootstrap/resource/src/main/java/com/baeldung/spring/cloud/bootstrap/resource/SessionConfig.java rename to spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/SessionConfig.java index f11f316826..dbde068069 100644 --- a/spring-cloud/spring-cloud-bootstrap/resource/src/main/java/com/baeldung/spring/cloud/bootstrap/resource/SessionConfig.java +++ b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/SessionConfig.java @@ -1,4 +1,4 @@ -package com.baeldung.spring.cloud.bootstrap.resource; +package com.baeldung.spring.cloud.bootstrap.svcbook; import org.springframework.context.annotation.Configuration; import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; diff --git a/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/Book.java b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/Book.java new file mode 100644 index 0000000000..33ea8dcb81 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/Book.java @@ -0,0 +1,45 @@ +package com.baeldung.spring.cloud.bootstrap.svcbook.book; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +@JsonIgnoreProperties(ignoreUnknown = true) +public class Book { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + private String author; + private String title; + + public Book() { + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } +} diff --git a/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookController.java b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookController.java new file mode 100644 index 0000000000..d00f114b8c --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookController.java @@ -0,0 +1,40 @@ +package com.baeldung.spring.cloud.bootstrap.svcbook.book; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + +@RestController +@RequestMapping("/books") +public class BookController { + + @Autowired + private BookService bookService; + + @GetMapping("") + public List findAllBooks() { + return bookService.findAllBooks(); + } + + @GetMapping("/{bookId}") + public Book findBook(@PathVariable Long bookId) { + return bookService.findBookById(bookId); + } + + @PostMapping("") + public Book createBook(@RequestBody Book book) { + return bookService.createBook(book); + } + + @DeleteMapping("/{bookId}") + public void deleteBook(@PathVariable Long bookId) { + bookService.deleteBook(bookId); + } + + @PatchMapping("/{bookId") + public Book updateBook(@RequestBody Map updates, @PathVariable Long bookId) { + return bookService.updateBook(updates, bookId); + } +} diff --git a/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookNotFoundException.java b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookNotFoundException.java new file mode 100644 index 0000000000..f0a4797387 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookNotFoundException.java @@ -0,0 +1,11 @@ +package com.baeldung.spring.cloud.bootstrap.svcbook.book; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(HttpStatus.NOT_FOUND) +class BookNotFoundException extends RuntimeException { + BookNotFoundException(String message) { + super(message); + } +} diff --git a/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookRepository.java b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookRepository.java new file mode 100644 index 0000000000..66fd3880c5 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookRepository.java @@ -0,0 +1,6 @@ +package com.baeldung.spring.cloud.bootstrap.svcbook.book; + +import org.springframework.data.jpa.repository.JpaRepository; + +interface BookRepository extends JpaRepository{ +} diff --git a/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookService.java b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookService.java new file mode 100644 index 0000000000..cfcbf15757 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookService.java @@ -0,0 +1,55 @@ +package com.baeldung.spring.cloud.bootstrap.svcbook.book; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +@Service +@Transactional(readOnly = true) +public class BookService { + + @Autowired + private BookRepository bookRepository; + + public List findAllBooks() { + return bookRepository.findAll(); + } + + public Book findBookById(Long bookId) { + return Optional.ofNullable(bookRepository.findOne(bookId)) + .orElseThrow(() -> new BookNotFoundException("Book not found. ID: " + bookId)); + } + + @Transactional(propagation = Propagation.REQUIRED) + public Book createBook(Book book) { + Book newBook = new Book(); + newBook.setTitle(book.getTitle()); + newBook.setAuthor(book.getAuthor()); + return bookRepository.save(newBook); + } + + @Transactional(propagation = Propagation.REQUIRED) + public void deleteBook(Long bookId) { + bookRepository.delete(bookId); + } + + @Transactional(propagation = Propagation.REQUIRED) + public Book updateBook(Map updates, Long bookId) { + Book book = findBookById(bookId); + updates.keySet().forEach(key -> { + switch (key) { + case "author": + book.setAuthor(updates.get(key)); + break; + case "title": + book.setTitle(updates.get(key)); + } + }); + return bookRepository.save(book); + } +} diff --git a/spring-cloud/spring-cloud-bootstrap/resource/src/main/resources/bootstrap.properties b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/resources/bootstrap.properties similarity index 87% rename from spring-cloud/spring-cloud-bootstrap/resource/src/main/resources/bootstrap.properties rename to spring-cloud/spring-cloud-bootstrap/svc-book/src/main/resources/bootstrap.properties index 9ecfb46125..8f3a3261ac 100644 --- a/spring-cloud/spring-cloud-bootstrap/resource/src/main/resources/bootstrap.properties +++ b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/resources/bootstrap.properties @@ -1,4 +1,4 @@ -spring.cloud.config.name=resource +spring.cloud.config.name=book-service spring.cloud.config.discovery.service-id=config spring.cloud.config.discovery.enabled=true spring.cloud.config.username=configUser diff --git a/spring-cloud/spring-cloud-bootstrap/svc-rating/pom.xml b/spring-cloud/spring-cloud-bootstrap/svc-rating/pom.xml new file mode 100644 index 0000000000..2285286812 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/svc-rating/pom.xml @@ -0,0 +1,96 @@ + + + 4.0.0 + + com.baeldung.spring.cloud + svc-rating + 1.0.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + 1.4.4.RELEASE + + + + + + org.springframework.cloud + spring-cloud-starter-config + + + org.springframework.cloud + spring-cloud-starter-eureka + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-security + + + + org.springframework.session + spring-session + + + org.springframework.boot + spring-boot-starter-data-redis + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + com.h2database + h2 + runtime + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud-dependencies.version} + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + + + Brixton.SR7 + 3.6.0 + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/RatingServiceApplication.java b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/RatingServiceApplication.java new file mode 100644 index 0000000000..61074e0bcc --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/RatingServiceApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.spring.cloud.bootstrap.svcrating; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.eureka.EnableEurekaClient; + +@SpringBootApplication +@EnableEurekaClient +public class RatingServiceApplication { + public static void main(String[] args) { + SpringApplication.run(RatingServiceApplication.class, args); + } +} \ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/SecurityConfig.java b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/SecurityConfig.java new file mode 100644 index 0000000000..171fbba7af --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/SecurityConfig.java @@ -0,0 +1,36 @@ +package com.baeldung.spring.cloud.bootstrap.svcrating; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@EnableWebSecurity +@Configuration +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Autowired + public void configureGlobal1(AuthenticationManagerBuilder auth) throws Exception { + //try in memory auth with no users to support the case that this will allow for users that are logged in to go anywhere + auth.inMemoryAuthentication(); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.httpBasic() + .disable() + .authorizeRequests() + .regexMatchers("^/ratings\\?bookId.*$").authenticated() + .antMatchers(HttpMethod.POST,"/ratings").authenticated() + .antMatchers(HttpMethod.PATCH,"/ratings/*").hasRole("ADMIN") + .antMatchers(HttpMethod.DELETE,"/ratings/*").hasRole("ADMIN") + .antMatchers(HttpMethod.GET,"/ratings").hasRole("ADMIN") + .anyRequest().authenticated() + .and() + .csrf() + .disable(); + } +} diff --git a/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/SessionConfig.java b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/SessionConfig.java new file mode 100644 index 0000000000..62bc701868 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/SessionConfig.java @@ -0,0 +1,10 @@ +package com.baeldung.spring.cloud.bootstrap.svcrating; + +import org.springframework.context.annotation.Configuration; +import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; +import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer; + +@Configuration +@EnableRedisHttpSession +public class SessionConfig extends AbstractHttpSessionApplicationInitializer { +} diff --git a/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/Rating.java b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/Rating.java new file mode 100644 index 0000000000..ae44f9ae2e --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/Rating.java @@ -0,0 +1,52 @@ +package com.baeldung.spring.cloud.bootstrap.svcrating.rating; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +@JsonIgnoreProperties(ignoreUnknown = true) +public class Rating { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + private Long bookId; + private int stars; + + public Rating() { + } + + public Rating(Long id, Long bookId, int stars) { + this.id = id; + this.bookId = bookId; + this.stars = stars; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getBookId() { + return bookId; + } + + public void setBookId(Long bookId) { + this.bookId = bookId; + } + + public int getStars() { + return stars; + } + + public void setStars(int stars) { + this.stars = stars; + } +} diff --git a/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingController.java b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingController.java new file mode 100644 index 0000000000..83452ad747 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingController.java @@ -0,0 +1,38 @@ +package com.baeldung.spring.cloud.bootstrap.svcrating.rating; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + +@RestController +@RequestMapping("/ratings") +public class RatingController { + + @Autowired + private RatingService ratingService; + + @GetMapping("") + public List findRatingsByBookId(@RequestParam(required = false, defaultValue = "0") Long bookId) { + if (bookId.equals(0L)) { + return ratingService.findAllRatings(); + } + return ratingService.findRatingsByBookId(bookId); + } + + @PostMapping("") + public Rating createRating(@RequestBody Rating rating) { + return ratingService.createRating(rating); + } + + @DeleteMapping("/{ratingId}") + public void deleteRating(@PathVariable Long ratingId) { + ratingService.deleteRating(ratingId); + } + + @PatchMapping("/{ratingId") + public Rating updateRating(@RequestBody Map updates, @PathVariable Long ratingId) { + return ratingService.updateRating(updates, ratingId); + } +} diff --git a/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingNotFoundException.java b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingNotFoundException.java new file mode 100644 index 0000000000..473d636a71 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingNotFoundException.java @@ -0,0 +1,11 @@ +package com.baeldung.spring.cloud.bootstrap.svcrating.rating; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(HttpStatus.NOT_FOUND) +class RatingNotFoundException extends RuntimeException { + RatingNotFoundException(String message) { + super(message); + } +} diff --git a/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingRepository.java b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingRepository.java new file mode 100644 index 0000000000..08d781b5a3 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingRepository.java @@ -0,0 +1,9 @@ +package com.baeldung.spring.cloud.bootstrap.svcrating.rating; + +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +interface RatingRepository extends JpaRepository{ + List findRatingsByBookId(Long bookId); +} diff --git a/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingService.java b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingService.java new file mode 100644 index 0000000000..a2360b7be5 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingService.java @@ -0,0 +1,57 @@ +package com.baeldung.spring.cloud.bootstrap.svcrating.rating; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +@Service +@Transactional(readOnly = true) +public class RatingService { + + @Autowired + private RatingRepository ratingRepository; + + public Rating findRatingById(Long ratingId) { + return Optional.ofNullable(ratingRepository.findOne(ratingId)) + .orElseThrow(() -> new RatingNotFoundException("Rating not found. ID: " + ratingId)); + } + + public List findRatingsByBookId(Long bookId) { + return ratingRepository.findRatingsByBookId(bookId); + } + + public List findAllRatings() { + return ratingRepository.findAll(); + } + + @Transactional(propagation = Propagation.REQUIRED) + public Rating createRating(Rating rating) { + Rating newRating = new Rating(); + newRating.setBookId(rating.getBookId()); + newRating.setStars(rating.getStars()); + return ratingRepository.save(newRating); + } + + @Transactional(propagation = Propagation.REQUIRED) + public void deleteRating(Long ratingId) { + ratingRepository.delete(ratingId); + } + + @Transactional(propagation = Propagation.REQUIRED) + public Rating updateRating(Map updates, Long ratingId) { + Rating rating = findRatingById(ratingId); + updates.keySet().forEach(key -> { + switch (key) { + case "stars": + rating.setStars(Integer.parseInt(updates.get(key))); + break; + } + }); + return ratingRepository.save(rating); + } +} diff --git a/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/resources/bootstrap.properties b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/resources/bootstrap.properties new file mode 100644 index 0000000000..be5cf7f1e1 --- /dev/null +++ b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/resources/bootstrap.properties @@ -0,0 +1,7 @@ +spring.cloud.config.name=rating-service +spring.cloud.config.discovery.service-id=config +spring.cloud.config.discovery.enabled=true +spring.cloud.config.username=configUser +spring.cloud.config.password=configPassword + +eureka.client.serviceUrl.defaultZone=http://discUser:discPassword@localhost:8082/eureka/ diff --git a/spring-cloud/spring-cloud-config/pom.xml b/spring-cloud/spring-cloud-config/pom.xml index d25037a49f..56ff377956 100644 --- a/spring-cloud/spring-cloud-config/pom.xml +++ b/spring-cloud/spring-cloud-config/pom.xml @@ -16,7 +16,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-cloud/spring-cloud-ribbon-client/pom.xml b/spring-cloud/spring-cloud-ribbon-client/pom.xml index 8aee41f5c4..d70de51a58 100644 --- a/spring-cloud/spring-cloud-ribbon-client/pom.xml +++ b/spring-cloud/spring-cloud-ribbon-client/pom.xml @@ -11,7 +11,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-core/README.md b/spring-core/README.md index f6aaaf44a0..a32d30939f 100644 --- a/spring-core/README.md +++ b/spring-core/README.md @@ -3,4 +3,4 @@ - [Exploring the Spring BeanFactory API](http://www.baeldung.com/spring-beanfactory) - [How to use the Spring FactoryBean?](http://www.baeldung.com/spring-factorybean) - [Constructor Dependency Injection in Spring](http://www.baeldung.com/constructor-injection-in-spring) -- [Constructor Injection in Spring with Lombok](http://inprogress.baeldung.com/constructor-injection-in-spring-with-lombok) +- [Constructor Injection in Spring with Lombok](http://www.baeldung.com/spring-injection-lombok) diff --git a/spring-core/src/main/java/com/baeldung/Ebook.java b/spring-core/src/main/java/com/baeldung/Ebook.java new file mode 100644 index 0000000000..fc29ddfcf5 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/Ebook.java @@ -0,0 +1,20 @@ +package com.baeldung; + +public class Ebook { + + private int bookId; + private String bookTitle; + + public int getBookId() { + return bookId; + } + public void setBookId(int bookId) { + this.bookId = bookId; + } + public String getBookTitle() { + return bookTitle; + } + public void setBookTitle(String bookTitle) { + this.bookTitle = bookTitle; + } +} diff --git a/spring-core/src/main/java/com/baeldung/EbookRepository.java b/spring-core/src/main/java/com/baeldung/EbookRepository.java new file mode 100644 index 0000000000..661283c355 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/EbookRepository.java @@ -0,0 +1,5 @@ +package com.baeldung; + +public interface EbookRepository { + String titleById(int id); +} diff --git a/spring-core/src/main/java/com/baeldung/LibraryUtils.java b/spring-core/src/main/java/com/baeldung/LibraryUtils.java new file mode 100644 index 0000000000..49af60c89d --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/LibraryUtils.java @@ -0,0 +1,12 @@ +package com.baeldung; + +import org.springframework.beans.factory.annotation.Autowired; + +public class LibraryUtils { + @Autowired + private EbookRepository eBookRepository; + + public String findBook(int id) { + return eBookRepository.titleById(id); + } +} diff --git a/spring-core/src/main/java/com/baeldung/Member.java b/spring-core/src/main/java/com/baeldung/Member.java new file mode 100644 index 0000000000..ceebb32017 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/Member.java @@ -0,0 +1,20 @@ +package com.baeldung; + +public class Member { + + private int memberId; + private String memberName; + + public int getMemberId() { + return memberId; + } + public void setMemberId(int memberId) { + this.memberId = memberId; + } + public String getMemberName() { + return memberName; + } + public void setMemberName(String memberName) { + this.memberName = memberName; + } +} diff --git a/spring-core/src/main/java/com/baeldung/Reservation.java b/spring-core/src/main/java/com/baeldung/Reservation.java new file mode 100644 index 0000000000..ed33bb6464 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/Reservation.java @@ -0,0 +1,14 @@ +package com.baeldung; + +import org.springframework.beans.factory.annotation.Autowired; + +public class Reservation { + private Member member; + private Ebook eBook; + + @Autowired + public Reservation(Member member, Ebook eBook) { + this.member = member; + this.eBook = eBook; + } +} diff --git a/spring-core/src/main/java/com/baeldung/lombok/Apologizer.java b/spring-core/src/main/java/com/baeldung/lombok/ApologizeService.java similarity index 83% rename from spring-core/src/main/java/com/baeldung/lombok/Apologizer.java rename to spring-core/src/main/java/com/baeldung/lombok/ApologizeService.java index ddce9cdc52..25ef65cad2 100644 --- a/spring-core/src/main/java/com/baeldung/lombok/Apologizer.java +++ b/spring-core/src/main/java/com/baeldung/lombok/ApologizeService.java @@ -6,13 +6,13 @@ import org.springframework.stereotype.Component; @Component @AllArgsConstructor -public class Apologizer { +public class ApologizeService { private final Translator translator; private final String message; @Autowired - public Apologizer(Translator translator) { + public ApologizeService(Translator translator) { this(translator, "sorry"); } diff --git a/spring-core/src/main/java/com/baeldung/lombok/Fareweller.java b/spring-core/src/main/java/com/baeldung/lombok/FarewellService.java similarity index 79% rename from spring-core/src/main/java/com/baeldung/lombok/Fareweller.java rename to spring-core/src/main/java/com/baeldung/lombok/FarewellService.java index b10ebb72b9..4e8c4993cb 100644 --- a/spring-core/src/main/java/com/baeldung/lombok/Fareweller.java +++ b/spring-core/src/main/java/com/baeldung/lombok/FarewellService.java @@ -4,11 +4,11 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component -public class Fareweller { +public class FarewellService { private final Translator translator; - public Fareweller(Translator translator) { + public FarewellService(Translator translator) { this.translator = translator; } diff --git a/spring-core/src/main/java/com/baeldung/lombok/Greeter.java b/spring-core/src/main/java/com/baeldung/lombok/GreetingService.java similarity index 90% rename from spring-core/src/main/java/com/baeldung/lombok/Greeter.java rename to spring-core/src/main/java/com/baeldung/lombok/GreetingService.java index ddbc024ce7..0e03e177e1 100644 --- a/spring-core/src/main/java/com/baeldung/lombok/Greeter.java +++ b/spring-core/src/main/java/com/baeldung/lombok/GreetingService.java @@ -4,7 +4,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component -public class Greeter { +public class GreetingService { @Autowired private Translator translator; diff --git a/spring-core/src/main/java/com/baeldung/lombok/Thanker.java b/spring-core/src/main/java/com/baeldung/lombok/ThankingService.java similarity index 76% rename from spring-core/src/main/java/com/baeldung/lombok/Thanker.java rename to spring-core/src/main/java/com/baeldung/lombok/ThankingService.java index 784100c258..f3bdf8bb7f 100644 --- a/spring-core/src/main/java/com/baeldung/lombok/Thanker.java +++ b/spring-core/src/main/java/com/baeldung/lombok/ThankingService.java @@ -1,12 +1,11 @@ package com.baeldung.lombok; import lombok.AllArgsConstructor; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component @AllArgsConstructor -public class Thanker { +public class ThankingService { private final Translator translator; diff --git a/spring-core/src/test/java/com/baeldung/lombok/ApologizerAutowiringTest.java b/spring-core/src/test/java/com/baeldung/lombok/ApologizeServiceAutowiringTest.java similarity index 84% rename from spring-core/src/test/java/com/baeldung/lombok/ApologizerAutowiringTest.java rename to spring-core/src/test/java/com/baeldung/lombok/ApologizeServiceAutowiringTest.java index 3e7c775f91..755fc5868b 100644 --- a/spring-core/src/test/java/com/baeldung/lombok/ApologizerAutowiringTest.java +++ b/spring-core/src/test/java/com/baeldung/lombok/ApologizeServiceAutowiringTest.java @@ -14,12 +14,12 @@ import static org.mockito.Mockito.when; @ContextConfiguration( loader = AnnotationConfigContextLoader.class, classes = TestConfig.class) -public class ApologizerAutowiringTest { +public class ApologizeServiceAutowiringTest { private final static String TRANSLATED = "TRANSLATED"; @Autowired - private Apologizer apologizer; + private ApologizeService apologizeService; @Autowired private Translator translator; @@ -27,7 +27,7 @@ public class ApologizerAutowiringTest { @Test public void apologizeWithTranslatedMessage() { when(translator.translate("sorry")).thenReturn(TRANSLATED); - assertEquals(TRANSLATED, apologizer.apologize()); + assertEquals(TRANSLATED, apologizeService.apologize()); } } \ No newline at end of file diff --git a/spring-core/src/test/java/com/baeldung/lombok/ApologizerTest.java b/spring-core/src/test/java/com/baeldung/lombok/ApologizeServiceTest.java similarity index 72% rename from spring-core/src/test/java/com/baeldung/lombok/ApologizerTest.java rename to spring-core/src/test/java/com/baeldung/lombok/ApologizeServiceTest.java index 28bd08c89f..ab545e7adf 100644 --- a/spring-core/src/test/java/com/baeldung/lombok/ApologizerTest.java +++ b/spring-core/src/test/java/com/baeldung/lombok/ApologizeServiceTest.java @@ -6,7 +6,7 @@ import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -public class ApologizerTest { +public class ApologizeServiceTest { private final static String MESSAGE = "MESSAGE"; private final static String TRANSLATED = "TRANSLATED"; @@ -14,8 +14,8 @@ public class ApologizerTest { @Test public void apologizeWithCustomTranslatedMessage() { Translator translator = mock(Translator.class); - Apologizer apologizer = new Apologizer(translator, MESSAGE); + ApologizeService apologizeService = new ApologizeService(translator, MESSAGE); when(translator.translate(MESSAGE)).thenReturn(TRANSLATED); - assertEquals(TRANSLATED, apologizer.apologize()); + assertEquals(TRANSLATED, apologizeService.apologize()); } } diff --git a/spring-core/src/test/java/com/baeldung/lombok/FarewellAutowiringTest.java b/spring-core/src/test/java/com/baeldung/lombok/FarewellAutowiringTest.java index d55d44fb3e..592e309236 100644 --- a/spring-core/src/test/java/com/baeldung/lombok/FarewellAutowiringTest.java +++ b/spring-core/src/test/java/com/baeldung/lombok/FarewellAutowiringTest.java @@ -17,7 +17,7 @@ import static org.mockito.Mockito.when; public class FarewellAutowiringTest { @Autowired - private Fareweller fareweller; + private FarewellService farewellService; @Autowired private Translator translator; @@ -26,6 +26,6 @@ public class FarewellAutowiringTest { public void sayByeWithTranslatedMessage() { String translated = "translated"; when(translator.translate("bye")).thenReturn(translated); - assertEquals(translated, fareweller.farewell()); + assertEquals(translated, farewellService.farewell()); } } diff --git a/spring-core/src/test/java/com/baeldung/lombok/FarewellerTest.java b/spring-core/src/test/java/com/baeldung/lombok/FarewellServiceTest.java similarity index 70% rename from spring-core/src/test/java/com/baeldung/lombok/FarewellerTest.java rename to spring-core/src/test/java/com/baeldung/lombok/FarewellServiceTest.java index a02ad1d8ac..9ad593a489 100644 --- a/spring-core/src/test/java/com/baeldung/lombok/FarewellerTest.java +++ b/spring-core/src/test/java/com/baeldung/lombok/FarewellServiceTest.java @@ -6,7 +6,7 @@ import static org.junit.Assert.*; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -public class FarewellerTest { +public class FarewellServiceTest { private final static String TRANSLATED = "TRANSLATED"; @@ -14,7 +14,7 @@ public class FarewellerTest { public void sayByeWithTranslatedMessage() { Translator translator = mock(Translator.class); when(translator.translate("bye")).thenReturn(TRANSLATED); - Fareweller fareweller = new Fareweller(translator); - assertEquals(TRANSLATED, fareweller.farewell()); + FarewellService farewellService = new FarewellService(translator); + assertEquals(TRANSLATED, farewellService.farewell()); } } \ No newline at end of file diff --git a/spring-core/src/test/java/com/baeldung/lombok/GreeterTest.java b/spring-core/src/test/java/com/baeldung/lombok/GreetingServiceTest.java similarity index 79% rename from spring-core/src/test/java/com/baeldung/lombok/GreeterTest.java rename to spring-core/src/test/java/com/baeldung/lombok/GreetingServiceTest.java index 0f66eaf301..d0207d681b 100644 --- a/spring-core/src/test/java/com/baeldung/lombok/GreeterTest.java +++ b/spring-core/src/test/java/com/baeldung/lombok/GreetingServiceTest.java @@ -14,10 +14,10 @@ import static org.mockito.Mockito.when; @ContextConfiguration( loader = AnnotationConfigContextLoader.class, classes = TestConfig.class) -public class GreeterTest { +public class GreetingServiceTest { @Autowired - private Greeter greeter; + private GreetingService greetingService; @Autowired private Translator translator; @@ -26,12 +26,12 @@ public class GreeterTest { public void greetWithTranslatedMessage() { String translated = "translated"; when(translator.translate("hello")).thenReturn(translated); - assertEquals(translated, greeter.greet()); + assertEquals(translated, greetingService.greet()); } @Test(expected = NullPointerException.class) public void throwWhenInstantiated() { - Greeter greeter = new Greeter(); - greeter.greet(); + GreetingService greetingService = new GreetingService(); + greetingService.greet(); } } \ No newline at end of file diff --git a/spring-core/src/test/java/com/baeldung/lombok/ThankerAutowiringTest.java b/spring-core/src/test/java/com/baeldung/lombok/ThankingServiceAutowiringTest.java similarity index 84% rename from spring-core/src/test/java/com/baeldung/lombok/ThankerAutowiringTest.java rename to spring-core/src/test/java/com/baeldung/lombok/ThankingServiceAutowiringTest.java index 59aded5831..b2a338b18f 100644 --- a/spring-core/src/test/java/com/baeldung/lombok/ThankerAutowiringTest.java +++ b/spring-core/src/test/java/com/baeldung/lombok/ThankingServiceAutowiringTest.java @@ -14,10 +14,10 @@ import static org.mockito.Mockito.when; @ContextConfiguration( loader = AnnotationConfigContextLoader.class, classes = TestConfig.class) -public class ThankerAutowiringTest { +public class ThankingServiceAutowiringTest { @Autowired - private Thanker thanker; + private ThankingService thankingService; @Autowired private Translator translator; @@ -26,6 +26,6 @@ public class ThankerAutowiringTest { public void thankWithTranslatedMessage() { String translated = "translated"; when(translator.translate("thank you")).thenReturn(translated); - assertEquals(translated, thanker.thank()); + assertEquals(translated, thankingService.thank()); } } \ No newline at end of file diff --git a/spring-core/src/test/java/com/baeldung/lombok/ThankerTest.java b/spring-core/src/test/java/com/baeldung/lombok/ThankingServiceTest.java similarity index 71% rename from spring-core/src/test/java/com/baeldung/lombok/ThankerTest.java rename to spring-core/src/test/java/com/baeldung/lombok/ThankingServiceTest.java index 466762fa50..7dc663622b 100644 --- a/spring-core/src/test/java/com/baeldung/lombok/ThankerTest.java +++ b/spring-core/src/test/java/com/baeldung/lombok/ThankingServiceTest.java @@ -6,7 +6,7 @@ import static org.junit.Assert.*; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -public class ThankerTest { +public class ThankingServiceTest { private final static String TRANSLATED = "TRANSLATED"; @@ -14,7 +14,7 @@ public class ThankerTest { public void thankWithTranslatedMessage() { Translator translator = mock(Translator.class); when(translator.translate("thank you")).thenReturn(TRANSLATED); - Thanker thanker = new Thanker(translator); - assertEquals(TRANSLATED, thanker.thank()); + ThankingService thankingService = new ThankingService(translator); + assertEquals(TRANSLATED, thankingService.thank()); } } \ No newline at end of file diff --git a/spring-cucumber/pom.xml b/spring-cucumber/pom.xml index 644ddff1d8..55c0af670a 100644 --- a/spring-cucumber/pom.xml +++ b/spring-cucumber/pom.xml @@ -14,7 +14,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-data-dynamodb/pom.xml b/spring-data-dynamodb/pom.xml index 0ce9b3a399..8b06c0b36f 100644 --- a/spring-data-dynamodb/pom.xml +++ b/spring-data-dynamodb/pom.xml @@ -11,7 +11,7 @@ spring-boot-starter-parent org.springframework.boot - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-data-dynamodb/src/test/java/com/baeldung/spring/data/dynamodb/repository/ProductInfoRepositoryIntegrationTest.java b/spring-data-dynamodb/src/test/java/com/baeldung/spring/data/dynamodb/repository/ProductInfoRepositoryIntegrationTest.java index 8fe3e96940..05badc74b4 100644 --- a/spring-data-dynamodb/src/test/java/com/baeldung/spring/data/dynamodb/repository/ProductInfoRepositoryIntegrationTest.java +++ b/spring-data-dynamodb/src/test/java/com/baeldung/spring/data/dynamodb/repository/ProductInfoRepositoryIntegrationTest.java @@ -44,8 +44,8 @@ public class ProductInfoRepositoryIntegrationTest { private static final String EXPECTED_PRICE = "50"; @Before - @Ignore //TODO Remove Ignore annotations when running locally with Local DynamoDB instance - public void setup() throws Exception { + @Ignore // TODO Remove Ignore annotations when running locally with Local DynamoDB instance + public void setup() throws Exception { try { dynamoDBMapper = new DynamoDBMapper(amazonDynamoDB); @@ -64,7 +64,7 @@ public class ProductInfoRepositoryIntegrationTest { } @Test - @Ignore //TODO Remove Ignore annotations when running locally with Local DynamoDB instance + @Ignore // TODO Remove Ignore annotations when running locally with Local DynamoDB instance public void givenItemWithExpectedCost_whenRunFindAll_thenItemIsFound() { ProductInfo productInfo = new ProductInfo(EXPECTED_COST, EXPECTED_PRICE); diff --git a/spring-data-mongodb/README.md b/spring-data-mongodb/README.md index d656bc897c..c2a1f703b5 100644 --- a/spring-data-mongodb/README.md +++ b/spring-data-mongodb/README.md @@ -9,3 +9,4 @@ - [Custom Cascading in Spring Data MongoDB](http://www.baeldung.com/cascading-with-dbref-and-lifecycle-events-in-spring-data-mongodb) - [GridFS in Spring Data MongoDB](http://www.baeldung.com/spring-data-mongodb-gridfs) - [Introduction to Spring Data MongoDB](http://www.baeldung.com/spring-data-mongodb-tutorial) +- [Spring Data MongoDB: Projections and Aggregations](http://www.baeldung.com/spring-data-mongodb-projections-aggregations) diff --git a/spring-data-mongodb/src/main/java/org/baeldung/config/SimpleMongoConfig.java b/spring-data-mongodb/src/main/java/org/baeldung/config/SimpleMongoConfig.java new file mode 100644 index 0000000000..6140382f82 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/baeldung/config/SimpleMongoConfig.java @@ -0,0 +1,25 @@ +package org.baeldung.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; + +import com.mongodb.Mongo; +import com.mongodb.MongoClient; + +@Configuration +@EnableMongoRepositories(basePackages = "org.baeldung.repository") +public class SimpleMongoConfig { + + @Bean + public Mongo mongo() throws Exception { + return new MongoClient("localhost"); + } + + @Bean + public MongoTemplate mongoTemplate() throws Exception { + return new MongoTemplate(mongo(), "test"); + } + +} diff --git a/spring-data-mongodb/src/test/java/org/baeldung/mongotemplate/MongoTemplateProjectionLiveTest.java b/spring-data-mongodb/src/test/java/org/baeldung/mongotemplate/MongoTemplateProjectionLiveTest.java index 04e474f71b..61115faede 100644 --- a/spring-data-mongodb/src/test/java/org/baeldung/mongotemplate/MongoTemplateProjectionLiveTest.java +++ b/spring-data-mongodb/src/test/java/org/baeldung/mongotemplate/MongoTemplateProjectionLiveTest.java @@ -1,8 +1,10 @@ package org.baeldung.mongotemplate; -import static org.junit.Assert.*; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; -import org.baeldung.config.MongoConfig; +import org.baeldung.config.SimpleMongoConfig; import org.baeldung.model.User; import org.junit.After; import org.junit.Before; @@ -15,7 +17,7 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = MongoConfig.class) +@ContextConfiguration(classes = SimpleMongoConfig.class) public class MongoTemplateProjectionLiveTest { @Autowired @@ -38,7 +40,7 @@ public class MongoTemplateProjectionLiveTest { mongoTemplate.insert(new User("John", 30)); mongoTemplate.insert(new User("Ringo", 35)); - Query query = new Query(); + final Query query = new Query(); query.fields() .include("name"); @@ -55,7 +57,7 @@ public class MongoTemplateProjectionLiveTest { mongoTemplate.insert(new User("John", 30)); mongoTemplate.insert(new User("Ringo", 35)); - Query query = new Query(); + final Query query = new Query(); query.fields() .exclude("_id"); @@ -64,7 +66,7 @@ public class MongoTemplateProjectionLiveTest { assertNull(user.getId()); assertNotNull(user.getAge()); }); - + } } diff --git a/spring-data-neo4j/README.md b/spring-data-neo4j/README.md index 0f13d9dbc9..03c9ed333d 100644 --- a/spring-data-neo4j/README.md +++ b/spring-data-neo4j/README.md @@ -2,6 +2,7 @@ ### Relevant Articles: - [Introduction to Spring Data Neo4j](http://www.baeldung.com/spring-data-neo4j-intro) +- [A Guide to Neo4J with Java](http://www.baeldung.com/java-neo4j) ### Build the Project with Tests Running ``` diff --git a/spring-data-neo4j/pom.xml b/spring-data-neo4j/pom.xml index ce10313b2e..96606d597b 100644 --- a/spring-data-neo4j/pom.xml +++ b/spring-data-neo4j/pom.xml @@ -7,10 +7,41 @@ 1.0 + + org.neo4j + neo4j + 3.1.0 + + + + org.neo4j + neo4j-ogm-core + 2.1.1 + + + + org.neo4j + neo4j-ogm-embedded-driver + 2.1.1 + + + + org.neo4j.driver + neo4j-java-driver + 1.1.1 + + + + org.springframework.data + spring-data-neo4j + 4.2.0.RELEASE + + org.springframework.data spring-data-neo4j ${spring-data-neo4j.version} + test-jar @@ -27,13 +58,6 @@ test - - org.springframework.data - spring-data-neo4j - ${spring-data-neo4j.version} - test-jar - - org.neo4j neo4j-kernel @@ -72,9 +96,9 @@ spring-test ${spring-test.version} - + @@ -130,16 +154,18 @@ + 1.8 + 1.8 1.8 UTF-8 UTF-8 - 3.0.7 + 3.1.0 4.1.6.RELEASE 1.1 1.4.3.RELEASE 4.3.5.RELEASE - 2.0.6 + 2.1.1 4.12 diff --git a/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/config/MovieDatabaseNeo4jConfiguration.java b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/config/MovieDatabaseNeo4jConfiguration.java index fb4fda1497..344282d665 100644 --- a/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/config/MovieDatabaseNeo4jConfiguration.java +++ b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/config/MovieDatabaseNeo4jConfiguration.java @@ -4,15 +4,12 @@ import org.neo4j.ogm.session.SessionFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; -import org.springframework.data.neo4j.config.Neo4jConfiguration; import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories; -import org.springframework.scheduling.annotation.EnableScheduling; -import org.springframework.transaction.annotation.EnableTransactionManagement; @ComponentScan(basePackages = { "com.baeldung.spring.data.neo4j.services" }) @Configuration @EnableNeo4jRepositories(basePackages = "com.baeldung.spring.data.neo4j.repostory") -public class MovieDatabaseNeo4jConfiguration extends Neo4jConfiguration { +public class MovieDatabaseNeo4jConfiguration { public static final String URL = System.getenv("NEO4J_URL") != null ? System.getenv("NEO4J_URL") : "http://neo4j:movies@localhost:7474"; @@ -23,7 +20,7 @@ public class MovieDatabaseNeo4jConfiguration extends Neo4jConfiguration { return config; } - @Override + @Bean public SessionFactory getSessionFactory() { return new SessionFactory(getConfiguration(), "com.baeldung.spring.data.neo4j.domain"); } diff --git a/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/config/MovieDatabaseNeo4jTestConfiguration.java b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/config/MovieDatabaseNeo4jTestConfiguration.java index 81935b2293..7bb1b78a09 100644 --- a/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/config/MovieDatabaseNeo4jTestConfiguration.java +++ b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/config/MovieDatabaseNeo4jTestConfiguration.java @@ -5,9 +5,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; -import org.springframework.data.neo4j.config.Neo4jConfiguration; import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories; -import org.springframework.data.neo4j.server.Neo4jServer; import org.springframework.transaction.annotation.EnableTransactionManagement; @EnableTransactionManagement @@ -15,7 +13,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement; @Configuration @EnableNeo4jRepositories(basePackages = "com.baeldung.spring.data.neo4j.repostory") @Profile({ "embedded", "test" }) -public class MovieDatabaseNeo4jTestConfiguration extends Neo4jConfiguration { +public class MovieDatabaseNeo4jTestConfiguration { @Bean public org.neo4j.ogm.config.Configuration getConfiguration() { @@ -24,7 +22,7 @@ public class MovieDatabaseNeo4jTestConfiguration extends Neo4jConfiguration { return config; } - @Override + @Bean public SessionFactory getSessionFactory() { return new SessionFactory(getConfiguration(), "com.baeldung.spring.data.neo4j.domain"); } diff --git a/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Car.java b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Car.java new file mode 100644 index 0000000000..f2325a334f --- /dev/null +++ b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Car.java @@ -0,0 +1,47 @@ +package com.baeldung.spring.data.neo4j.domain; + +import org.neo4j.ogm.annotation.GraphId; +import org.neo4j.ogm.annotation.NodeEntity; +import org.neo4j.ogm.annotation.Relationship; + +@NodeEntity +public class Car { + @GraphId + private Long id; + + private String make; + + @Relationship(direction = "INCOMING") + private Company company; + + public Car(String make, String model) { + this.make = make; + this.model = model; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getMake() { + return make; + } + + public void setMake(String make) { + this.make = make; + } + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + + private String model; +} diff --git a/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Company.java b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Company.java new file mode 100644 index 0000000000..4422ade44f --- /dev/null +++ b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Company.java @@ -0,0 +1,42 @@ +package com.baeldung.spring.data.neo4j.domain; + +import org.neo4j.ogm.annotation.NodeEntity; +import org.neo4j.ogm.annotation.Relationship; + +@NodeEntity +public class Company { + private Long id; + + private String name; + + @Relationship(type="owns") + private Car car; + + public Company(String name) { + this.name = name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Car getCar() { + return car; + } + + public void setCar(Car car) { + this.car = car; + } +} diff --git a/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/repostory/MovieRepository.java b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/repostory/MovieRepository.java index 1bd605a7bc..afb82551e7 100644 --- a/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/repostory/MovieRepository.java +++ b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/repostory/MovieRepository.java @@ -12,6 +12,7 @@ import java.util.Map; @Repository public interface MovieRepository extends GraphRepository { + Movie findByTitle(@Param("title") String title); @Query("MATCH (m:Movie) WHERE m.title =~ ('(?i).*'+{title}+'.*') RETURN m") diff --git a/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/repostory/PersonRepository.java b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/repostory/PersonRepository.java index f7f694c07f..4ac40ef75b 100644 --- a/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/repostory/PersonRepository.java +++ b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/repostory/PersonRepository.java @@ -6,5 +6,4 @@ import org.springframework.stereotype.Repository; @Repository public interface PersonRepository extends GraphRepository { - } diff --git a/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/services/MovieService.java b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/services/MovieService.java index d760d19066..ae1f6eb8e5 100644 --- a/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/services/MovieService.java +++ b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/services/MovieService.java @@ -12,11 +12,11 @@ import java.util.*; public class MovieService { @Autowired - MovieRepository movieRepository; + private MovieRepository movieRepository; private Map toD3Format(Iterator> result) { - List> nodes = new ArrayList>(); - List> rels = new ArrayList>(); + List> nodes = new ArrayList<>(); + List> rels = new ArrayList<>(); int i = 0; while (result.hasNext()) { Map row = result.next(); @@ -37,7 +37,7 @@ public class MovieService { } private Map map(String key1, Object value1, String key2, Object value2) { - Map result = new HashMap(2); + Map result = new HashMap<>(2); result.put(key1, value1); result.put(key2, value2); return result; diff --git a/spring-data-neo4j/src/test/java/com/baeldung/neo4j/Neo4JServerTest.java b/spring-data-neo4j/src/test/java/com/baeldung/neo4j/Neo4JServerTest.java new file mode 100644 index 0000000000..e959e0237d --- /dev/null +++ b/spring-data-neo4j/src/test/java/com/baeldung/neo4j/Neo4JServerTest.java @@ -0,0 +1,60 @@ +package com.baeldung.neo4j; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.Statement; + +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; +import org.neo4j.driver.v1.AuthTokens; +import org.neo4j.driver.v1.Driver; +import org.neo4j.driver.v1.GraphDatabase; +import org.neo4j.driver.v1.Session; +import org.neo4j.driver.v1.StatementResult; + +@Ignore +public class Neo4JServerTest { + + @Test + public void standAloneDriver() { + Driver driver = GraphDatabase.driver("bolt://localhost:7687", AuthTokens.basic("neo4j", "12345")); + Session session = driver.session(); + + session.run("CREATE (baeldung:Company {name:\"Baeldung\"}) " + + "-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" + + "RETURN baeldung, tesla"); + + StatementResult result = session.run("MATCH (company:Company)-[:owns]-> (car:Car)" + + "WHERE car.make='tesla' and car.model='modelX'" + + "RETURN company.name"); + + Assert.assertTrue(result.hasNext()); + Assert.assertEquals(result.next().get("company.name").asString(), "Baeldung"); + + session.close(); + driver.close(); + } + + @Test + public void standAloneJdbc() throws Exception { + Connection con = DriverManager.getConnection("jdbc:neo4j:bolt://localhost/?user=neo4j,password=12345,scheme=basic"); + + // Querying + try (Statement stmt = con.createStatement()) { + stmt.execute("CREATE (baeldung:Company {name:\"Baeldung\"}) " + + "-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" + + "RETURN baeldung, tesla"); + + ResultSet rs = stmt.executeQuery("MATCH (company:Company)-[:owns]-> (car:Car)" + + "WHERE car.make='tesla' and car.model='modelX'" + + "RETURN company.name"); + + while (rs.next()) { + Assert.assertEquals(rs.getString("company.name"), "Baeldung"); + } + } + con.close(); + } +} diff --git a/spring-data-neo4j/src/test/java/com/baeldung/neo4j/Neo4jLiveTest.java b/spring-data-neo4j/src/test/java/com/baeldung/neo4j/Neo4jLiveTest.java new file mode 100644 index 0000000000..1ff01b93a1 --- /dev/null +++ b/spring-data-neo4j/src/test/java/com/baeldung/neo4j/Neo4jLiveTest.java @@ -0,0 +1,167 @@ +package com.baeldung.neo4j; + + +import java.io.File; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.neo4j.graphdb.GraphDatabaseService; +import org.neo4j.graphdb.Label; +import org.neo4j.graphdb.Node; +import org.neo4j.graphdb.NotFoundException; +import org.neo4j.graphdb.RelationshipType; +import org.neo4j.graphdb.Result; +import org.neo4j.graphdb.factory.GraphDatabaseFactory; + +public class Neo4jLiveTest { + + private static GraphDatabaseService graphDb; + + @Before + public void setUp() { + GraphDatabaseFactory graphDbFactory = new GraphDatabaseFactory(); + graphDb = graphDbFactory.newEmbeddedDatabase(new File("data/cars")); + } + + @After + public void tearDown() { + graphDb.shutdown(); + } + + @Test + public void testPersonCar() { + graphDb.beginTx(); + Node car = graphDb.createNode(Label.label("Car")); + car.setProperty("make", "tesla"); + car.setProperty("model", "model3"); + + Node owner = graphDb.createNode(Label.label("Person")); + owner.setProperty("firstName", "baeldung"); + owner.setProperty("lastName", "baeldung"); + + owner.createRelationshipTo(car, RelationshipType.withName("owner")); + + Result result = graphDb.execute("MATCH (c:Car) <-[owner]- (p:Person) " + + "WHERE c.make = 'tesla'" + + "RETURN p.firstName, p.lastName"); + + Map firstResult = result.next(); + Assert.assertEquals("baeldung", firstResult.get("p.firstName")); + } + + @Test + public void testCreateNode() { + + graphDb.beginTx(); + + Result result = graphDb.execute("CREATE (baeldung:Company {name:\"Baeldung\"})" + + "RETURN baeldung"); + + Map firstResult = result.next(); + Node firstNode = (Node) firstResult.get("baeldung"); + Assert.assertEquals(firstNode.getProperty("name"), "Baeldung"); + } + + @Test + public void testCreateNodeAndLink() { + graphDb.beginTx(); + + Result result = graphDb.execute("CREATE (baeldung:Company {name:\"Baeldung\"}) " + + "-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" + + "RETURN baeldung, tesla"); + + Map firstResult = result.next(); + Assert.assertTrue(firstResult.containsKey("baeldung")); + Assert.assertTrue(firstResult.containsKey("tesla")); + } + + @Test + public void testFindAndReturn() { + graphDb.beginTx(); + + graphDb.execute("CREATE (baeldung:Company {name:\"Baeldung\"}) " + + "-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" + + "RETURN baeldung, tesla"); + + Result result = graphDb.execute("MATCH (company:Company)-[:owns]-> (car:Car)" + + "WHERE car.make='tesla' and car.model='modelX'" + + "RETURN company.name"); + + Map firstResult = result.next(); + Assert.assertEquals(firstResult.get("company.name"), "Baeldung"); + } + + @Test + public void testUpdate() { + graphDb.beginTx(); + + graphDb.execute("CREATE (baeldung:Company {name:\"Baeldung\"}) " + + "-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" + + "RETURN baeldung, tesla"); + + Result result = graphDb.execute("MATCH (car:Car)" + + "WHERE car.make='tesla'" + + " SET car.milage=120" + + " SET car :Car:Electro" + + " SET car.model=NULL" + + " RETURN car"); + + Map firstResult = result.next(); + Node car = (Node) firstResult.get("car"); + + Assert.assertEquals(car.getProperty("milage"), 120L); + Assert.assertEquals(car.getLabels(), Arrays.asList(Label.label("Car"), Label.label("Electro"))); + + try { + car.getProperty("model"); + Assert.fail(); + } catch (NotFoundException e) { + // expected + } + } + + @Test + public void testDelete() { + graphDb.beginTx(); + + graphDb.execute("CREATE (baeldung:Company {name:\"Baeldung\"}) " + + "-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" + + "RETURN baeldung, tesla"); + + graphDb.execute("MATCH (company:Company)" + + " WHERE company.name='Baeldung'" + + " DELETE company"); + + Result result = graphDb.execute("MATCH (company:Company)" + + " WHERE company.name='Baeldung'" + + " RETURN company"); + + Assert.assertFalse(result.hasNext()); + } + + @Test + public void testBindings() { + graphDb.beginTx(); + + Map params = new HashMap<>(); + params.put("name", "baeldung"); + params.put("make", "tesla"); + params.put("model", "modelS"); + + Result result = graphDb.execute("CREATE (baeldung:Company {name:$name}) " + + "-[:owns]-> (tesla:Car {make: $make, model: $model})" + + "RETURN baeldung, tesla", params); + + Map firstResult = result.next(); + Assert.assertTrue(firstResult.containsKey("baeldung")); + Assert.assertTrue(firstResult.containsKey("tesla")); + + Node car = (Node) firstResult.get("tesla"); + Assert.assertEquals(car.getProperty("model"), "modelS"); + } +} diff --git a/spring-data-neo4j/src/test/java/com/baeldung/neo4j/Neo4jOgmLiveTest.java b/spring-data-neo4j/src/test/java/com/baeldung/neo4j/Neo4jOgmLiveTest.java new file mode 100644 index 0000000000..06b31667dd --- /dev/null +++ b/spring-data-neo4j/src/test/java/com/baeldung/neo4j/Neo4jOgmLiveTest.java @@ -0,0 +1,49 @@ +package com.baeldung.neo4j; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; +import org.neo4j.ogm.config.Configuration; +import org.neo4j.ogm.model.Result; +import org.neo4j.ogm.session.Session; +import org.neo4j.ogm.session.SessionFactory; + +import com.baeldung.spring.data.neo4j.domain.Car; +import com.baeldung.spring.data.neo4j.domain.Company; +import org.neo4j.ogm.transaction.Transaction; + +public class Neo4jOgmLiveTest { + + @Test + public void testOgm() { + Configuration conf = new Configuration(); + conf.driverConfiguration().setDriverClassName("org.neo4j.ogm.drivers.embedded.driver.EmbeddedDriver"); + + SessionFactory factory = new SessionFactory(conf, "com.baeldung.spring.data.neo4j.domain"); + Session session = factory.openSession(); + + Car tesla = new Car("tesla", "modelS"); + Company baeldung = new Company("baeldung"); + + baeldung.setCar(tesla); + + session.save(baeldung); + + Assert.assertEquals(1, session.countEntitiesOfType(Company.class)); + + Map params = new HashMap<>(); + params.put("make", "tesla"); + Result result = session.query("MATCH (car:Car) <-[:owns]- (company:Company)" + + " WHERE car.make=$make" + + " RETURN company", params); + + Map firstResult = result.iterator().next(); + + Assert.assertEquals(firstResult.size(), 1); + + Company actual = (Company) firstResult.get("company"); + Assert.assertEquals(actual.getName(), baeldung.getName()); + } +} diff --git a/spring-data-neo4j/src/test/resources/logback.xml b/spring-data-neo4j/src/test/resources/logback.xml new file mode 100644 index 0000000000..39a6538324 --- /dev/null +++ b/spring-data-neo4j/src/test/resources/logback.xml @@ -0,0 +1,16 @@ + + + + + + %d %5p %40.40c:%4L - %m%n + + + + + + + + + + diff --git a/spring-data-rest/pom.xml b/spring-data-rest/pom.xml index da5d844211..4e8001ae7b 100644 --- a/spring-data-rest/pom.xml +++ b/spring-data-rest/pom.xml @@ -14,7 +14,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-data-rest/src/main/java/com/baeldung/config/ValidatorEventRegister.java b/spring-data-rest/src/main/java/com/baeldung/config/ValidatorEventRegister.java index 89ab848e81..8f14d6c1c6 100644 --- a/spring-data-rest/src/main/java/com/baeldung/config/ValidatorEventRegister.java +++ b/spring-data-rest/src/main/java/com/baeldung/config/ValidatorEventRegister.java @@ -22,9 +22,15 @@ public class ValidatorEventRegister implements InitializingBean { @Override public void afterPropertiesSet() throws Exception { List events = Arrays.asList("beforeCreate", "afterCreate", "beforeSave", "afterSave", "beforeLinkSave", "afterLinkSave", "beforeDelete", "afterDelete"); - + for (Map.Entry entry : validators.entrySet()) { - events.stream().filter(p -> entry.getKey().startsWith(p)).findFirst().ifPresent(p -> validatingRepositoryEventListener.addValidator(p, entry.getValue())); + events + .stream() + .filter(p -> entry + .getKey() + .startsWith(p)) + .findFirst() + .ifPresent(p -> validatingRepositoryEventListener.addValidator(p, entry.getValue())); } } } diff --git a/spring-data-rest/src/main/java/com/baeldung/exception/handlers/RestResponseEntityExceptionHandler.java b/spring-data-rest/src/main/java/com/baeldung/exception/handlers/RestResponseEntityExceptionHandler.java index ee84738e7a..aa24fccac7 100644 --- a/spring-data-rest/src/main/java/com/baeldung/exception/handlers/RestResponseEntityExceptionHandler.java +++ b/spring-data-rest/src/main/java/com/baeldung/exception/handlers/RestResponseEntityExceptionHandler.java @@ -1,16 +1,17 @@ package com.baeldung.exception.handlers; -import java.util.stream.Collectors; - import org.springframework.data.rest.core.RepositoryConstraintViolationException; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.validation.ObjectError; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.context.request.WebRequest; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; +import java.util.stream.Collectors; + @ControllerAdvice public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler { @@ -18,8 +19,13 @@ public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionH public ResponseEntity handleAccessDeniedException(Exception ex, WebRequest request) { RepositoryConstraintViolationException nevEx = (RepositoryConstraintViolationException) ex; - String errors = nevEx.getErrors().getAllErrors().stream().map(p -> p.toString()).collect(Collectors.joining("\n")); - return new ResponseEntity(errors, new HttpHeaders(), HttpStatus.NOT_ACCEPTABLE); + String errors = nevEx + .getErrors() + .getAllErrors() + .stream() + .map(ObjectError::toString) + .collect(Collectors.joining("\n")); + return new ResponseEntity<>(errors, new HttpHeaders(), HttpStatus.NOT_ACCEPTABLE); } } \ No newline at end of file diff --git a/spring-data-rest/src/main/test/com/baeldung/validator/SpringDataRestValidatorTest.java b/spring-data-rest/src/test/java/com/baeldung/validator/SpringDataRestValidatorTest.java similarity index 75% rename from spring-data-rest/src/main/test/com/baeldung/validator/SpringDataRestValidatorTest.java rename to spring-data-rest/src/test/java/com/baeldung/validator/SpringDataRestValidatorTest.java index b185c6d5ab..300fc081d3 100644 --- a/spring-data-rest/src/main/test/com/baeldung/validator/SpringDataRestValidatorTest.java +++ b/spring-data-rest/src/test/java/com/baeldung/validator/SpringDataRestValidatorTest.java @@ -1,100 +1,86 @@ -package com.baeldung.validator; - -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.SpringApplicationConfiguration; -import org.springframework.http.MediaType; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.web.WebAppConfiguration; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.ResultActions; -import org.springframework.test.web.servlet.ResultMatcher; -import org.springframework.web.context.WebApplicationContext; - -import com.baeldung.SpringDataRestApplication; -import com.baeldung.models.WebsiteUser; -import com.fasterxml.jackson.databind.ObjectMapper; - -@RunWith(SpringJUnit4ClassRunner.class) -@SpringApplicationConfiguration(classes = SpringDataRestApplication.class) -@WebAppConfiguration -public class SpringDataRestValidatorTest { - public static final String URL = "http://localhost"; - - private MockMvc mockMvc; - - @Autowired - protected WebApplicationContext wac; - - @Before - public void setup() { - mockMvc = webAppContextSetup(wac).build(); - } - - @Test - public void whenStartingApplication_thenCorrectStatusCode() throws Exception { - mockMvc.perform(get("/users")).andExpect(status().is2xxSuccessful()); - }; - - @Test - public void whenAddingNewCorrectUser_thenCorrectStatusCodeAndResponse() throws Exception { - WebsiteUser user = new WebsiteUser(); - user.setEmail("john.doe@john.com"); - user.setName("John Doe"); - - mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))) - .andExpect(status().is2xxSuccessful()) - .andExpect(redirectedUrl("http://localhost/users/1")); - } - - @Test - public void whenAddingNewUserWithoutName_thenErrorStatusCodeAndResponse() throws Exception { - WebsiteUser user = new WebsiteUser(); - user.setEmail("john.doe@john.com"); - - mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))) - .andExpect(status().isNotAcceptable()) - .andExpect(redirectedUrl(null)); - } - - @Test - public void whenAddingNewUserWithEmptyName_thenErrorStatusCodeAndResponse() throws Exception { - WebsiteUser user = new WebsiteUser(); - user.setEmail("john.doe@john.com"); - user.setName(""); - mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))) - .andExpect(status().isNotAcceptable()) - .andExpect(redirectedUrl(null)); - } - - @Test - public void whenAddingNewUserWithoutEmail_thenErrorStatusCodeAndResponse() throws Exception { - WebsiteUser user = new WebsiteUser(); - user.setName("John Doe"); - - mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))) - .andExpect(status().isNotAcceptable()) - .andExpect(redirectedUrl(null)); - } - - @Test - public void whenAddingNewUserWithEmptyEmail_thenErrorStatusCodeAndResponse() throws Exception { - WebsiteUser user = new WebsiteUser(); - user.setName("John Doe"); - user.setEmail(""); - mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))) - .andExpect(status().isNotAcceptable()) - .andExpect(redirectedUrl(null)); - } - -} +package com.baeldung.validator; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.web.context.WebApplicationContext; + +import com.baeldung.SpringDataRestApplication; +import com.baeldung.models.WebsiteUser; +import com.fasterxml.jackson.databind.ObjectMapper; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = SpringDataRestApplication.class) +@WebAppConfiguration +public class SpringDataRestValidatorTest { + public static final String URL = "http://localhost"; + + private MockMvc mockMvc; + + @Autowired + protected WebApplicationContext wac; + + @Before + public void setup() { + mockMvc = webAppContextSetup(wac).build(); + } + + @Test + public void whenStartingApplication_thenCorrectStatusCode() throws Exception { + mockMvc.perform(get("/users")).andExpect(status().is2xxSuccessful()); + }; + + @Test + public void whenAddingNewCorrectUser_thenCorrectStatusCodeAndResponse() throws Exception { + WebsiteUser user = new WebsiteUser(); + user.setEmail("john.doe@john.com"); + user.setName("John Doe"); + + mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))).andExpect(status().is2xxSuccessful()).andExpect(redirectedUrl("http://localhost/users/1")); + } + + @Test + public void whenAddingNewUserWithoutName_thenErrorStatusCodeAndResponse() throws Exception { + WebsiteUser user = new WebsiteUser(); + user.setEmail("john.doe@john.com"); + + mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))).andExpect(status().isNotAcceptable()).andExpect(redirectedUrl(null)); + } + + @Test + public void whenAddingNewUserWithEmptyName_thenErrorStatusCodeAndResponse() throws Exception { + WebsiteUser user = new WebsiteUser(); + user.setEmail("john.doe@john.com"); + user.setName(""); + mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))).andExpect(status().isNotAcceptable()).andExpect(redirectedUrl(null)); + } + + @Test + public void whenAddingNewUserWithoutEmail_thenErrorStatusCodeAndResponse() throws Exception { + WebsiteUser user = new WebsiteUser(); + user.setName("John Doe"); + + mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))).andExpect(status().isNotAcceptable()).andExpect(redirectedUrl(null)); + } + + @Test + public void whenAddingNewUserWithEmptyEmail_thenErrorStatusCodeAndResponse() throws Exception { + WebsiteUser user = new WebsiteUser(); + user.setName("John Doe"); + user.setEmail(""); + mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))).andExpect(status().isNotAcceptable()).andExpect(redirectedUrl(null)); + } + +} diff --git a/spring-hibernate4/.gitignore b/spring-hibernate4/.gitignore index 83c05e60c8..d31cc4c619 100644 --- a/spring-hibernate4/.gitignore +++ b/spring-hibernate4/.gitignore @@ -10,4 +10,6 @@ # Packaged files # *.jar *.war -*.ear \ No newline at end of file +*.ear +/target/ +/target/ diff --git a/spring-hibernate4/README.md b/spring-hibernate4/README.md index 7888e8b4ee..02888c4ad0 100644 --- a/spring-hibernate4/README.md +++ b/spring-hibernate4/README.md @@ -12,6 +12,7 @@ - [Hibernate: save, persist, update, merge, saveOrUpdate](http://www.baeldung.com/hibernate-save-persist-update-merge-saveorupdate/) - [Eager/Lazy Loading In Hibernate](http://www.baeldung.com/hibernate-lazy-eager-loading) - [Hibernate Criteria Queries](http://www.baeldung.com/hibernate-criteria-queries) +- [Hibernate One to Many Annotation Tutorial](http://www.baeldung.com/hibernate-one-to-many) ### Quick Start @@ -22,3 +23,4 @@ mvn install mvn cargo:run ``` - **note**: starts on port `8082` + diff --git a/spring-hibernate4/src/main/java/com/baeldung/hibernate/oneToMany/config/HibernateAnnotationUtil.java b/spring-hibernate4/src/main/java/com/baeldung/hibernate/oneToMany/config/HibernateAnnotationUtil.java index ba54985853..e522dab48d 100644 --- a/spring-hibernate4/src/main/java/com/baeldung/hibernate/oneToMany/config/HibernateAnnotationUtil.java +++ b/spring-hibernate4/src/main/java/com/baeldung/hibernate/oneToMany/config/HibernateAnnotationUtil.java @@ -7,32 +7,31 @@ import org.hibernate.service.ServiceRegistry; public class HibernateAnnotationUtil { - private static SessionFactory sessionFactory; - - private static SessionFactory buildSessionFactory() { + private static SessionFactory sessionFactory; + + private static SessionFactory buildSessionFactory() { try { // Create the SessionFactory from hibernate-annotation.cfg.xml - Configuration configuration = new Configuration(); - configuration.configure("hibernate-annotation.cfg.xml"); - System.out.println("Hibernate Annotation Configuration loaded"); - - ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build(); - System.out.println("Hibernate Annotation serviceRegistry created"); - - SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry); - - + Configuration configuration = new Configuration(); + configuration.configure("hibernate-annotation.cfg.xml"); + System.out.println("Hibernate Annotation Configuration loaded"); + + ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build(); + System.out.println("Hibernate Annotation serviceRegistry created"); + + SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry); + return sessionFactory; - } - catch (Throwable ex) { + } catch (Throwable ex) { System.err.println("Initial SessionFactory creation failed." + ex); ex.printStackTrace(); throw new ExceptionInInitializerError(ex); } } - - public static SessionFactory getSessionFactory() { - if(sessionFactory == null) sessionFactory = buildSessionFactory(); + + public static SessionFactory getSessionFactory() { + if (sessionFactory == null) + sessionFactory = buildSessionFactory(); return sessionFactory; } } diff --git a/spring-hibernate4/src/main/java/com/baeldung/hibernate/oneToMany/main/HibernateOneToManyAnnotationMain.java b/spring-hibernate4/src/main/java/com/baeldung/hibernate/oneToMany/main/HibernateOneToManyAnnotationMain.java index d5c41bcfab..2bc5e514f7 100644 --- a/spring-hibernate4/src/main/java/com/baeldung/hibernate/oneToMany/main/HibernateOneToManyAnnotationMain.java +++ b/spring-hibernate4/src/main/java/com/baeldung/hibernate/oneToMany/main/HibernateOneToManyAnnotationMain.java @@ -13,48 +13,48 @@ import com.baeldung.hibernate.oneToMany.model.Items; public class HibernateOneToManyAnnotationMain { - public static void main(String[] args) { + public static void main(String[] args) { - Cart cart = new Cart(); - cart.setName("MyCart"); - - Items item1 = new Items("I10", 10, 1, cart); - Items item2 = new Items("I20", 20, 2, cart); - Set itemsSet = new HashSet(); - itemsSet.add(item1); itemsSet.add(item2); - - cart.setItems(itemsSet); - cart.setTotal(10*1 + 20*2); - - SessionFactory sessionFactory = null; - Session session = null; - Transaction tx = null; - try{ - //Get Session - sessionFactory = HibernateAnnotationUtil.getSessionFactory(); - session = sessionFactory.getCurrentSession(); - System.out.println("Session created"); - //start transaction - tx = session.beginTransaction(); - //Save the Model object - session.save(cart); - session.save(item1); - session.save(item2); - //Commit transaction - tx.commit(); - System.out.println("Cart ID="+cart.getId()); - System.out.println("item1 ID="+item1.getId()+", Foreign Key Cart ID="+item1.getCart().getId()); - System.out.println("item2 ID="+item2.getId()+", Foreign Key Cart ID="+item1.getCart().getId()); - - }catch(Exception e){ - System.out.println("Exception occured. "+e.getMessage()); - e.printStackTrace(); - }finally{ - if(!sessionFactory.isClosed()){ - System.out.println("Closing SessionFactory"); - sessionFactory.close(); - } - } - } + Cart cart = new Cart(); + + Items item1 = new Items(cart); + Items item2 = new Items(cart); + Set itemsSet = new HashSet(); + itemsSet.add(item1); + itemsSet.add(item2); + + cart.setItems(itemsSet); + + + SessionFactory sessionFactory = null; + Session session = null; + Transaction tx = null; + try { + // Get Session + sessionFactory = HibernateAnnotationUtil.getSessionFactory(); + session = sessionFactory.getCurrentSession(); + System.out.println("Session created"); + // start transaction + tx = session.beginTransaction(); + // Save the Model object + session.save(cart); + session.save(item1); + session.save(item2); + // Commit transaction + tx.commit(); + System.out.println("Cart ID=" + cart.getId()); + System.out.println("item1 ID=" + item1.getId() + ", Foreign Key Cart ID=" + item1.getCart().getId()); + System.out.println("item2 ID=" + item2.getId() + ", Foreign Key Cart ID=" + item1.getCart().getId()); + + } catch (Exception e) { + System.out.println("Exception occured. " + e.getMessage()); + e.printStackTrace(); + } finally { + if (!sessionFactory.isClosed()) { + System.out.println("Closing SessionFactory"); + sessionFactory.close(); + } + } + } } diff --git a/spring-hibernate4/src/main/java/com/baeldung/hibernate/oneToMany/model/Cart.java b/spring-hibernate4/src/main/java/com/baeldung/hibernate/oneToMany/model/Cart.java index fdbfda2279..b8b991831e 100644 --- a/spring-hibernate4/src/main/java/com/baeldung/hibernate/oneToMany/model/Cart.java +++ b/spring-hibernate4/src/main/java/com/baeldung/hibernate/oneToMany/model/Cart.java @@ -11,46 +11,33 @@ import javax.persistence.OneToMany; import javax.persistence.Table; @Entity -@Table(name="CART") +@Table(name = "CART") public class Cart { - @Id - @GeneratedValue(strategy=GenerationType.IDENTITY) - @Column(name="cart_id") - private long id; - - @Column(name="total") - private double total; - - @Column(name="name") - private String name; - - @OneToMany(mappedBy="cart") - private Set items; - - public long getId() { - return id; - } - public void setId(long id) { - this.id = id; - } - public double getTotal() { - return total; - } - public void setTotal(double total) { - this.total = total; - } - public String getName() { - return name; - } - public void setName(String name) { - this.name = name; - } - public Set getItems() { - return items; - } - public void setItems(Set items) { - this.items = items; - } - + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "cart_id") + private long id; + + + @OneToMany(mappedBy = "cart") + private Set items; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + + public Set getItems() { + return items; + } + + public void setItems(Set items) { + this.items = items; + } + } diff --git a/spring-hibernate4/src/main/java/com/baeldung/hibernate/oneToMany/model/Items.java b/spring-hibernate4/src/main/java/com/baeldung/hibernate/oneToMany/model/Items.java index 630bf0a12e..f63a4855b5 100644 --- a/spring-hibernate4/src/main/java/com/baeldung/hibernate/oneToMany/model/Items.java +++ b/spring-hibernate4/src/main/java/com/baeldung/hibernate/oneToMany/model/Items.java @@ -10,65 +10,41 @@ import javax.persistence.ManyToOne; import javax.persistence.Table; @Entity -@Table(name="ITEMS") +@Table(name = "ITEMS") public class Items { - @Id - @GeneratedValue(strategy=GenerationType.IDENTITY) - @Column(name="id") - private long id; - - @Column(name="item_id") - private String itemId; - - @Column(name="item_total") - private double itemTotal; - - @Column(name="quantity") - private int quantity; - - @ManyToOne - @JoinColumn(name="cart_id", nullable=false) - private Cart cart; - - //Hibernate requires no-args constructor - public Items(){} - - public Items(String itemId, double total, int qty, Cart c){ - this.itemId=itemId; - this.itemTotal=total; - this.quantity=qty; - this.cart=c; - } - public String getItemId() { - return itemId; - } - public void setItemId(String itemId) { - this.itemId = itemId; - } - public double getItemTotal() { - return itemTotal; - } - public void setItemTotal(double itemTotal) { - this.itemTotal = itemTotal; - } - public int getQuantity() { - return quantity; - } - public void setQuantity(int quantity) { - this.quantity = quantity; - } - public Cart getCart() { - return cart; - } - public void setCart(Cart cart) { - this.cart = cart; - } - public long getId() { - return id; - } - public void setId(long id) { - this.id = id; - } - + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private long id; + + + @ManyToOne + @JoinColumn(name = "cart_id", nullable = false) + private Cart cart; + + // Hibernate requires no-args constructor + public Items() { + } + + public Items(Cart c) { + this.cart = c; + } + + public Cart getCart() { + return cart; + } + + public void setCart(Cart cart) { + this.cart = cart; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + } diff --git a/spring-hibernate4/src/main/resources/one_to_many.sql b/spring-hibernate4/src/main/resources/one_to_many.sql index 7887ff7d9c..2eb48fc262 100644 --- a/spring-hibernate4/src/main/resources/one_to_many.sql +++ b/spring-hibernate4/src/main/resources/one_to_many.sql @@ -1,16 +1,11 @@ CREATE TABLE `Cart` ( `cart_id` int(11) unsigned NOT NULL AUTO_INCREMENT, - `total` decimal(10,0) NOT NULL, - `name` varchar(10) DEFAULT NULL, PRIMARY KEY (`cart_id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; CREATE TABLE `Items` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `cart_id` int(11) unsigned NOT NULL, - `item_id` varchar(10) NOT NULL, - `item_total` decimal(10,0) NOT NULL, - `quantity` int(3) NOT NULL, PRIMARY KEY (`id`), KEY `cart_id` (`cart_id`), CONSTRAINT `items_ibfk_1` FOREIGN KEY (`cart_id`) REFERENCES `Cart` (`cart_id`) diff --git a/spring-hibernate4/src/test/java/com/baeldung/hibernate/oneToMany/main/HibernateOneToManyAnnotationMainTest.java b/spring-hibernate4/src/test/java/com/baeldung/hibernate/oneToMany/main/HibernateOneToManyAnnotationMainTest.java index 742bb2b470..e2d2bf9143 100644 --- a/spring-hibernate4/src/test/java/com/baeldung/hibernate/oneToMany/main/HibernateOneToManyAnnotationMainTest.java +++ b/spring-hibernate4/src/test/java/com/baeldung/hibernate/oneToMany/main/HibernateOneToManyAnnotationMainTest.java @@ -1,102 +1,94 @@ - package com.baeldung.hibernate.oneToMany.main; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; -import com.baeldung.hibernate.oneToMany.model.Cart; -import com.baeldung.hibernate.oneToMany.model.Items; import java.util.HashSet; import java.util.Set; -import static org.hamcrest.Matchers.hasSize; + import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; import org.hibernate.dialect.HSQLDialect; import org.hibernate.service.ServiceRegistry; +import org.junit.After; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -import static org.junit.Assert.*; -import org.junit.runner.RunWith; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import com.baeldung.hibernate.oneToMany.model.Cart; +import com.baeldung.hibernate.oneToMany.model.Items; -//@RunWith(SpringJUnit4ClassRunner.class) public class HibernateOneToManyAnnotationMainTest { - - private static SessionFactory sessionFactory; - private Session session; - - public HibernateOneToManyAnnotationMainTest() { - } - - - @BeforeClass - public static void beforeTests() { - Configuration configuration = new Configuration().addAnnotatedClass(Cart.class).addAnnotatedClass(Items.class).setProperty("hibernate.dialect", HSQLDialect.class.getName()).setProperty("hibernate.connection.driver_class", org.hsqldb.jdbcDriver.class.getName()) - .setProperty("hibernate.connection.url", "jdbc:hsqldb:mem:test").setProperty("hibernate.connection.username", "sa").setProperty("hibernate.connection.password", "").setProperty("hibernate.hbm2ddl.auto", "update"); - ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build(); - sessionFactory = configuration.buildSessionFactory(serviceRegistry); - } - - @Before - public void setUp() { - session = sessionFactory.openSession(); - session.beginTransaction(); - - } - - @Test - public void givenSession_checkIfDatabaseIsEmpty(){ - Cart cart = (Cart) session.get(Cart.class, new Long(1)); - assertNull(cart); - - } - - - - + private static SessionFactory sessionFactory; + + private Session session; + + public HibernateOneToManyAnnotationMainTest() { + } + + @BeforeClass + public static void beforeTests() { + Configuration configuration = new Configuration().addAnnotatedClass(Cart.class).addAnnotatedClass(Items.class) + .setProperty("hibernate.dialect", HSQLDialect.class.getName()) + .setProperty("hibernate.connection.driver_class", org.hsqldb.jdbcDriver.class.getName()) + .setProperty("hibernate.connection.url", "jdbc:hsqldb:mem:test") + .setProperty("hibernate.connection.username", "sa").setProperty("hibernate.connection.password", "") + .setProperty("hibernate.hbm2ddl.auto", "update"); + ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder() + .applySettings(configuration.getProperties()).build(); + sessionFactory = configuration.buildSessionFactory(serviceRegistry); + } + + @Before + public void setUp() { + session = sessionFactory.openSession(); + session.beginTransaction(); + } + + @Test + public void givenSession_checkIfDatabaseIsEmpty() { + Cart cart = (Cart) session.get(Cart.class, new Long(1)); + assertNull(cart); + + } + + @Test + public void givenSession_checkIfDatabaseIsPopulated_afterCommit() { + Cart cart = new Cart(); + Set cartItems = new HashSet<>(); + cartItems = cart.getItems(); + Assert.assertNull(cartItems); + Items item1 = new Items(); + item1.setCart(cart); + assertNotNull(item1); + Set itemsSet = new HashSet(); + itemsSet.add(item1); + assertNotNull(itemsSet); + cart.setItems(itemsSet); + assertNotNull(cart); + session.persist(cart); + session.getTransaction().commit(); + session.close(); + + session = sessionFactory.openSession(); + session.beginTransaction(); + cart = (Cart) session.get(Cart.class, new Long(1)); + assertNotNull(cart); + } + + @After + public void tearDown() { + session.getTransaction().commit(); + session.close(); + } + + @AfterClass + public static void afterTests() { + sessionFactory.close(); + } - @Test - public void testAddItemsToCart() { - Cart cart = new Cart(); - Set cartItems = new HashSet<>(); - cartItems = cart.getItems(); - Assert.assertNull(cartItems); - Items item1 = new Items("I10", 10, 1, cart); - assertNotNull(item1); - Set itemsSet = new HashSet(); - cart.setItems(itemsSet); - assertNotNull(cart); - System.out.println("Items added to cart"); - - } - - @Test - public void givenSession_checkIfDatabaseIsPopulated_afterCommit(){ - Cart cart = new Cart(); - Set cartItems = new HashSet<>(); - cartItems = cart.getItems(); - Assert.assertNull(cartItems); - Items item1 = new Items(); - item1.setItemId("I10"); - item1.setItemTotal(10); - item1.setQuantity(1); - item1.setCart(cart); - assertNotNull(item1); - Set itemsSet = new HashSet(); - itemsSet.add(item1); - assertNotNull(itemsSet); - cart.setItems(itemsSet); - assertNotNull(cart); - session.persist(cart); - session.getTransaction().commit(); - cart = (Cart) session.get(Cart.class, new Long(1)); - assertNotNull(cart); - session.close(); - - } - - } diff --git a/spring-jersey/README.md b/spring-jersey/README.md index 2767ceb9a7..8b2eecc0e1 100644 --- a/spring-jersey/README.md +++ b/spring-jersey/README.md @@ -1,3 +1,5 @@ ========= ## REST API with Jersey & Spring Example Project +- [REST API with Jersey and Spring](http://www.baeldung.com/jersey-rest-api-with-spring) +- [JAX-RS Client with Jersey](http://www.baeldung.com/jersey-jax-rs-client) diff --git a/spring-jersey/pom.xml b/spring-jersey/pom.xml index 293850d41e..41ebb9a6b5 100644 --- a/spring-jersey/pom.xml +++ b/spring-jersey/pom.xml @@ -9,7 +9,7 @@ war - 2.25 + 2.25.1 1.7.22 1.1.8 4.12 diff --git a/spring-jersey/src/main/java/com/baeldung/client/rest/RestClient.java b/spring-jersey/src/main/java/com/baeldung/client/rest/RestClient.java index 0e45b68b14..34f7d45601 100644 --- a/spring-jersey/src/main/java/com/baeldung/client/rest/RestClient.java +++ b/spring-jersey/src/main/java/com/baeldung/client/rest/RestClient.java @@ -18,7 +18,7 @@ public class RestClient { } public Employee getJsonEmployee(int id) { - return client.target(REST_URI).path(new Integer(id).toString()).request(MediaType.APPLICATION_JSON).get(Employee.class); + return client.target(REST_URI).path(String.valueOf(id)).request(MediaType.APPLICATION_JSON).get(Employee.class); } public Response createXmlEmployee(Employee emp) { @@ -26,6 +26,6 @@ public class RestClient { } public Employee getXmlEmployee(int id) { - return client.target(REST_URI).path(new Integer(id).toString()).request(MediaType.APPLICATION_XML).get(Employee.class); + return client.target(REST_URI).path(String.valueOf(id)).request(MediaType.APPLICATION_XML).get(Employee.class); } } diff --git a/spring-jooq/pom.xml b/spring-jooq/pom.xml index bf0dffd68c..195c0b8514 100644 --- a/spring-jooq/pom.xml +++ b/spring-jooq/pom.xml @@ -1,215 +1,215 @@ - 4.0.0 - com.baeldung - jooq-spring - 0.0.1-SNAPSHOT + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + com.baeldung + jooq-spring + 0.0.1-SNAPSHOT - - - - - org.springframework.boot - spring-boot-dependencies - 1.4.2.RELEASE - pom - import - - - + + + + + org.springframework.boot + spring-boot-dependencies + 1.4.4.RELEASE + pom + import + + + - - - - org.jooq - jooq - + + + + org.jooq + jooq + - - - com.h2database - h2 - + + + com.h2database + h2 + - - - org.springframework - spring-context - - - org.springframework - spring-jdbc - - - org.springframework.boot - spring-boot-starter-jooq - + + + org.springframework + spring-context + + + org.springframework + spring-jdbc + + + org.springframework.boot + spring-boot-starter-jooq + - - - org.slf4j - slf4j-api - runtime - - - ch.qos.logback - logback-classic - runtime - + + + org.slf4j + slf4j-api + runtime + + + ch.qos.logback + logback-classic + runtime + - - - junit - junit - test - - - org.springframework - spring-test - test - - - org.springframework.boot - spring-boot-starter-test - - - + + + junit + junit + test + + + org.springframework + spring-test + test + + + org.springframework.boot + spring-boot-starter-test + - - - - org.codehaus.mojo - properties-maven-plugin - ${properties-maven-plugin.version} - - - initialize - - read-project-properties - - - - src/main/resources/intro_config.properties - - - - - + - - org.codehaus.mojo - sql-maven-plugin - ${sql-maven-plugin.version} - - - initialize - - execute - - - ${db.driver} - ${db.url} - ${db.username} - ${db.password} - - src/main/resources/intro_schema.sql - - - - - - - com.h2database - h2 - ${com.h2database.version} - - - + + + + org.codehaus.mojo + properties-maven-plugin + ${properties-maven-plugin.version} + + + initialize + + read-project-properties + + + + src/main/resources/intro_config.properties + + + + + - - org.jooq - jooq-codegen-maven - ${org.jooq.version} - - - generate-sources - - generate - - - - ${db.driver} - ${db.url} - ${db.username} - ${db.password} - - - - com.baeldung.jooq.introduction.db - src/main/java - - - - - - + + org.codehaus.mojo + sql-maven-plugin + ${sql-maven-plugin.version} + + + initialize + + execute + + + ${db.driver} + ${db.url} + ${db.username} + ${db.password} + + src/main/resources/intro_schema.sql + + + + + + + com.h2database + h2 + ${com.h2database.version} + + + - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} - - 1.8 - 1.8 - - + + org.jooq + jooq-codegen-maven + ${org.jooq.version} + + + generate-sources + + generate + + + + ${db.driver} + ${db.url} + ${db.username} + ${db.password} + + + + com.baeldung.jooq.introduction.db + src/main/java + + + + + + - - org.apache.maven.plugins - maven-surefire-plugin - - - **/*IntegrationTest.java - **/*LiveTest.java - - - + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + - - - - - - org.eclipse.m2e - lifecycle-mapping - ${lifecycle-mapping.version} - - - - - - org.jooq - - jooq-codegen-maven - - - [3.7.3,) - - - generate - - - - - - - - - - - - - + + org.apache.maven.plugins + maven-surefire-plugin + + + **/*IntegrationTest.java + **/*LiveTest.java + + + + + + + + + + org.eclipse.m2e + lifecycle-mapping + ${lifecycle-mapping.version} + + + + + + org.jooq + + jooq-codegen-maven + + + [3.7.3,) + + + generate + + + + + + + + + + + + + @@ -245,21 +245,21 @@ - - - 3.8.6 - 1.4.193 - 4.3.4.RELEASE - 1.7.21 - 1.1.7 - 4.12 - - 3.6.0 + + + 3.8.6 + 1.4.193 + 4.3.4.RELEASE + 1.7.21 + 1.1.7 + 4.12 + + 3.6.0 2.19.1 1.0.0 1.5 - 1.0.0 - - + 1.0.0 + + \ No newline at end of file diff --git a/spring-katharsis/pom.xml b/spring-katharsis/pom.xml index 32f24231a9..25a1c13f6b 100644 --- a/spring-katharsis/pom.xml +++ b/spring-katharsis/pom.xml @@ -8,7 +8,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-mobile/README.md b/spring-mobile/README.md new file mode 100644 index 0000000000..e3d23bcda6 --- /dev/null +++ b/spring-mobile/README.md @@ -0,0 +1,4 @@ +## Relevant articles: + +- [A Guide to Spring Mobile](http://www.baeldung.com/spring-mobile) + diff --git a/spring-mobile/src/main/java/com/baeldung/Application.java b/spring-mobile/src/main/java/com/baeldung/Application.java index d384ab09b3..7275477b8d 100644 --- a/spring-mobile/src/main/java/com/baeldung/Application.java +++ b/spring-mobile/src/main/java/com/baeldung/Application.java @@ -6,9 +6,10 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - } + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + + } } diff --git a/spring-mockito/pom.xml b/spring-mockito/pom.xml index ca9bad2bc0..3231faf197 100644 --- a/spring-mockito/pom.xml +++ b/spring-mockito/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-mvc-email/README.md b/spring-mvc-email/README.md index 0de6532393..aa880188d7 100644 --- a/spring-mvc-email/README.md +++ b/spring-mvc-email/README.md @@ -1,3 +1,7 @@ +## Relevant articles: + +- [Guide to Spring Email](http://www.baeldung.com/spring-email) + ## Spring MVC Email Example Spring MVC project to send email from web form. @@ -10,4 +14,4 @@ Type http://localhost:8080 in your browser to open the application. ### Sending test emails -Follow UI links to send simple email, email using template or email with attachment. \ No newline at end of file +Follow UI links to send simple email, email using template or email with attachment. diff --git a/spring-mvc-email/pom.xml b/spring-mvc-email/pom.xml index 5d72bb4a1c..4a3ef5f83b 100644 --- a/spring-mvc-email/pom.xml +++ b/spring-mvc-email/pom.xml @@ -12,7 +12,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-mvc-forms/pom.xml b/spring-mvc-forms/pom.xml index 31a0c38791..35ed00c0e9 100644 --- a/spring-mvc-forms/pom.xml +++ b/spring-mvc-forms/pom.xml @@ -46,6 +46,7 @@ commons-fileupload ${fileupload.version} + diff --git a/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/configuration/WebInitializer.java b/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/configuration/WebInitializer.java index c602ea6454..2eb669da2c 100644 --- a/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/configuration/WebInitializer.java +++ b/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/configuration/WebInitializer.java @@ -24,6 +24,7 @@ public class WebInitializer implements WebApplicationInitializer { servlet.setLoadOnStartup(1); servlet.addMapping("/"); + } // @Override // public void onStartup(ServletContext container) { diff --git a/spring-mvc-java/README.md b/spring-mvc-java/README.md index 0f267c5ec9..4d3e58558b 100644 --- a/spring-mvc-java/README.md +++ b/spring-mvc-java/README.md @@ -18,3 +18,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Spring MVC Content Negotiation](http://www.baeldung.com/spring-mvc-content-negotiation-json-xml) - [Circular Dependencies in Spring](http://www.baeldung.com/circular-dependencies-in-spring) - [Introduction to HtmlUnit](http://www.baeldung.com/htmlunit) +- [Spring @RequestMapping New Shortcut Annotations](http://www.baeldung.com/spring-new-requestmapping-shortcuts) +- [Guide to Spring Handler Mappings](http://www.baeldung.com/spring-handler-mappings) +- [Uploading and Displaying Excel Files with Spring MVC](http://www.baeldung.com/spring-mvc-excel-files) diff --git a/spring-mvc-java/persons.xls b/spring-mvc-java/persons.xls new file mode 100644 index 0000000000..ea270f69cc Binary files /dev/null and b/spring-mvc-java/persons.xls differ diff --git a/spring-mvc-java/persons.xlsx b/spring-mvc-java/persons.xlsx new file mode 100644 index 0000000000..1f58606532 Binary files /dev/null and b/spring-mvc-java/persons.xlsx differ diff --git a/spring-mvc-java/pom.xml b/spring-mvc-java/pom.xml index 9513c81064..ef18cef3e0 100644 --- a/spring-mvc-java/pom.xml +++ b/spring-mvc-java/pom.xml @@ -161,26 +161,11 @@ - - org.apache.poi - poi - ${poi.version} - org.apache.poi poi-ooxml ${poi.version} - - org.apache.poi - poi-ooxml-schemas - ${poi.version} - - - org.jxls - jxls-jexcel - ${jexcel.version} - @@ -395,7 +380,6 @@ 3.16-beta1 - 1.0.6 diff --git a/spring-mvc-java/src/main/java/com/baeldung/excel/ExcelPOIHelper.java b/spring-mvc-java/src/main/java/com/baeldung/excel/ExcelPOIHelper.java index 5cf74aff63..0519a8f3c7 100644 --- a/spring-mvc-java/src/main/java/com/baeldung/excel/ExcelPOIHelper.java +++ b/spring-mvc-java/src/main/java/com/baeldung/excel/ExcelPOIHelper.java @@ -1,140 +1,185 @@ package com.baeldung.excel; import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.CellType; -import org.apache.poi.ss.usermodel.CellStyle; -import org.apache.poi.ss.usermodel.IndexedColors; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.apache.poi.xssf.usermodel.XSSFCell; +import org.apache.poi.xssf.usermodel.XSSFCellStyle; +import org.apache.poi.xssf.usermodel.XSSFColor; import org.apache.poi.xssf.usermodel.XSSFFont; +import org.apache.poi.xssf.usermodel.XSSFRow; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.apache.poi.hssf.usermodel.HSSFCell; +import org.apache.poi.hssf.usermodel.HSSFCellStyle; +import org.apache.poi.hssf.usermodel.HSSFFont; +import org.apache.poi.hssf.usermodel.HSSFRow; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.ss.usermodel.DateUtil; -import org.apache.poi.ss.usermodel.FillPatternType; + import java.io.File; -import java.io.FileOutputStream; import java.io.FileInputStream; import java.io.IOException; -import java.io.InputStream; import java.util.Map; import java.util.HashMap; import java.util.ArrayList; -import org.springframework.stereotype.Service; +import java.util.List; +import java.util.stream.IntStream; -@Service public class ExcelPOIHelper { - public Map> readExcel(String fileLocation) throws IOException { + public Map> readExcel(String fileLocation) throws IOException { - Map> data = new HashMap>(); - FileInputStream file = new FileInputStream(new File(fileLocation)); - Workbook workbook = new XSSFWorkbook(file); - Sheet sheet = workbook.getSheetAt(0); - int i = 0; - for (Row row : sheet) { - data.put(i, new ArrayList()); - for (Cell cell : row) { - switch (cell.getCellTypeEnum()) { - case STRING: - data.get(i) - .add(cell.getRichStringCellValue() - .getString()); - break; - case NUMERIC: - if (DateUtil.isCellDateFormatted(cell)) { - data.get(i) - .add(cell.getDateCellValue() + ""); - } else { - data.get(i) - .add(cell.getNumericCellValue() + ""); + Map> data = new HashMap<>(); + FileInputStream fis = new FileInputStream(new File(fileLocation)); + + if (fileLocation.endsWith(".xls")) { + data = readHSSFWorkbook(fis); + } else if (fileLocation.endsWith(".xlsx")) { + data = readXSSFWorkbook(fis); + } + + int maxNrCols = data.values().stream() + .mapToInt(List::size) + .max() + .orElse(0); + + data.values().stream() + .filter(ls -> ls.size() < maxNrCols) + .forEach(ls -> { + IntStream.range(ls.size(), maxNrCols) + .forEach(i -> ls.add(new MyCell(""))); + }); + + return data; + } + + private String readCellContent(Cell cell) { + String content; + switch (cell.getCellTypeEnum()) { + case STRING: + content = cell.getStringCellValue(); + break; + case NUMERIC: + if (DateUtil.isCellDateFormatted(cell)) { + content = cell.getDateCellValue() + ""; + } else { + content = cell.getNumericCellValue() + ""; + } + break; + case BOOLEAN: + content = cell.getBooleanCellValue() + ""; + break; + case FORMULA: + content = cell.getCellFormula() + ""; + break; + default: + content = ""; + } + return content; + } + + private Map> readHSSFWorkbook(FileInputStream fis) throws IOException { + Map> data = new HashMap<>(); + HSSFWorkbook workbook = null; + try { + workbook = new HSSFWorkbook(fis); + + HSSFSheet sheet = workbook.getSheetAt(0); + for (int i = sheet.getFirstRowNum(); i <= sheet.getLastRowNum(); i++) { + HSSFRow row = sheet.getRow(i); + data.put(i, new ArrayList<>()); + if (row != null) { + for (int j = 0; j < row.getLastCellNum(); j++) { + HSSFCell cell = row.getCell(j); + if (cell != null) { + HSSFCellStyle cellStyle = cell.getCellStyle(); + + MyCell myCell = new MyCell(); + + HSSFColor bgColor = cellStyle.getFillForegroundColorColor(); + if (bgColor != null) { + short[] rgbColor = bgColor.getTriplet(); + myCell.setBgColor("rgb(" + rgbColor[0] + "," + rgbColor[1] + "," + rgbColor[2] + ")"); + } + HSSFFont font = cell.getCellStyle() + .getFont(workbook); + myCell.setTextSize(font.getFontHeightInPoints() + ""); + if (font.getBold()) { + myCell.setTextWeight("bold"); + } + HSSFColor textColor = font.getHSSFColor(workbook); + if (textColor != null) { + short[] rgbColor = textColor.getTriplet(); + myCell.setTextColor("rgb(" + rgbColor[0] + "," + rgbColor[1] + "," + rgbColor[2] + ")"); + } + myCell.setContent(readCellContent(cell)); + data.get(i) + .add(myCell); + } else { + data.get(i) + .add(new MyCell("")); + } } - break; - case BOOLEAN: - data.get(i) - .add(cell.getBooleanCellValue() + ""); - break; - case FORMULA: - data.get(i) - .add(cell.getCellFormula() + ""); - break; - default: - data.get(i) - .add(" "); } } - i++; - } - if (workbook != null){ - workbook.close(); + } finally { + if (workbook != null) { + workbook.close(); + } } return data; } - public void writeExcel() throws IOException { - Workbook workbook = new XSSFWorkbook(); - + private Map> readXSSFWorkbook(FileInputStream fis) throws IOException { + XSSFWorkbook workbook = null; + Map> data = new HashMap<>(); try { - Sheet sheet = workbook.createSheet("Persons"); - sheet.setColumnWidth(0, 6000); - sheet.setColumnWidth(1, 4000); - Row header = sheet.createRow(0); + workbook = new XSSFWorkbook(fis); + XSSFSheet sheet = workbook.getSheetAt(0); - CellStyle headerStyle = workbook.createCellStyle(); + for (int i = sheet.getFirstRowNum(); i <= sheet.getLastRowNum(); i++) { + XSSFRow row = sheet.getRow(i); + data.put(i, new ArrayList<>()); + if (row != null) { + for (int j = 0; j < row.getLastCellNum(); j++) { + XSSFCell cell = row.getCell(j); + if (cell != null) { + XSSFCellStyle cellStyle = cell.getCellStyle(); - headerStyle.setFillForegroundColor(IndexedColors.LIGHT_BLUE.getIndex()); - headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); - - XSSFFont font = ((XSSFWorkbook) workbook).createFont(); - font.setFontName("Arial"); - font.setFontHeightInPoints((short) 16); - font.setBold(true); - headerStyle.setFont(font); - - Cell headerCell = header.createCell(0); - headerCell.setCellValue("Name"); - headerCell.setCellStyle(headerStyle); - - headerCell = header.createCell(1); - headerCell.setCellValue("Age"); - headerCell.setCellStyle(headerStyle); - - CellStyle style = workbook.createCellStyle(); - style.setWrapText(true); - - Row row = sheet.createRow(2); - Cell cell = row.createCell(0); - cell.setCellValue("John Smith"); - cell.setCellStyle(style); - - cell = row.createCell(1); - cell.setCellValue(20); - cell.setCellStyle(style); - - row = sheet.createRow(3); - cell = row.createCell(0); - cell.setCellValue("Ana Johnson"); - cell.setCellStyle(style); - - cell = row.createCell(1); - cell.setCellValue(30); - cell.setCellStyle(style); - - File currDir = new File("."); - String path = currDir.getAbsolutePath(); - String fileLocation = path.substring(0, path.length() - 1) + "temp.xlsx"; - - FileOutputStream outputStream = new FileOutputStream(fileLocation); - workbook.write(outputStream); - } finally { - if (workbook != null) { - try { - workbook.close(); - } catch (IOException e) { - e.printStackTrace(); + MyCell myCell = new MyCell(); + XSSFColor bgColor = cellStyle.getFillForegroundColorColor(); + if (bgColor != null) { + byte[] rgbColor = bgColor.getRGB(); + myCell.setBgColor("rgb(" + (rgbColor[0] < 0 ? (rgbColor[0] + 0xff) : rgbColor[0]) + "," + (rgbColor[1] < 0 ? (rgbColor[1] + 0xff) : rgbColor[1]) + "," + (rgbColor[2] < 0 ? (rgbColor[2] + 0xff) : rgbColor[2]) + ")"); + } + XSSFFont font = cellStyle.getFont(); + myCell.setTextSize(font.getFontHeightInPoints() + ""); + if (font.getBold()) { + myCell.setTextWeight("bold"); + } + XSSFColor textColor = font.getXSSFColor(); + if (textColor != null) { + byte[] rgbColor = textColor.getRGB(); + myCell.setTextColor("rgb(" + (rgbColor[0] < 0 ? (rgbColor[0] + 0xff) : rgbColor[0]) + "," + (rgbColor[1] < 0 ? (rgbColor[1] + 0xff) : rgbColor[1]) + "," + (rgbColor[2] < 0 ? (rgbColor[2] + 0xff) : rgbColor[2]) + ")"); + } + myCell.setContent(readCellContent(cell)); + data.get(i) + .add(myCell); + } else { + data.get(i) + .add(new MyCell("")); + } + } } } + } finally { + if (workbook != null) { + workbook.close(); + } } + return data; } } \ No newline at end of file diff --git a/spring-mvc-java/src/main/java/com/baeldung/excel/MyCell.java b/spring-mvc-java/src/main/java/com/baeldung/excel/MyCell.java new file mode 100644 index 0000000000..409829bc35 --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/excel/MyCell.java @@ -0,0 +1,57 @@ +package com.baeldung.excel; + +public class MyCell { + private String content; + private String textColor; + private String bgColor; + private String textSize; + private String textWeight; + + public MyCell() { + } + + public MyCell(String content) { + this.content = content; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getTextColor() { + return textColor; + } + + public void setTextColor(String textColor) { + this.textColor = textColor; + } + + public String getBgColor() { + return bgColor; + } + + public void setBgColor(String bgColor) { + this.bgColor = bgColor; + } + + public String getTextSize() { + return textSize; + } + + public void setTextSize(String textSize) { + this.textSize = textSize; + } + + public String getTextWeight() { + return textWeight; + } + + public void setTextWeight(String textWeight) { + this.textWeight = textWeight; + } + +} \ No newline at end of file diff --git a/spring-mvc-java/src/main/java/com/baeldung/model/FormDataWithFile.java b/spring-mvc-java/src/main/java/com/baeldung/model/FormDataWithFile.java new file mode 100644 index 0000000000..29925a592d --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/model/FormDataWithFile.java @@ -0,0 +1,35 @@ +package com.baeldung.model; + +import org.springframework.web.multipart.MultipartFile; + +public class FormDataWithFile { + + private String name; + private String email; + private MultipartFile file; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public MultipartFile getFile() { + return file; + } + + public void setFile(MultipartFile file) { + this.file = file; + } + +} diff --git a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java index 9578303554..11be08a79d 100644 --- a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java +++ b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java @@ -108,11 +108,6 @@ public class WebConfig extends WebMvcConfigurerAdapter { configurer.setUrlPathHelper(urlPathHelper); } - @Bean - public JExcelHelper jExcelHelper() { - return new JExcelHelper(); - } - @Bean public ExcelPOIHelper excelPOIHelper() { return new ExcelPOIHelper(); diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/ExcelController.java b/spring-mvc-java/src/main/java/com/baeldung/web/controller/ExcelController.java index 810282dd65..f76f7441a5 100644 --- a/spring-mvc-java/src/main/java/com/baeldung/web/controller/ExcelController.java +++ b/spring-mvc-java/src/main/java/com/baeldung/web/controller/ExcelController.java @@ -10,20 +10,15 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import com.baeldung.excel.*; -import jxl.read.biff.BiffException; import java.util.Map; -import java.util.ArrayList; +import java.util.List; import javax.annotation.Resource; -import jxl.write.WriteException; @Controller public class ExcelController { private String fileLocation; - @Resource(name = "jExcelHelper") - private JExcelHelper jExcelHelper; - @Resource(name = "excelPOIHelper") private ExcelPOIHelper excelPOIHelper; @@ -45,36 +40,19 @@ public class ExcelController { } f.flush(); f.close(); - System.out.println(fileLocation); model.addAttribute("message", "File: " + file.getOriginalFilename() + " has been uploaded successfully!"); return "excel"; } - @RequestMapping(method = RequestMethod.GET, value = "/readJExcel") - public String readJExcel(Model model) throws IOException, BiffException { - - if (fileLocation != null) { - if (fileLocation.endsWith(".xls")) { - Map> data = jExcelHelper.readJExcel(fileLocation); - model.addAttribute("data", data); - } else { - model.addAttribute("message", "Not a valid .xls file!"); - } - } else { - model.addAttribute("message", "File missing! Please upload an excel file."); - } - return "excel"; - } - @RequestMapping(method = RequestMethod.GET, value = "/readPOI") public String readPOI(Model model) throws IOException { if (fileLocation != null) { - if (fileLocation.endsWith(".xlsx")) { - Map> data = excelPOIHelper.readExcel(fileLocation); + if (fileLocation.endsWith(".xlsx") || fileLocation.endsWith(".xls")) { + Map> data = excelPOIHelper.readExcel(fileLocation); model.addAttribute("data", data); } else { - model.addAttribute("message", "Not a valid .xlsx file!"); + model.addAttribute("message", "Not a valid excel file!"); } } else { model.addAttribute("message", "File missing! Please upload an excel file."); @@ -82,24 +60,4 @@ public class ExcelController { return "excel"; } - @RequestMapping(method = RequestMethod.POST, value = "/writeJExcel") - public String writeJExcel(Model model) throws IOException, BiffException, WriteException { - - jExcelHelper.writeJExcel(); - - model.addAttribute("message", "Write successful!"); - - return "excel"; - } - - @RequestMapping(method = RequestMethod.POST, value = "/writePOI") - public String writePOI(Model model) throws IOException { - - excelPOIHelper.writeExcel(); - - model.addAttribute("message", "Write successful!"); - - return "excel"; - } - } \ No newline at end of file diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/FileUploadController.java b/spring-mvc-java/src/main/java/com/baeldung/web/controller/FileUploadController.java index 61bccb21aa..b357b9270f 100644 --- a/spring-mvc-java/src/main/java/com/baeldung/web/controller/FileUploadController.java +++ b/spring-mvc-java/src/main/java/com/baeldung/web/controller/FileUploadController.java @@ -2,11 +2,14 @@ package com.baeldung.web.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; +import com.baeldung.model.FormDataWithFile; + @Controller public class FileUploadController { @@ -29,4 +32,21 @@ public class FileUploadController { modelMap.addAttribute("files", files); return "fileUploadView"; } + + @RequestMapping(value = "/uploadFileWithAddtionalData", method = RequestMethod.POST) + public String submit(@RequestParam final MultipartFile file, @RequestParam final String name, @RequestParam final String email, final ModelMap modelMap) { + + modelMap.addAttribute("name", name); + modelMap.addAttribute("email", email); + modelMap.addAttribute("file", file); + return "fileUploadView"; + } + + @RequestMapping(value = "/uploadFileModelAttribute", method = RequestMethod.POST) + public String submit(@ModelAttribute final FormDataWithFile formDataWithFile, final ModelMap modelMap) { + + modelMap.addAttribute("formDataWithFile", formDataWithFile); + return "fileUploadView"; + } + } diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/RequestMappingShortcutsController.java b/spring-mvc-java/src/main/java/com/baeldung/web/controller/RequestMappingShortcutsController.java new file mode 100644 index 0000000000..5d4cbe9d78 --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/web/controller/RequestMappingShortcutsController.java @@ -0,0 +1,47 @@ +package com.baeldung.web.controller; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class RequestMappingShortcutsController { + + @GetMapping("/get") + public @ResponseBody ResponseEntity get() { + return new ResponseEntity("GET Response", HttpStatus.OK); + } + + @GetMapping("/get/{id}") + public @ResponseBody ResponseEntity getById(@PathVariable String id) { + return new ResponseEntity("GET Response : " + id, HttpStatus.OK); + } + + @PostMapping("/post") + public @ResponseBody ResponseEntity post() { + return new ResponseEntity("POST Response", HttpStatus.OK); + } + + @PutMapping("/put") + public @ResponseBody ResponseEntity put() { + return new ResponseEntity("PUT Response", HttpStatus.OK); + } + + @DeleteMapping("/delete") + public @ResponseBody ResponseEntity delete() { + return new ResponseEntity("DELETE Response", HttpStatus.OK); + } + + @PatchMapping("/patch") + public @ResponseBody ResponseEntity patch() { + return new ResponseEntity("PATCH Response", HttpStatus.OK); + } + +} diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/view/excel.jsp b/spring-mvc-java/src/main/webapp/WEB-INF/view/excel.jsp index b50687df15..bcb5a31371 100644 --- a/spring-mvc-java/src/main/webapp/WEB-INF/view/excel.jsp +++ b/spring-mvc-java/src/main/webapp/WEB-INF/view/excel.jsp @@ -1,6 +1,6 @@ <%@ page language="java" contentType="text/html; charset=ISO-8859-1" - pageEncoding="ISO-8859-1"%> -<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> + pageEncoding="ISO-8859-1"%> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> @@ -8,49 +8,43 @@ Excel Processing - - - - - - + + + -
- - -
-
-${message } -

-
- -
-

-Read file using JExcel     -Read file using Apache POI -

+
+ + +
+
+
+ +
+
${message } +
+
-File content: - - - - - - - - - -
${cell}
-
-

-
- -
-
-
- -
+
+ +
+
+
+ + + + + + + + + + +
+ ${cell.content} +
+
- \ No newline at end of file diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/view/fileUploadForm.jsp b/spring-mvc-java/src/main/webapp/WEB-INF/view/fileUploadForm.jsp index 1414b824ff..41b7c09629 100644 --- a/spring-mvc-java/src/main/webapp/WEB-INF/view/fileUploadForm.jsp +++ b/spring-mvc-java/src/main/webapp/WEB-INF/view/fileUploadForm.jsp @@ -49,6 +49,58 @@ + +
+ +

Fill the Form and Select a File (@RequestParam)

+ + + + + + + + + + + + + + + + + + + +
Name
Email
Select a file to upload
+ +
+ +
+ +

Fill the Form and Select a File (@ModelAttribute)

+ + + + + + + + + + + + + + + + + + + +
Name
Email
Select a file to upload
+ +
diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/view/fileUploadView.jsp b/spring-mvc-java/src/main/webapp/WEB-INF/view/fileUploadView.jsp index d6f748c6af..696af4c4aa 100644 --- a/spring-mvc-java/src/main/webapp/WEB-INF/view/fileUploadView.jsp +++ b/spring-mvc-java/src/main/webapp/WEB-INF/view/fileUploadView.jsp @@ -32,5 +32,48 @@ +
+ +

Submitted File with Data (@RequestParam)

+ + + + + + + + + + + + + + + + + +
Name :${name}
Email :${email}
OriginalFileName :${file.originalFilename}
Type :${file.contentType}
+ +
+ +

Submitted File with Data (@ModelAttribute)

+ + + + + + + + + + + + + + + + + +
Name :${formDataWithFile.name}
Email :${formDataWithFile.email}
OriginalFileName :${formDataWithFile.file.originalFilename}
Type :${formDataWithFile.file.contentType}
\ No newline at end of file diff --git a/spring-mvc-java/src/test/java/com/baeldung/handlermappings/BeanNameMappingConfigTest.java b/spring-mvc-java/src/test/java/com/baeldung/handlermappings/BeanNameMappingConfigIntegrationTest.java similarity index 96% rename from spring-mvc-java/src/test/java/com/baeldung/handlermappings/BeanNameMappingConfigTest.java rename to spring-mvc-java/src/test/java/com/baeldung/handlermappings/BeanNameMappingConfigIntegrationTest.java index f58e5cb0a1..f2c2c05f29 100644 --- a/spring-mvc-java/src/test/java/com/baeldung/handlermappings/BeanNameMappingConfigTest.java +++ b/spring-mvc-java/src/test/java/com/baeldung/handlermappings/BeanNameMappingConfigIntegrationTest.java @@ -22,7 +22,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration(classes = BeanNameUrlHandlerMappingConfig.class) -public class BeanNameMappingConfigTest { +public class BeanNameMappingConfigIntegrationTest { @Autowired private WebApplicationContext webAppContext; diff --git a/spring-mvc-java/src/test/java/com/baeldung/handlermappings/ControllerClassNameHandlerMappingTest.java b/spring-mvc-java/src/test/java/com/baeldung/handlermappings/ControllerClassNameHandlerMappingIntegrationTest.java similarity index 96% rename from spring-mvc-java/src/test/java/com/baeldung/handlermappings/ControllerClassNameHandlerMappingTest.java rename to spring-mvc-java/src/test/java/com/baeldung/handlermappings/ControllerClassNameHandlerMappingIntegrationTest.java index 6fdd168d0b..b84998470d 100644 --- a/spring-mvc-java/src/test/java/com/baeldung/handlermappings/ControllerClassNameHandlerMappingTest.java +++ b/spring-mvc-java/src/test/java/com/baeldung/handlermappings/ControllerClassNameHandlerMappingIntegrationTest.java @@ -22,7 +22,7 @@ import com.baeldung.config.ControllerClassNameHandlerMappingConfig; @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration(classes = ControllerClassNameHandlerMappingConfig.class) -public class ControllerClassNameHandlerMappingTest { +public class ControllerClassNameHandlerMappingIntegrationTest { @Autowired private WebApplicationContext webAppContext; diff --git a/spring-mvc-java/src/test/java/com/baeldung/handlermappings/HandlerMappingDefaultConfigTest.java b/spring-mvc-java/src/test/java/com/baeldung/handlermappings/HandlerMappingDefaultConfigIntegrationTest.java similarity index 93% rename from spring-mvc-java/src/test/java/com/baeldung/handlermappings/HandlerMappingDefaultConfigTest.java rename to spring-mvc-java/src/test/java/com/baeldung/handlermappings/HandlerMappingDefaultConfigIntegrationTest.java index 01be65b829..cb89c01fed 100644 --- a/spring-mvc-java/src/test/java/com/baeldung/handlermappings/HandlerMappingDefaultConfigTest.java +++ b/spring-mvc-java/src/test/java/com/baeldung/handlermappings/HandlerMappingDefaultConfigIntegrationTest.java @@ -1,7 +1,10 @@ package com.baeldung.handlermappings; -import com.baeldung.config.HandlerMappingDefaultConfig; -import com.baeldung.config.HandlerMappingPrioritiesConfig; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -14,15 +17,12 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; +import com.baeldung.config.HandlerMappingDefaultConfig; @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration(classes = HandlerMappingDefaultConfig.class) -public class HandlerMappingDefaultConfigTest { +public class HandlerMappingDefaultConfigIntegrationTest { @Autowired private WebApplicationContext webAppContext; diff --git a/spring-mvc-java/src/test/java/com/baeldung/handlermappings/HandlerMappingPriorityConfigTest.java b/spring-mvc-java/src/test/java/com/baeldung/handlermappings/HandlerMappingPriorityConfigIntegrationTest.java similarity index 96% rename from spring-mvc-java/src/test/java/com/baeldung/handlermappings/HandlerMappingPriorityConfigTest.java rename to spring-mvc-java/src/test/java/com/baeldung/handlermappings/HandlerMappingPriorityConfigIntegrationTest.java index d6329ca6c1..55007aec28 100644 --- a/spring-mvc-java/src/test/java/com/baeldung/handlermappings/HandlerMappingPriorityConfigTest.java +++ b/spring-mvc-java/src/test/java/com/baeldung/handlermappings/HandlerMappingPriorityConfigIntegrationTest.java @@ -21,7 +21,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration(classes = HandlerMappingPrioritiesConfig.class) -public class HandlerMappingPriorityConfigTest { +public class HandlerMappingPriorityConfigIntegrationTest { @Autowired private WebApplicationContext webAppContext; diff --git a/spring-mvc-java/src/test/java/com/baeldung/handlermappings/SimpleUrlMappingConfigTest.java b/spring-mvc-java/src/test/java/com/baeldung/handlermappings/SimpleUrlMappingConfigIntegrationTest.java similarity index 96% rename from spring-mvc-java/src/test/java/com/baeldung/handlermappings/SimpleUrlMappingConfigTest.java rename to spring-mvc-java/src/test/java/com/baeldung/handlermappings/SimpleUrlMappingConfigIntegrationTest.java index 636339f152..ad35307330 100644 --- a/spring-mvc-java/src/test/java/com/baeldung/handlermappings/SimpleUrlMappingConfigTest.java +++ b/spring-mvc-java/src/test/java/com/baeldung/handlermappings/SimpleUrlMappingConfigIntegrationTest.java @@ -21,7 +21,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration(classes = SimpleUrlHandlerMappingConfig.class) -public class SimpleUrlMappingConfigTest { +public class SimpleUrlMappingConfigIntegrationTest { @Autowired private WebApplicationContext webAppContext; diff --git a/spring-mvc-java/src/test/java/com/baeldung/web/controller/RequestMapingShortcutsUnitTest.java b/spring-mvc-java/src/test/java/com/baeldung/web/controller/RequestMapingShortcutsUnitTest.java new file mode 100644 index 0000000000..d02a7140b5 --- /dev/null +++ b/spring-mvc-java/src/test/java/com/baeldung/web/controller/RequestMapingShortcutsUnitTest.java @@ -0,0 +1,92 @@ +package com.baeldung.web.controller; + +import org.junit.Before; +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 org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultMatcher; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import com.baeldung.spring.web.config.WebConfig; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@ContextConfiguration(classes = WebConfig.class) +public class RequestMapingShortcutsUnitTest { + + @Autowired + private WebApplicationContext ctx; + + private MockMvc mockMvc; + + @Before + public void setup () { + DefaultMockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(this.ctx); + this.mockMvc = builder.build(); + } + + @Test + public void giventUrl_whenGetRequest_thenFindGetResponse() throws Exception { + + MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/get"); + + ResultMatcher contentMatcher = MockMvcResultMatchers.content().string("GET Response"); + + this.mockMvc.perform(builder).andExpect(contentMatcher).andExpect(MockMvcResultMatchers.status().isOk()); + + } + + @Test + public void giventUrl_whenPostRequest_thenFindPostResponse() throws Exception { + + MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.post("/post"); + + ResultMatcher contentMatcher = MockMvcResultMatchers.content().string("POST Response"); + + this.mockMvc.perform(builder).andExpect(contentMatcher).andExpect(MockMvcResultMatchers.status().isOk()); + + } + + @Test + public void giventUrl_whenPutRequest_thenFindPutResponse() throws Exception { + + MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.put("/put"); + + ResultMatcher contentMatcher = MockMvcResultMatchers.content().string("PUT Response"); + + this.mockMvc.perform(builder).andExpect(contentMatcher).andExpect(MockMvcResultMatchers.status().isOk()); + + } + + @Test + public void giventUrl_whenDeleteRequest_thenFindDeleteResponse() throws Exception { + + MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.delete("/delete"); + + ResultMatcher contentMatcher = MockMvcResultMatchers.content().string("DELETE Response"); + + this.mockMvc.perform(builder).andExpect(contentMatcher).andExpect(MockMvcResultMatchers.status().isOk()); + + } + + @Test + public void giventUrl_whenPatchRequest_thenFindPatchResponse() throws Exception { + + MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.patch("/patch"); + + ResultMatcher contentMatcher = MockMvcResultMatchers.content().string("PATCH Response"); + + this.mockMvc.perform(builder).andExpect(contentMatcher).andExpect(MockMvcResultMatchers.status().isOk()); + + } + +} diff --git a/spring-mvc-simple/README.md b/spring-mvc-simple/README.md new file mode 100644 index 0000000000..ffb02c846a --- /dev/null +++ b/spring-mvc-simple/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [HandlerAdapters in Spring MVC](http://www.baeldung.com/spring-mvc-handler-adapters) diff --git a/spring-mvc-web-vs-initializer/pom.xml b/spring-mvc-web-vs-initializer/pom.xml index c8bb08cb38..8fe8893903 100644 --- a/spring-mvc-web-vs-initializer/pom.xml +++ b/spring-mvc-web-vs-initializer/pom.xml @@ -10,7 +10,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-mvc-xml/pom.xml b/spring-mvc-xml/pom.xml index f0e4bbff55..86eb17da64 100644 --- a/spring-mvc-xml/pom.xml +++ b/spring-mvc-xml/pom.xml @@ -116,7 +116,13 @@ com.maxmind.geoip2 geoip2 ${geoip2.version} - + + + com.fasterxml.jackson.core + jackson-databind + + + diff --git a/spring-protobuf/pom.xml b/spring-protobuf/pom.xml index 84ebeff9ae..566d11132c 100644 --- a/spring-protobuf/pom.xml +++ b/spring-protobuf/pom.xml @@ -9,7 +9,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-quartz/pom.xml b/spring-quartz/pom.xml index 2fb4ab0e47..85b5734ecc 100644 --- a/spring-quartz/pom.xml +++ b/spring-quartz/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-reactor/README.md b/spring-reactor/README.md new file mode 100644 index 0000000000..0da2d6be51 --- /dev/null +++ b/spring-reactor/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Introduction to Spring Reactor](http://www.baeldung.com/spring-reactor) diff --git a/spring-remoting/pom.xml b/spring-remoting/pom.xml index a43dd52a3e..52d670a726 100644 --- a/spring-remoting/pom.xml +++ b/spring-remoting/pom.xml @@ -3,16 +3,17 @@ 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"> 4.0.0 + com.baeldung + spring-remoting + pom + 1.0-SNAPSHOT + spring-remoting + Parent for all projects related to Spring Remoting. org.springframework.boot spring-boot-starter-parent 1.4.3.RELEASE - com.baeldung - spring-remoting - 1.0-SNAPSHOT - Parent for all projects related to Spring Remoting. - pom 1.8 @@ -34,6 +35,7 @@ remoting-http + remoting-hessian-burlap \ No newline at end of file diff --git a/spring-remoting/remoting-hessian-burlap/client/pom.xml b/spring-remoting/remoting-hessian-burlap/client/pom.xml new file mode 100644 index 0000000000..1ae9b10019 --- /dev/null +++ b/spring-remoting/remoting-hessian-burlap/client/pom.xml @@ -0,0 +1,59 @@ + + + + remoting-hessian-burlap + com.baeldung + 1.0-SNAPSHOT + + 4.0.0 + + spring-remoting-hessian-burlap-client + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-tomcat + + + + + ${project.groupId} + api + + + com.caucho + hessian + 4.0.38 + + + + + ${project.groupId} + remoting-hessian-burlap-server + ${project.version} + test + + + javax.servlet + javax.servlet-api + test + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-tomcat + test + + + + \ No newline at end of file diff --git a/spring-remoting/remoting-hessian-burlap/client/src/main/java/com/baeldung/client/BurlapClient.java b/spring-remoting/remoting-hessian-burlap/client/src/main/java/com/baeldung/client/BurlapClient.java new file mode 100644 index 0000000000..477c29eb26 --- /dev/null +++ b/spring-remoting/remoting-hessian-burlap/client/src/main/java/com/baeldung/client/BurlapClient.java @@ -0,0 +1,28 @@ +package com.baeldung.client; + +import com.baeldung.api.BookingException; +import com.baeldung.api.CabBookingService; +import org.springframework.boot.SpringApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.remoting.caucho.BurlapProxyFactoryBean; + +import static java.lang.System.out; + +@Configuration +public class BurlapClient { + + @Bean + public BurlapProxyFactoryBean burlapInvoker() { + BurlapProxyFactoryBean invoker = new BurlapProxyFactoryBean(); + invoker.setServiceUrl("http://localhost:8080/b_booking"); + invoker.setServiceInterface(CabBookingService.class); + return invoker; + } + + public static void main(String[] args) throws BookingException { + CabBookingService service = SpringApplication.run(BurlapClient.class, args).getBean(CabBookingService.class); + out.println(service.bookRide("13 Seagate Blvd, Key Largo, FL 33037")); + } + +} diff --git a/spring-remoting/remoting-hessian-burlap/client/src/main/java/com/baeldung/client/HessianClient.java b/spring-remoting/remoting-hessian-burlap/client/src/main/java/com/baeldung/client/HessianClient.java new file mode 100644 index 0000000000..b5f366094e --- /dev/null +++ b/spring-remoting/remoting-hessian-burlap/client/src/main/java/com/baeldung/client/HessianClient.java @@ -0,0 +1,28 @@ +package com.baeldung.client; + +import com.baeldung.api.BookingException; +import com.baeldung.api.CabBookingService; +import org.springframework.boot.SpringApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.remoting.caucho.HessianProxyFactoryBean; + +import static java.lang.System.out; + +@Configuration +public class HessianClient { + + @Bean + public HessianProxyFactoryBean hessianInvoker() { + HessianProxyFactoryBean invoker = new HessianProxyFactoryBean(); + invoker.setServiceUrl("http://localhost:8080/booking"); + invoker.setServiceInterface(CabBookingService.class); + return invoker; + } + + public static void main(String[] args) throws BookingException { + CabBookingService service = SpringApplication.run(HessianClient.class, args).getBean(CabBookingService.class); + out.println(service.bookRide("13 Seagate Blvd, Key Largo, FL 33037")); + } + +} diff --git a/spring-remoting/remoting-hessian-burlap/client/src/test/java/com/baeldung/client/CabBookingServiceTest.java b/spring-remoting/remoting-hessian-burlap/client/src/test/java/com/baeldung/client/CabBookingServiceTest.java new file mode 100644 index 0000000000..20746bbf09 --- /dev/null +++ b/spring-remoting/remoting-hessian-burlap/client/src/test/java/com/baeldung/client/CabBookingServiceTest.java @@ -0,0 +1,73 @@ +package com.baeldung.client; + +import com.baeldung.api.Booking; +import com.baeldung.api.BookingException; +import com.baeldung.api.CabBookingService; +import com.baeldung.server.Server; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import static java.lang.Thread.sleep; + +@SpringBootTest(classes = {BurlapClient.class, HessianClient.class}) +@RunWith(SpringRunner.class) +public class CabBookingServiceTest { + + static Logger log = LoggerFactory.getLogger(CabBookingServiceTest.class); + @Autowired @Qualifier("burlapInvoker") CabBookingService burlapClient; + @Autowired @Qualifier("hessianInvoker") CabBookingService hessianClient; + static Thread serverThread; + + @BeforeClass + public static void startServer() throws InterruptedException { + serverThread = serverThread(); + log.info("Starting server."); + serverThread.start(); + sleep(4000); + } + + @org.junit.Test + public void bookACabWithBurlapClient() throws InterruptedException { + bookACab(this.burlapClient); + } + + @org.junit.Test + public void bookACabWithHessianClient() throws InterruptedException { + bookACab(this.hessianClient); + } + + private void bookACab(CabBookingService burlapClient) { + Booking booking; + try { + booking = burlapClient.bookRide("Duomo place"); + log.info("Booking success: {}", booking); + } catch (BookingException e) { + log.info("Booking failed: {}", e.getMessage()); + } + } + + @AfterClass + public static void stopServer() throws InterruptedException { + serverThread.interrupt(); + serverThread.join(); + log.info("Server terminated."); + } + + static Thread serverThread() { + Thread serverThread = new Thread(()-> { + log.info("Starting Burlap and Hessian server"); + Server.main(new String[]{}); + log.info("Burlap and Hessian server terminated"); + }); + serverThread.setDaemon(true); + return serverThread; + } + +} diff --git a/spring-remoting/remoting-hessian-burlap/client/src/test/resources/application.properties b/spring-remoting/remoting-hessian-burlap/client/src/test/resources/application.properties new file mode 100644 index 0000000000..13577dc391 --- /dev/null +++ b/spring-remoting/remoting-hessian-burlap/client/src/test/resources/application.properties @@ -0,0 +1 @@ +application.properties=9999 \ No newline at end of file diff --git a/spring-remoting/remoting-hessian-burlap/pom.xml b/spring-remoting/remoting-hessian-burlap/pom.xml new file mode 100644 index 0000000000..682e460880 --- /dev/null +++ b/spring-remoting/remoting-hessian-burlap/pom.xml @@ -0,0 +1,20 @@ + + + + spring-remoting + com.baeldung + 1.0-SNAPSHOT + + pom + + server + client + + 4.0.0 + + remoting-hessian-burlap + + + \ No newline at end of file diff --git a/spring-remoting/remoting-hessian-burlap/server/pom.xml b/spring-remoting/remoting-hessian-burlap/server/pom.xml new file mode 100644 index 0000000000..f1fed73ed8 --- /dev/null +++ b/spring-remoting/remoting-hessian-burlap/server/pom.xml @@ -0,0 +1,30 @@ + + + + remoting-hessian-burlap + com.baeldung + 1.0-SNAPSHOT + + 4.0.0 + + remoting-hessian-burlap-server + + + + com.baeldung + spring-remoting-http-server + ${project.version} + + + org.springframework.boot + spring-boot-starter-web + + + com.caucho + hessian + 4.0.38 + + + \ No newline at end of file diff --git a/spring-remoting/remoting-hessian-burlap/server/src/main/java/com/baeldung/server/Server.java b/spring-remoting/remoting-hessian-burlap/server/src/main/java/com/baeldung/server/Server.java new file mode 100644 index 0000000000..9b7e463871 --- /dev/null +++ b/spring-remoting/remoting-hessian-burlap/server/src/main/java/com/baeldung/server/Server.java @@ -0,0 +1,37 @@ +package com.baeldung.server; + +import com.baeldung.api.CabBookingService; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.remoting.caucho.BurlapServiceExporter; +import org.springframework.remoting.caucho.HessianServiceExporter; +import org.springframework.remoting.support.RemoteExporter; + +@Configuration @ComponentScan @EnableAutoConfiguration public class Server { + + @Bean CabBookingService bookingService() { + return new CabBookingServiceImpl(); + } + + @Bean(name = "/booking") RemoteExporter hessianService(CabBookingService service) { + HessianServiceExporter exporter = new HessianServiceExporter(); + exporter.setService(bookingService()); + exporter.setServiceInterface(CabBookingService.class); + return exporter; + } + + @Bean(name = "/b_booking") RemoteExporter burlapService(CabBookingService service) { + BurlapServiceExporter exporter = new BurlapServiceExporter(); + exporter.setService(bookingService()); + exporter.setServiceInterface(CabBookingService.class); + return exporter; + } + + public static void main(String[] args) { + SpringApplication.run(Server.class, args); + } + +} \ No newline at end of file diff --git a/spring-rest-angular/pom.xml b/spring-rest-angular/pom.xml index e838e2d5e6..099867d19b 100644 --- a/spring-rest-angular/pom.xml +++ b/spring-rest-angular/pom.xml @@ -11,7 +11,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-rest-docs/pom.xml b/spring-rest-docs/pom.xml index 2acb6b4071..6714617d99 100644 --- a/spring-rest-docs/pom.xml +++ b/spring-rest-docs/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.example - demo + spring-rest-docs 0.0.1-SNAPSHOT jar @@ -14,7 +14,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE @@ -45,13 +45,11 @@ org.springframework.restdocs spring-restdocs-mockmvc - ${restdocs.version} test com.jayway.jsonpath json-path - ${jsonpath.version} diff --git a/spring-security-cache-control/pom.xml b/spring-security-cache-control/pom.xml new file mode 100644 index 0000000000..c30b0cd1aa --- /dev/null +++ b/spring-security-cache-control/pom.xml @@ -0,0 +1,88 @@ + + + 4.0.0 + + com.baeldung + spring-security-cache-control + 1.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + 1.4.3.RELEASE + + + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.security + spring-security-core + + + org.springframework.security + spring-security-config + + + org.springframework.security + spring-security-web + + + org.springframework.boot + spring-boot-starter-test + + + javax.servlet + javax.servlet-api + ${javax.servlet-api.version} + + + + junit + junit + test + + + + org.hamcrest + hamcrest-core + test + + + org.hamcrest + hamcrest-library + test + + + + org.mockito + mockito-core + test + + + + org.springframework + spring-test + + + + com.jayway.restassured + rest-assured + ${rest-assured.version} + + + + + 3.1.0 + 2.9.0 + + + \ No newline at end of file diff --git a/spring-security-cache-control/src/main/java/com/baeldung/cachecontrol/AppRunner.java b/spring-security-cache-control/src/main/java/com/baeldung/cachecontrol/AppRunner.java new file mode 100644 index 0000000000..28ff90a570 --- /dev/null +++ b/spring-security-cache-control/src/main/java/com/baeldung/cachecontrol/AppRunner.java @@ -0,0 +1,12 @@ +package com.baeldung.cachecontrol; + + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class AppRunner { + public static void main(String[] args) { + SpringApplication.run(AppRunner.class, args); + } +} \ No newline at end of file diff --git a/spring-security-cache-control/src/main/java/com/baeldung/cachecontrol/ResourceEndpoint.java b/spring-security-cache-control/src/main/java/com/baeldung/cachecontrol/ResourceEndpoint.java new file mode 100644 index 0000000000..038df43165 --- /dev/null +++ b/spring-security-cache-control/src/main/java/com/baeldung/cachecontrol/ResourceEndpoint.java @@ -0,0 +1,48 @@ +package com.baeldung.cachecontrol; + +import com.baeldung.cachecontrol.model.TimestampDto; +import com.baeldung.cachecontrol.model.UserDto; +import org.springframework.http.CacheControl; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; + +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.util.concurrent.TimeUnit; + +@Controller +public class ResourceEndpoint { + + @GetMapping(value = "/default/users/{name}") + public ResponseEntity getUserWithDefaultCaching(@PathVariable String name) { + return ResponseEntity.ok(new UserDto(name)); + } + + @GetMapping("/users/{name}") + public ResponseEntity getUser(@PathVariable String name) { + return ResponseEntity + .ok() + .cacheControl(CacheControl.maxAge(60, TimeUnit.SECONDS)) + .body(new UserDto(name)); + } + + @GetMapping("/timestamp") + public ResponseEntity getServerTimestamp() { + return ResponseEntity + .ok() + .cacheControl(CacheControl.noStore()) + .body(new TimestampDto(LocalDateTime + .now() + .toInstant(ZoneOffset.UTC) + .toEpochMilli())); + } + + @GetMapping("/private/users/{name}") + public ResponseEntity getUserNotCached(@PathVariable String name) { + return ResponseEntity + .ok() + .body(new UserDto(name)); + } +} diff --git a/spring-security-cache-control/src/main/java/com/baeldung/cachecontrol/config/SpringSecurityConfig.java b/spring-security-cache-control/src/main/java/com/baeldung/cachecontrol/config/SpringSecurityConfig.java new file mode 100644 index 0000000000..b4127e9b71 --- /dev/null +++ b/spring-security-cache-control/src/main/java/com/baeldung/cachecontrol/config/SpringSecurityConfig.java @@ -0,0 +1,17 @@ +package com.baeldung.cachecontrol.config; + + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@Configuration +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled = true) +public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception {} +} diff --git a/spring-security-cache-control/src/main/java/com/baeldung/cachecontrol/model/TimestampDto.java b/spring-security-cache-control/src/main/java/com/baeldung/cachecontrol/model/TimestampDto.java new file mode 100644 index 0000000000..cb3befacac --- /dev/null +++ b/spring-security-cache-control/src/main/java/com/baeldung/cachecontrol/model/TimestampDto.java @@ -0,0 +1,10 @@ +package com.baeldung.cachecontrol.model; + + +public class TimestampDto { + public final Long timestamp; + + public TimestampDto(Long timestamp) { + this.timestamp = timestamp; + } +} diff --git a/spring-security-cache-control/src/main/java/com/baeldung/cachecontrol/model/UserDto.java b/spring-security-cache-control/src/main/java/com/baeldung/cachecontrol/model/UserDto.java new file mode 100644 index 0000000000..a41cb31d80 --- /dev/null +++ b/spring-security-cache-control/src/main/java/com/baeldung/cachecontrol/model/UserDto.java @@ -0,0 +1,11 @@ +package com.baeldung.cachecontrol.model; + + +public class UserDto { + public final String name; + + public UserDto(String name) { + this.name = name; + } + +} diff --git a/spring-security-cache-control/src/test/java/com/baeldung/cachecontrol/ResourceEndpointTest.java b/spring-security-cache-control/src/test/java/com/baeldung/cachecontrol/ResourceEndpointTest.java new file mode 100644 index 0000000000..6d532f98fc --- /dev/null +++ b/spring-security-cache-control/src/test/java/com/baeldung/cachecontrol/ResourceEndpointTest.java @@ -0,0 +1,72 @@ +package com.baeldung.cachecontrol; + +import com.jayway.restassured.http.ContentType; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.context.embedded.LocalServerPort; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import static com.jayway.restassured.RestAssured.given; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = AppRunner.class) +public class ResourceEndpointTest { + + @LocalServerPort + private int serverPort; + + @Test + public void whenGetRequestForUser_shouldRespondWithDefaultCacheHeaders() { + given() + .when() + .get(getBaseUrl() + "/default/users/Michael") + .then() + .headers("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate") + .header("Pragma", "no-cache"); + } + + @Test + public void whenGetRequestForUser_shouldRespondMaxAgeCacheControl() { + given() + .when() + .get(getBaseUrl() + "/users/Michael") + .then() + .header("Cache-Control", "max-age=60"); + } + + @Test + public void givenServiceEndpoint_whenGetRequestForUser_shouldResponseWithCacheControlMaxAge() { + given() + .when() + .get(getBaseUrl() + "/users/Michael") + .then() + .contentType(ContentType.JSON).and().statusCode(200).and() + .header("Cache-Control", "max-age=60"); + } + + @Test + public void givenServiceEndpoint_whenGetRequestForNotCacheableContent_shouldResponseWithCacheControlNoCache() { + given() + .when() + .get(getBaseUrl() + "/timestamp") + .then() + .contentType(ContentType.JSON).and().statusCode(200).and() + .header("Cache-Control", "no-store"); + } + + @Test + public void givenServiceEndpoint_whenGetRequestForPrivateUser_shouldResponseWithSecurityDefaultCacheControl() { + given() + .when() + .get(getBaseUrl() + "/private/users/Michael") + .then() + .contentType(ContentType.JSON).and().statusCode(200).and() + .header("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate"); + } + + private String getBaseUrl() { + return String.format("http://localhost:%d", serverPort); + } + +} \ No newline at end of file diff --git a/spring-security-client/spring-security-jsp-authentication/pom.xml b/spring-security-client/spring-security-jsp-authentication/pom.xml index fc5f0cb86a..c021a46c82 100644 --- a/spring-security-client/spring-security-jsp-authentication/pom.xml +++ b/spring-security-client/spring-security-jsp-authentication/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-security-client/spring-security-jsp-authorize/pom.xml b/spring-security-client/spring-security-jsp-authorize/pom.xml index 8cedbeb713..e3611aba93 100644 --- a/spring-security-client/spring-security-jsp-authorize/pom.xml +++ b/spring-security-client/spring-security-jsp-authorize/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-security-client/spring-security-jsp-config/pom.xml b/spring-security-client/spring-security-jsp-config/pom.xml index 067e6dff60..94511a2785 100644 --- a/spring-security-client/spring-security-jsp-config/pom.xml +++ b/spring-security-client/spring-security-jsp-config/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-security-client/spring-security-mvc/pom.xml b/spring-security-client/spring-security-mvc/pom.xml index b6a67d9c2c..f91a186897 100644 --- a/spring-security-client/spring-security-mvc/pom.xml +++ b/spring-security-client/spring-security-mvc/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-security-client/spring-security-thymeleaf-authentication/pom.xml b/spring-security-client/spring-security-thymeleaf-authentication/pom.xml index 9f819d11c5..1a5e9e61d4 100644 --- a/spring-security-client/spring-security-thymeleaf-authentication/pom.xml +++ b/spring-security-client/spring-security-thymeleaf-authentication/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-security-client/spring-security-thymeleaf-authorize/pom.xml b/spring-security-client/spring-security-thymeleaf-authorize/pom.xml index 5c13c34dea..964c57b71e 100644 --- a/spring-security-client/spring-security-thymeleaf-authorize/pom.xml +++ b/spring-security-client/spring-security-thymeleaf-authorize/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-security-client/spring-security-thymeleaf-config/pom.xml b/spring-security-client/spring-security-thymeleaf-config/pom.xml index cc43b2ffb1..42c6ee4f0f 100644 --- a/spring-security-client/spring-security-thymeleaf-config/pom.xml +++ b/spring-security-client/spring-security-thymeleaf-config/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-security-core/pom.xml b/spring-security-core/pom.xml index 519ee73296..a8ffce84b7 100644 --- a/spring-security-core/pom.xml +++ b/spring-security-core/pom.xml @@ -11,7 +11,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-security-custom-permission/README.MD b/spring-security-mvc-boot/README.MD similarity index 83% rename from spring-security-custom-permission/README.MD rename to spring-security-mvc-boot/README.MD index d59aea97b4..3e789dedad 100644 --- a/spring-security-custom-permission/README.MD +++ b/spring-security-mvc-boot/README.MD @@ -5,3 +5,4 @@ The "REST With Spring" Classes: http://github.learnspringsecurity.com - [A Custom Security Expression with Spring Security](http://www.baeldung.com/spring-security-create-new-custom-security-expression) - [Custom AccessDecisionVoters in Spring Security](http://www.baeldung.com/spring-security-custom-voter) - [Spring Security: Authentication with a Database-backed UserDetailsService](http://www.baeldung.com/spring-security-authentication-with-a-database) +- [Two Login Pages with Spring Security](http://www.baeldung.com/spring-security-two-login-pages) diff --git a/spring-security-custom-permission/WebContent/META-INF/MANIFEST.MF b/spring-security-mvc-boot/WebContent/META-INF/MANIFEST.MF similarity index 100% rename from spring-security-custom-permission/WebContent/META-INF/MANIFEST.MF rename to spring-security-mvc-boot/WebContent/META-INF/MANIFEST.MF diff --git a/spring-security-custom-permission/pom.xml b/spring-security-mvc-boot/pom.xml similarity index 93% rename from spring-security-custom-permission/pom.xml rename to spring-security-mvc-boot/pom.xml index 39dec2805f..591ededccf 100644 --- a/spring-security-custom-permission/pom.xml +++ b/spring-security-mvc-boot/pom.xml @@ -4,17 +4,17 @@ 4.0.0 com.baeldung - spring-security-custom-permission + spring-security-mvc-boot 0.0.1-SNAPSHOT war - spring-security-custom-permission - Spring Security custom permission + spring-security-mvc-boot + Spring Security MVC Boot org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE @@ -128,6 +128,12 @@ spring-security-taglibs ${spring-security-taglibs.version} + + + org.springframework.security + spring-security-core + ${spring-security-core.version} + javax.servlet.jsp.jstl @@ -280,11 +286,15 @@ org.baeldung.Application - UTF-8 + + + UTF-8 1.8 10.13.1.1 1.1.2 4.2.0.RELEASE + 4.2.0.RELEASE + 1.2 2.4.0 1.6.1 diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/Application.java b/spring-security-mvc-boot/src/main/java/org/baeldung/Application.java similarity index 74% rename from spring-security-custom-permission/src/main/java/org/baeldung/Application.java rename to spring-security-mvc-boot/src/main/java/org/baeldung/Application.java index 71d503e678..03de5897f5 100644 --- a/spring-security-custom-permission/src/main/java/org/baeldung/Application.java +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/Application.java @@ -9,7 +9,7 @@ import org.springframework.context.annotation.FilterType; @Configuration @EnableAutoConfiguration -@ComponentScan(excludeFilters = @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.baeldung.voter.*")) +@ComponentScan(excludeFilters = { @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.baeldung.voter.*"), @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.baeldung.multiplelogin.*") }) public class Application extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(Application.class, args); diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/config/MethodSecurityConfig.java b/spring-security-mvc-boot/src/main/java/org/baeldung/config/MethodSecurityConfig.java similarity index 100% rename from spring-security-custom-permission/src/main/java/org/baeldung/config/MethodSecurityConfig.java rename to spring-security-mvc-boot/src/main/java/org/baeldung/config/MethodSecurityConfig.java diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/config/MvcConfig.java b/spring-security-mvc-boot/src/main/java/org/baeldung/config/MvcConfig.java similarity index 100% rename from spring-security-custom-permission/src/main/java/org/baeldung/config/MvcConfig.java rename to spring-security-mvc-boot/src/main/java/org/baeldung/config/MvcConfig.java diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/config/PersistenceConfig.java b/spring-security-mvc-boot/src/main/java/org/baeldung/config/PersistenceConfig.java similarity index 100% rename from spring-security-custom-permission/src/main/java/org/baeldung/config/PersistenceConfig.java rename to spring-security-mvc-boot/src/main/java/org/baeldung/config/PersistenceConfig.java diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/config/SecurityConfig.java b/spring-security-mvc-boot/src/main/java/org/baeldung/config/SecurityConfig.java similarity index 100% rename from spring-security-custom-permission/src/main/java/org/baeldung/config/SecurityConfig.java rename to spring-security-mvc-boot/src/main/java/org/baeldung/config/SecurityConfig.java diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/multiplelogin/MultipleLoginApplication.java b/spring-security-mvc-boot/src/main/java/org/baeldung/multiplelogin/MultipleLoginApplication.java new file mode 100644 index 0000000000..836336eb71 --- /dev/null +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/multiplelogin/MultipleLoginApplication.java @@ -0,0 +1,22 @@ +package org.baeldung.multiplelogin; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.context.web.SpringBootServletInitializer; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; + +@SpringBootApplication +@ComponentScan("org.baeldung.multiplelogin") +public class MultipleLoginApplication extends SpringBootServletInitializer { + public static void main(String[] args) { + SpringApplication.run(MultipleLoginApplication.class, args); + } + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(MultipleLoginApplication.class); + } +} \ No newline at end of file diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/multiplelogin/MultipleLoginMvcConfig.java b/spring-security-mvc-boot/src/main/java/org/baeldung/multiplelogin/MultipleLoginMvcConfig.java new file mode 100644 index 0000000000..ec76be1909 --- /dev/null +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/multiplelogin/MultipleLoginMvcConfig.java @@ -0,0 +1,45 @@ +package org.baeldung.multiplelogin; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.view.InternalResourceViewResolver; +import org.springframework.web.servlet.view.JstlView; +import org.springframework.context.annotation.ComponentScan; + +@EnableWebMvc +@Configuration +@ComponentScan("org.baeldung.controller") +public class MultipleLoginMvcConfig extends WebMvcConfigurerAdapter { + + public MultipleLoginMvcConfig() { + super(); + } + + // API + + @Override + public void addViewControllers(final ViewControllerRegistry registry) { + super.addViewControllers(registry); + + registry.addViewController("/anonymous.html"); + + registry.addViewController("/login.html"); + registry.addViewController("/homepage.html"); + registry.addViewController("/console.html"); + } + + @Bean + public ViewResolver viewResolver() { + final InternalResourceViewResolver bean = new InternalResourceViewResolver(); + + bean.setViewClass(JstlView.class); + bean.setPrefix("/WEB-INF/view/"); + bean.setSuffix(".jsp"); + + return bean; + } +} \ No newline at end of file diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/multiplelogin/MultipleLoginSecurityConfig.java b/spring-security-mvc-boot/src/main/java/org/baeldung/multiplelogin/MultipleLoginSecurityConfig.java new file mode 100644 index 0000000000..8327e7e5d3 --- /dev/null +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/multiplelogin/MultipleLoginSecurityConfig.java @@ -0,0 +1,74 @@ +package org.baeldung.multiplelogin; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.authentication.TestingAuthenticationProvider; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.provisioning.InMemoryUserDetailsManager; + +@Configuration +@EnableWebSecurity +public class MultipleLoginSecurityConfig { + + @Bean + public UserDetailsService userDetailsService() throws Exception { + InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager(); + manager.createUser(User.withUsername("user").password("userPass").roles("USER").build()); + manager.createUser(User.withUsername("admin").password("adminPass").roles("ADMIN").build()); + return manager; + } + + @Configuration + @Order(1) + public static class App1ConfigurationAdapter extends WebSecurityConfigurerAdapter { + + public App1ConfigurationAdapter() { + super(); + } + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication().withUser("admin").password("admin").roles("ADMIN"); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.antMatcher("/admin*").authorizeRequests().anyRequest().hasRole("ADMIN") + // log in + .and().formLogin().loginPage("/loginAdmin").loginProcessingUrl("/admin_login").failureUrl("/loginAdmin?error=loginError").defaultSuccessUrl("/adminPage") + // logout + .and().logout().logoutUrl("/admin_logout").logoutSuccessUrl("/protectedLinks").deleteCookies("JSESSIONID").and().exceptionHandling().accessDeniedPage("/403").and().csrf().disable(); + } + } + + @Configuration + @Order(2) + public static class App2ConfigurationAdapter extends WebSecurityConfigurerAdapter { + + public App2ConfigurationAdapter() { + super(); + } + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication().withUser("user").password("user").roles("USER"); + } + + protected void configure(HttpSecurity http) throws Exception { + http.antMatcher("/user*").authorizeRequests().anyRequest().hasRole("USER") + // log in + .and().formLogin().loginPage("/loginUser").loginProcessingUrl("/user_login").failureUrl("/loginUser?error=loginError").defaultSuccessUrl("/userPage") + // logout + .and().logout().logoutUrl("/user_logout").logoutSuccessUrl("/protectedLinks").deleteCookies("JSESSIONID").and().exceptionHandling().accessDeniedPage("/403").and().csrf().disable(); + } + } + +} diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/multiplelogin/UsersController.java b/spring-security-mvc-boot/src/main/java/org/baeldung/multiplelogin/UsersController.java new file mode 100644 index 0000000000..0672a760af --- /dev/null +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/multiplelogin/UsersController.java @@ -0,0 +1,38 @@ +package org.baeldung.multiplelogin; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +public class UsersController { + + @RequestMapping("/protectedLinks") + public String getAnonymousPage() { + return "protectedLinks"; + } + + @RequestMapping("/userPage") + public String getUserPage() { + return "userPage"; + } + + @RequestMapping("/adminPage") + public String getAdminPage() { + return "adminPage"; + } + + @RequestMapping("/loginAdmin") + public String getAdminLoginPage() { + return "loginAdmin"; + } + + @RequestMapping("/loginUser") + public String getUserLoginPage() { + return "loginUser"; + } + + @RequestMapping("/403") + public String getAccessDeniedPage() { + return "403"; + } +} diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/persistence/SetupData.java b/spring-security-mvc-boot/src/main/java/org/baeldung/persistence/SetupData.java similarity index 100% rename from spring-security-custom-permission/src/main/java/org/baeldung/persistence/SetupData.java rename to spring-security-mvc-boot/src/main/java/org/baeldung/persistence/SetupData.java diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/persistence/dao/OrganizationRepository.java b/spring-security-mvc-boot/src/main/java/org/baeldung/persistence/dao/OrganizationRepository.java similarity index 100% rename from spring-security-custom-permission/src/main/java/org/baeldung/persistence/dao/OrganizationRepository.java rename to spring-security-mvc-boot/src/main/java/org/baeldung/persistence/dao/OrganizationRepository.java diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/persistence/dao/PrivilegeRepository.java b/spring-security-mvc-boot/src/main/java/org/baeldung/persistence/dao/PrivilegeRepository.java similarity index 100% rename from spring-security-custom-permission/src/main/java/org/baeldung/persistence/dao/PrivilegeRepository.java rename to spring-security-mvc-boot/src/main/java/org/baeldung/persistence/dao/PrivilegeRepository.java diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/persistence/dao/UserRepository.java b/spring-security-mvc-boot/src/main/java/org/baeldung/persistence/dao/UserRepository.java similarity index 100% rename from spring-security-custom-permission/src/main/java/org/baeldung/persistence/dao/UserRepository.java rename to spring-security-mvc-boot/src/main/java/org/baeldung/persistence/dao/UserRepository.java diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/persistence/model/Foo.java b/spring-security-mvc-boot/src/main/java/org/baeldung/persistence/model/Foo.java similarity index 100% rename from spring-security-custom-permission/src/main/java/org/baeldung/persistence/model/Foo.java rename to spring-security-mvc-boot/src/main/java/org/baeldung/persistence/model/Foo.java diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/persistence/model/Organization.java b/spring-security-mvc-boot/src/main/java/org/baeldung/persistence/model/Organization.java similarity index 100% rename from spring-security-custom-permission/src/main/java/org/baeldung/persistence/model/Organization.java rename to spring-security-mvc-boot/src/main/java/org/baeldung/persistence/model/Organization.java diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/persistence/model/Privilege.java b/spring-security-mvc-boot/src/main/java/org/baeldung/persistence/model/Privilege.java similarity index 100% rename from spring-security-custom-permission/src/main/java/org/baeldung/persistence/model/Privilege.java rename to spring-security-mvc-boot/src/main/java/org/baeldung/persistence/model/Privilege.java diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/persistence/model/User.java b/spring-security-mvc-boot/src/main/java/org/baeldung/persistence/model/User.java similarity index 100% rename from spring-security-custom-permission/src/main/java/org/baeldung/persistence/model/User.java rename to spring-security-mvc-boot/src/main/java/org/baeldung/persistence/model/User.java diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/security/CustomMethodSecurityExpressionHandler.java b/spring-security-mvc-boot/src/main/java/org/baeldung/security/CustomMethodSecurityExpressionHandler.java similarity index 100% rename from spring-security-custom-permission/src/main/java/org/baeldung/security/CustomMethodSecurityExpressionHandler.java rename to spring-security-mvc-boot/src/main/java/org/baeldung/security/CustomMethodSecurityExpressionHandler.java diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/security/CustomMethodSecurityExpressionRoot.java b/spring-security-mvc-boot/src/main/java/org/baeldung/security/CustomMethodSecurityExpressionRoot.java similarity index 100% rename from spring-security-custom-permission/src/main/java/org/baeldung/security/CustomMethodSecurityExpressionRoot.java rename to spring-security-mvc-boot/src/main/java/org/baeldung/security/CustomMethodSecurityExpressionRoot.java diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/security/CustomPermissionEvaluator.java b/spring-security-mvc-boot/src/main/java/org/baeldung/security/CustomPermissionEvaluator.java similarity index 100% rename from spring-security-custom-permission/src/main/java/org/baeldung/security/CustomPermissionEvaluator.java rename to spring-security-mvc-boot/src/main/java/org/baeldung/security/CustomPermissionEvaluator.java diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/security/MySecurityExpressionRoot.java b/spring-security-mvc-boot/src/main/java/org/baeldung/security/MySecurityExpressionRoot.java similarity index 100% rename from spring-security-custom-permission/src/main/java/org/baeldung/security/MySecurityExpressionRoot.java rename to spring-security-mvc-boot/src/main/java/org/baeldung/security/MySecurityExpressionRoot.java diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/security/MyUserDetailsService.java b/spring-security-mvc-boot/src/main/java/org/baeldung/security/MyUserDetailsService.java similarity index 100% rename from spring-security-custom-permission/src/main/java/org/baeldung/security/MyUserDetailsService.java rename to spring-security-mvc-boot/src/main/java/org/baeldung/security/MyUserDetailsService.java diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/security/MyUserPrincipal.java b/spring-security-mvc-boot/src/main/java/org/baeldung/security/MyUserPrincipal.java similarity index 100% rename from spring-security-custom-permission/src/main/java/org/baeldung/security/MyUserPrincipal.java rename to spring-security-mvc-boot/src/main/java/org/baeldung/security/MyUserPrincipal.java diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/voter/MinuteBasedVoter.java b/spring-security-mvc-boot/src/main/java/org/baeldung/voter/MinuteBasedVoter.java similarity index 100% rename from spring-security-custom-permission/src/main/java/org/baeldung/voter/MinuteBasedVoter.java rename to spring-security-mvc-boot/src/main/java/org/baeldung/voter/MinuteBasedVoter.java diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/voter/VoterApplication.java b/spring-security-mvc-boot/src/main/java/org/baeldung/voter/VoterApplication.java similarity index 89% rename from spring-security-custom-permission/src/main/java/org/baeldung/voter/VoterApplication.java rename to spring-security-mvc-boot/src/main/java/org/baeldung/voter/VoterApplication.java index c032a9634e..d2078e6115 100644 --- a/spring-security-custom-permission/src/main/java/org/baeldung/voter/VoterApplication.java +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/voter/VoterApplication.java @@ -4,7 +4,6 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.FilterType; @Configuration @EnableAutoConfiguration diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/voter/VoterMvcConfig.java b/spring-security-mvc-boot/src/main/java/org/baeldung/voter/VoterMvcConfig.java similarity index 100% rename from spring-security-custom-permission/src/main/java/org/baeldung/voter/VoterMvcConfig.java rename to spring-security-mvc-boot/src/main/java/org/baeldung/voter/VoterMvcConfig.java diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/voter/WebSecurityConfig.java b/spring-security-mvc-boot/src/main/java/org/baeldung/voter/WebSecurityConfig.java similarity index 98% rename from spring-security-custom-permission/src/main/java/org/baeldung/voter/WebSecurityConfig.java rename to spring-security-mvc-boot/src/main/java/org/baeldung/voter/WebSecurityConfig.java index 495567c7b2..06fb4d2316 100644 --- a/spring-security-custom-permission/src/main/java/org/baeldung/voter/WebSecurityConfig.java +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/voter/WebSecurityConfig.java @@ -18,8 +18,8 @@ import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import java.util.Arrays; import java.util.List; -//@Configuration -//@EnableWebSecurity +@Configuration +@EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/voter/XmlSecurityConfig.java b/spring-security-mvc-boot/src/main/java/org/baeldung/voter/XmlSecurityConfig.java similarity index 77% rename from spring-security-custom-permission/src/main/java/org/baeldung/voter/XmlSecurityConfig.java rename to spring-security-mvc-boot/src/main/java/org/baeldung/voter/XmlSecurityConfig.java index 124513d317..8041585f42 100644 --- a/spring-security-custom-permission/src/main/java/org/baeldung/voter/XmlSecurityConfig.java +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/voter/XmlSecurityConfig.java @@ -6,8 +6,8 @@ import org.springframework.context.annotation.ImportResource; /** * Created by ambrusadrianz on 09/10/2016. */ -@Configuration -@ImportResource({ "classpath:spring-security.xml" }) +// @Configuration +// @ImportResource({ "classpath:spring-security-custom-voter.xml" }) public class XmlSecurityConfig { public XmlSecurityConfig() { super(); diff --git a/spring-security-custom-permission/src/main/java/org/baeldung/web/MainController.java b/spring-security-mvc-boot/src/main/java/org/baeldung/web/MainController.java similarity index 100% rename from spring-security-custom-permission/src/main/java/org/baeldung/web/MainController.java rename to spring-security-mvc-boot/src/main/java/org/baeldung/web/MainController.java diff --git a/spring-security-custom-permission/src/main/resources/application.properties b/spring-security-mvc-boot/src/main/resources/application.properties similarity index 85% rename from spring-security-custom-permission/src/main/resources/application.properties rename to spring-security-mvc-boot/src/main/resources/application.properties index 9b140b3c69..d29b5f6bf1 100644 --- a/spring-security-custom-permission/src/main/resources/application.properties +++ b/spring-security-mvc-boot/src/main/resources/application.properties @@ -1,5 +1,5 @@ server.port=8082 -server.context-path=/spring-security-custom-permission +server.context-path=/spring-security-mvc-boot spring.datasource.driver-class-name=org.h2.Driver spring.datasource.url=jdbc:h2:mem:security_permission;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE spring.datasource.username=sa diff --git a/spring-security-custom-permission/src/main/resources/persistence-derby.properties b/spring-security-mvc-boot/src/main/resources/persistence-derby.properties similarity index 100% rename from spring-security-custom-permission/src/main/resources/persistence-derby.properties rename to spring-security-mvc-boot/src/main/resources/persistence-derby.properties diff --git a/spring-security-custom-permission/src/main/resources/spring-security.xml b/spring-security-mvc-boot/src/main/resources/spring-security-custom-voter.xml similarity index 98% rename from spring-security-custom-permission/src/main/resources/spring-security.xml rename to spring-security-mvc-boot/src/main/resources/spring-security-custom-voter.xml index 83bc14dda7..0b334a3694 100644 --- a/spring-security-custom-permission/src/main/resources/spring-security.xml +++ b/spring-security-mvc-boot/src/main/resources/spring-security-custom-voter.xml @@ -4,7 +4,7 @@ xmlns:beans="http://www.springframework.org/schema/beans" xsi:schemaLocation=" http://www.springframework.org/schema/security - http://www.springframework.org/schema/security/spring-security-4.2.xsd + http://www.springframework.org/schema/security/spring-security.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> diff --git a/spring-security-mvc-boot/src/main/resources/templates/403.html b/spring-security-mvc-boot/src/main/resources/templates/403.html new file mode 100644 index 0000000000..20550768cf --- /dev/null +++ b/spring-security-mvc-boot/src/main/resources/templates/403.html @@ -0,0 +1,10 @@ + + + + + + + +You do not have permission to view this page. + + \ No newline at end of file diff --git a/spring-security-mvc-boot/src/main/resources/templates/adminPage.html b/spring-security-mvc-boot/src/main/resources/templates/adminPage.html new file mode 100644 index 0000000000..13aff9b15a --- /dev/null +++ b/spring-security-mvc-boot/src/main/resources/templates/adminPage.html @@ -0,0 +1,13 @@ + + + + +Insert title here + + +Welcome admin! Logout + +

+Back to links + + \ No newline at end of file diff --git a/spring-security-custom-permission/src/main/resources/templates/index.html b/spring-security-mvc-boot/src/main/resources/templates/index.html similarity index 100% rename from spring-security-custom-permission/src/main/resources/templates/index.html rename to spring-security-mvc-boot/src/main/resources/templates/index.html diff --git a/spring-security-mvc-boot/src/main/resources/templates/login.html b/spring-security-mvc-boot/src/main/resources/templates/login.html new file mode 100644 index 0000000000..dd6bd04767 --- /dev/null +++ b/spring-security-mvc-boot/src/main/resources/templates/login.html @@ -0,0 +1,27 @@ + + + + +

Login

+ +
+ + + + + + + + + + + + + + +
User:
Password:
+ +
+ + + \ No newline at end of file diff --git a/spring-security-mvc-boot/src/main/resources/templates/loginAdmin.html b/spring-security-mvc-boot/src/main/resources/templates/loginAdmin.html new file mode 100644 index 0000000000..43d0e73233 --- /dev/null +++ b/spring-security-mvc-boot/src/main/resources/templates/loginAdmin.html @@ -0,0 +1,31 @@ + + + + +Insert title here + + + +

Admin login page

+
+ + + + + + + + + + + + + +
User:
Password:
+ +
+ +

Login failed!

+ + + \ No newline at end of file diff --git a/spring-security-mvc-boot/src/main/resources/templates/loginUser.html b/spring-security-mvc-boot/src/main/resources/templates/loginUser.html new file mode 100644 index 0000000000..bf4ddd48bc --- /dev/null +++ b/spring-security-mvc-boot/src/main/resources/templates/loginUser.html @@ -0,0 +1,30 @@ + + + + +Login + + + +

User login page

+ +
+ + + + + + + + + + + + +
User:
Password:
+ +
+

Login failed!

+ + + \ No newline at end of file diff --git a/spring-security-custom-permission/src/main/resources/templates/private.html b/spring-security-mvc-boot/src/main/resources/templates/private.html similarity index 100% rename from spring-security-custom-permission/src/main/resources/templates/private.html rename to spring-security-mvc-boot/src/main/resources/templates/private.html diff --git a/spring-security-mvc-boot/src/main/resources/templates/protectedLinks.html b/spring-security-mvc-boot/src/main/resources/templates/protectedLinks.html new file mode 100644 index 0000000000..1877464fe5 --- /dev/null +++ b/spring-security-mvc-boot/src/main/resources/templates/protectedLinks.html @@ -0,0 +1,13 @@ + + + + +Insert title here + + + +User page +
+Admin page + + \ No newline at end of file diff --git a/spring-security-mvc-boot/src/main/resources/templates/userPage.html b/spring-security-mvc-boot/src/main/resources/templates/userPage.html new file mode 100644 index 0000000000..894a225871 --- /dev/null +++ b/spring-security-mvc-boot/src/main/resources/templates/userPage.html @@ -0,0 +1,12 @@ + + + + +Insert title here + + +Welcome user! Logout +

+Back to links + + \ No newline at end of file diff --git a/spring-security-custom-permission/src/test/java/org/baeldung/web/CustomUserDetailsServiceIntegrationTest.java b/spring-security-mvc-boot/src/test/java/org/baeldung/web/CustomUserDetailsServiceIntegrationTest.java similarity index 100% rename from spring-security-custom-permission/src/test/java/org/baeldung/web/CustomUserDetailsServiceIntegrationTest.java rename to spring-security-mvc-boot/src/test/java/org/baeldung/web/CustomUserDetailsServiceIntegrationTest.java diff --git a/spring-security-custom-permission/src/test/java/org/baeldung/web/LiveTest.java b/spring-security-mvc-boot/src/test/java/org/baeldung/web/LiveTest.java similarity index 82% rename from spring-security-custom-permission/src/test/java/org/baeldung/web/LiveTest.java rename to spring-security-mvc-boot/src/test/java/org/baeldung/web/LiveTest.java index 47626b814a..d237ff2ec5 100644 --- a/spring-security-custom-permission/src/test/java/org/baeldung/web/LiveTest.java +++ b/spring-security-mvc-boot/src/test/java/org/baeldung/web/LiveTest.java @@ -14,24 +14,24 @@ import com.jayway.restassured.specification.RequestSpecification; public class LiveTest { - private final FormAuthConfig formAuthConfig = new FormAuthConfig("http://localhost:8082/spring-security-custom-permission/login", "username", "password"); + private final FormAuthConfig formAuthConfig = new FormAuthConfig("http://localhost:8082/spring-security-mvc-boot/login", "username", "password"); @Test public void givenUserWithReadPrivilegeAndHasPermission_whenGetFooById_thenOK() { - final Response response = givenAuth("john", "123").get("http://localhost:8082/spring-security-custom-permission/foos/1"); + final Response response = givenAuth("john", "123").get("http://localhost:8082/spring-security-mvc-boot/foos/1"); assertEquals(200, response.getStatusCode()); assertTrue(response.asString().contains("id")); } @Test public void givenUserWithNoWritePrivilegeAndHasPermission_whenPostFoo_thenForbidden() { - final Response response = givenAuth("john", "123").contentType(MediaType.APPLICATION_JSON_VALUE).body(new Foo("sample")).post("http://localhost:8082/spring-security-custom-permission/foos"); + final Response response = givenAuth("john", "123").contentType(MediaType.APPLICATION_JSON_VALUE).body(new Foo("sample")).post("http://localhost:8082/spring-security-mvc-boot/foos"); assertEquals(403, response.getStatusCode()); } @Test public void givenUserWithWritePrivilegeAndHasPermission_whenPostFoo_thenOk() { - final Response response = givenAuth("tom", "111").contentType(MediaType.APPLICATION_JSON_VALUE).body(new Foo("sample")).post("http://localhost:8082/spring-security-custom-permission/foos"); + final Response response = givenAuth("tom", "111").contentType(MediaType.APPLICATION_JSON_VALUE).body(new Foo("sample")).post("http://localhost:8082/spring-security-mvc-boot/foos"); assertEquals(201, response.getStatusCode()); assertTrue(response.asString().contains("id")); } @@ -40,14 +40,14 @@ public class LiveTest { @Test public void givenUserMemberInOrganization_whenGetOrganization_thenOK() { - final Response response = givenAuth("john", "123").get("http://localhost:8082/spring-security-custom-permission/organizations/1"); + final Response response = givenAuth("john", "123").get("http://localhost:8082/spring-security-mvc-boot/organizations/1"); assertEquals(200, response.getStatusCode()); assertTrue(response.asString().contains("id")); } @Test public void givenUserMemberNotInOrganization_whenGetOrganization_thenForbidden() { - final Response response = givenAuth("john", "123").get("http://localhost:8082/spring-security-custom-permission/organizations/2"); + final Response response = givenAuth("john", "123").get("http://localhost:8082/spring-security-mvc-boot/organizations/2"); assertEquals(403, response.getStatusCode()); } @@ -55,7 +55,7 @@ public class LiveTest { @Test public void givenDisabledSecurityExpression_whenGetFooByName_thenError() { - final Response response = givenAuth("john", "123").get("http://localhost:8082/spring-security-custom-permission/foos?name=sample"); + final Response response = givenAuth("john", "123").get("http://localhost:8082/spring-security-mvc-boot/foos?name=sample"); assertEquals(500, response.getStatusCode()); assertTrue(response.asString().contains("method hasAuthority() not allowed")); } diff --git a/spring-security-mvc-ldap/pom.xml b/spring-security-mvc-ldap/pom.xml index 242cc527ac..fc7941863e 100644 --- a/spring-security-mvc-ldap/pom.xml +++ b/spring-security-mvc-ldap/pom.xml @@ -10,7 +10,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-security-mvc-login/README.md b/spring-security-mvc-login/README.md index d1f6b884b1..35305112b4 100644 --- a/spring-security-mvc-login/README.md +++ b/spring-security-mvc-login/README.md @@ -10,6 +10,7 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com - [Spring Security Logout](http://www.baeldung.com/spring-security-logout) - [Spring Security Expressions – hasRole Example](http://www.baeldung.com/spring-security-expressions-basic) - [Spring HTTP/HTTPS Channel Security](http://www.baeldung.com/spring-channel-security-https) +- [Spring Security - Customize the 403 Forbidden/Access Denied Page](http://www.baeldung.com/spring-security-custom-access-denied-page) ### Build the Project ``` diff --git a/spring-security-mvc-login/pom.xml b/spring-security-mvc-login/pom.xml index 965f4fe1de..3809dc9f26 100644 --- a/spring-security-mvc-login/pom.xml +++ b/spring-security-mvc-login/pom.xml @@ -152,6 +152,19 @@ test
+ + org.springframework + spring-test + ${org.springframework.version} + test + + + org.springframework.security + spring-security-test + ${org.springframework.security.version} + test + +
@@ -222,7 +235,7 @@ - 4.3.5.RELEASE + 4.3.6.RELEASE 4.2.1.RELEASE diff --git a/spring-security-mvc-login/src/main/java/org/baeldung/controller/SecuredResourceController.java b/spring-security-mvc-login/src/main/java/org/baeldung/controller/SecuredResourceController.java new file mode 100644 index 0000000000..4b68eee983 --- /dev/null +++ b/spring-security-mvc-login/src/main/java/org/baeldung/controller/SecuredResourceController.java @@ -0,0 +1,17 @@ +package org.baeldung.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@Controller +public class SecuredResourceController { + + @RequestMapping("/secured") + public void secureResource(HttpServletRequest request, HttpServletResponse response) { + System.out.println("accessing secured resource"); + } + +} diff --git a/spring-security-mvc-login/src/main/java/org/baeldung/security/CustomAccessDeniedHandler.java b/spring-security-mvc-login/src/main/java/org/baeldung/security/CustomAccessDeniedHandler.java new file mode 100644 index 0000000000..ea4407c5c4 --- /dev/null +++ b/spring-security-mvc-login/src/main/java/org/baeldung/security/CustomAccessDeniedHandler.java @@ -0,0 +1,30 @@ +package org.baeldung.security; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.access.AccessDeniedHandler; + +public class CustomAccessDeniedHandler implements AccessDeniedHandler { + + public static final Logger LOG = Logger.getLogger(CustomAccessDeniedHandler.class); + + @Override + public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException exc) throws IOException, ServletException { + Authentication auth = SecurityContextHolder.getContext() + .getAuthentication(); + if (auth != null) { + LOG.warn("User: " + auth.getName() + " attempted to access the protected URL: " + request.getRequestURI()); + } + + response.sendRedirect(request.getContextPath() + "/accessDenied"); + } + +} diff --git a/spring-security-mvc-login/src/main/java/org/baeldung/security/RefererAuthenticationSuccessHandler.java b/spring-security-mvc-login/src/main/java/org/baeldung/security/RefererAuthenticationSuccessHandler.java new file mode 100644 index 0000000000..5b025d9fd1 --- /dev/null +++ b/spring-security-mvc-login/src/main/java/org/baeldung/security/RefererAuthenticationSuccessHandler.java @@ -0,0 +1,13 @@ +package org.baeldung.security; + +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; +import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; + +public class RefererAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler implements AuthenticationSuccessHandler { + + public RefererAuthenticationSuccessHandler() { + super(); + setUseReferer(true); + } + +} \ No newline at end of file diff --git a/spring-security-mvc-login/src/main/java/org/baeldung/spring/MvcConfig.java b/spring-security-mvc-login/src/main/java/org/baeldung/spring/MvcConfig.java index 02392df736..b59dbee0cf 100644 --- a/spring-security-mvc-login/src/main/java/org/baeldung/spring/MvcConfig.java +++ b/spring-security-mvc-login/src/main/java/org/baeldung/spring/MvcConfig.java @@ -28,6 +28,7 @@ public class MvcConfig extends WebMvcConfigurerAdapter { registry.addViewController("/login.html"); registry.addViewController("/homepage.html"); registry.addViewController("/admin/adminpage.html"); + registry.addViewController("/accessDenied"); } @Bean diff --git a/spring-security-mvc-login/src/main/java/org/baeldung/spring/RedirectionSecurityConfig.java b/spring-security-mvc-login/src/main/java/org/baeldung/spring/RedirectionSecurityConfig.java new file mode 100644 index 0000000000..b68e7eab50 --- /dev/null +++ b/spring-security-mvc-login/src/main/java/org/baeldung/spring/RedirectionSecurityConfig.java @@ -0,0 +1,44 @@ +package org.baeldung.spring; + +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; + +@Configuration +//@ImportResource({ "classpath:RedirectionWebSecurityConfig.xml" }) +@EnableWebSecurity +@Profile("!https") +public class RedirectionSecurityConfig extends WebSecurityConfigurerAdapter { + + public RedirectionSecurityConfig() { + super(); + } + + @Override + protected void configure(final AuthenticationManagerBuilder auth) throws Exception { + auth + .inMemoryAuthentication() + .withUser("user1") + .password("user1Pass") + .roles("USER"); + } + + @Override + protected void configure(final HttpSecurity http) throws Exception { + http + .authorizeRequests() + .antMatchers("/login*") + .permitAll() + .anyRequest() + .authenticated() + .and() + .formLogin() + .successHandler(new SavedRequestAwareAuthenticationSuccessHandler()); + //.successHandler(new RefererAuthenticationSuccessHandler()) + } + +} diff --git a/spring-security-mvc-login/src/main/java/org/baeldung/spring/SecSecurityConfig.java b/spring-security-mvc-login/src/main/java/org/baeldung/spring/SecSecurityConfig.java index ae41a037cd..7331d7bb18 100644 --- a/spring-security-mvc-login/src/main/java/org/baeldung/spring/SecSecurityConfig.java +++ b/spring-security-mvc-login/src/main/java/org/baeldung/spring/SecSecurityConfig.java @@ -1,5 +1,6 @@ package org.baeldung.spring; +import org.baeldung.security.CustomAccessDeniedHandler; import org.baeldung.security.CustomLogoutSuccessHandler; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -8,6 +9,7 @@ import org.springframework.security.config.annotation.authentication.builders.Au import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; @Configuration @@ -53,6 +55,9 @@ public class SecSecurityConfig extends WebSecurityConfigurerAdapter { .logoutUrl("/perform_logout") .deleteCookies("JSESSIONID") .logoutSuccessHandler(logoutSuccessHandler()); + //.and() + //.exceptionHandling().accessDeniedPage("/accessDenied"); + //.exceptionHandling().accessDeniedHandler(accessDeniedHandler()); // @formatter:on } @@ -60,5 +65,10 @@ public class SecSecurityConfig extends WebSecurityConfigurerAdapter { public LogoutSuccessHandler logoutSuccessHandler() { return new CustomLogoutSuccessHandler(); } + + @Bean + public AccessDeniedHandler accessDeniedHandler(){ + return new CustomAccessDeniedHandler(); + } } diff --git a/spring-security-mvc-login/src/main/resources/RedirectionWebSecurityConfig.xml b/spring-security-mvc-login/src/main/resources/RedirectionWebSecurityConfig.xml new file mode 100644 index 0000000000..231b5ab57e --- /dev/null +++ b/spring-security-mvc-login/src/main/resources/RedirectionWebSecurityConfig.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-security-mvc-login/src/main/resources/webSecurityConfig.xml b/spring-security-mvc-login/src/main/resources/webSecurityConfig.xml index 9c8fdea9ee..f0fa956934 100644 --- a/spring-security-mvc-login/src/main/resources/webSecurityConfig.xml +++ b/spring-security-mvc-login/src/main/resources/webSecurityConfig.xml @@ -19,10 +19,16 @@ always-use-default-target="true"/> + + + + + + diff --git a/spring-security-mvc-login/src/main/webapp/WEB-INF/view/accessDenied.jsp b/spring-security-mvc-login/src/main/webapp/WEB-INF/view/accessDenied.jsp new file mode 100644 index 0000000000..45820cf43d --- /dev/null +++ b/spring-security-mvc-login/src/main/webapp/WEB-INF/view/accessDenied.jsp @@ -0,0 +1,15 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> + + + + +Access Denied + + +

Sorry, you do not have permission to view this page.

+ +Click ">here to go back to the Homepage. + + \ No newline at end of file diff --git a/spring-security-mvc-login/src/main/webapp/WEB-INF/view/homepage.jsp b/spring-security-mvc-login/src/main/webapp/WEB-INF/view/homepage.jsp index 80f27f5466..c9d88cbc9b 100644 --- a/spring-security-mvc-login/src/main/webapp/WEB-INF/view/homepage.jsp +++ b/spring-security-mvc-login/src/main/webapp/WEB-INF/view/homepage.jsp @@ -4,21 +4,23 @@ -

This is the body of the sample view

+

This is the body of the sample view

- - This text is only visible to a user -
-
+ + This text is only visible to a user +

+ ">Restricted Admin Page +

+
- - This text is only visible to an admin -
+ + This text is only visible to an admin +
">Admin Page
-
+
+ + ">Logout - ">Logout - \ No newline at end of file diff --git a/spring-security-mvc-login/src/main/webapp/WEB-INF/web.xml b/spring-security-mvc-login/src/main/webapp/WEB-INF/web.xml index 0a0a340995..eef48ec9b3 100644 --- a/spring-security-mvc-login/src/main/webapp/WEB-INF/web.xml +++ b/spring-security-mvc-login/src/main/webapp/WEB-INF/web.xml @@ -43,8 +43,15 @@ /* + + 403 + /accessDenied + + + + \ No newline at end of file diff --git a/spring-security-mvc-login/src/test/java/org/baeldung/security/RedirectionSecurityIntegrationTest.java b/spring-security-mvc-login/src/test/java/org/baeldung/security/RedirectionSecurityIntegrationTest.java new file mode 100644 index 0000000000..1d7fae8b60 --- /dev/null +++ b/spring-security-mvc-login/src/test/java/org/baeldung/security/RedirectionSecurityIntegrationTest.java @@ -0,0 +1,94 @@ +package org.baeldung.security; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mock.web.MockHttpSession; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrlPattern; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({ "/RedirectionWebSecurityConfig.xml", "/mvc-servlet.xml" }) +@WebAppConfiguration +public class RedirectionSecurityIntegrationTest { + + @Autowired private WebApplicationContext context; + + @Autowired private UserDetailsService userDetailsService; + + private MockMvc mvc; + private UserDetails userDetails; + + @Before + public void setup() { + mvc = MockMvcBuilders + .webAppContextSetup(context) + .apply(springSecurity()) + .build(); + userDetails = userDetailsService.loadUserByUsername("user1"); + } + + @Test + public void givenSecuredResource_whenAccessUnauthenticated_thenRequiresAuthentication() throws Exception { + mvc + .perform(get("/secured")) + .andExpect(status().is3xxRedirection()) + .andExpect(redirectedUrlPattern("**/login")); + + } + + @Test + public void givenCredentials_whenAccessSecuredResource_thenSuccess() throws Exception { + mvc + .perform(get("/secured").with(user(userDetails))) + .andExpect(status().isOk()); + } + + @Test + public void givenAccessSecuredResource_whenAuthenticated_thenRedirectedBack() throws Exception { + MockHttpServletRequestBuilder securedResourceAccess = get("/secured"); + MvcResult unauthenticatedResult = mvc + .perform(securedResourceAccess) + .andExpect(status().is3xxRedirection()) + .andReturn(); + + MockHttpSession session = (MockHttpSession) unauthenticatedResult + .getRequest() + .getSession(); + String loginUrl = unauthenticatedResult + .getResponse() + .getRedirectedUrl(); + mvc + .perform(post(loginUrl) + .param("username", userDetails.getUsername()) + .param("password", userDetails.getPassword()) + .session(session) + .with(csrf())) + .andExpect(status().is3xxRedirection()) + .andExpect(redirectedUrlPattern("**/secured")) + .andReturn(); + + mvc + .perform(securedResourceAccess.session(session)) + .andExpect(status().isOk()); + + } + +} diff --git a/spring-security-mvc-login/src/test/resources/mvc-servlet.xml b/spring-security-mvc-login/src/test/resources/mvc-servlet.xml new file mode 100644 index 0000000000..aa5488b116 --- /dev/null +++ b/spring-security-mvc-login/src/test/resources/mvc-servlet.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/spring-security-openid/pom.xml b/spring-security-openid/pom.xml index 6e5db533d7..ff0b030bd2 100644 --- a/spring-security-openid/pom.xml +++ b/spring-security-openid/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-security-rest-basic-auth/pom.xml b/spring-security-rest-basic-auth/pom.xml index 7987eebb66..953cfd6b6b 100644 --- a/spring-security-rest-basic-auth/pom.xml +++ b/spring-security-rest-basic-auth/pom.xml @@ -342,8 +342,8 @@ - 4.3.4.RELEASE - 4.2.0.RELEASE + 4.3.6.RELEASE + 4.2.1.RELEASE 5.2.5.Final @@ -351,7 +351,7 @@ 4.4.5 - 4.5.2 + 4.5.3 1.7.21 diff --git a/spring-security-rest-basic-auth/src/main/java/org/baeldung/client/HttpComponentsClientHttpRequestFactoryBasicAuth.java b/spring-security-rest-basic-auth/src/main/java/org/baeldung/client/HttpComponentsClientHttpRequestFactoryBasicAuth.java new file mode 100644 index 0000000000..a2f51d343b --- /dev/null +++ b/spring-security-rest-basic-auth/src/main/java/org/baeldung/client/HttpComponentsClientHttpRequestFactoryBasicAuth.java @@ -0,0 +1,39 @@ +package org.baeldung.client; + +import java.net.URI; + +import org.apache.http.HttpHost; +import org.apache.http.client.AuthCache; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.impl.auth.BasicScheme; +import org.apache.http.impl.client.BasicAuthCache; +import org.apache.http.protocol.BasicHttpContext; +import org.apache.http.protocol.HttpContext; +import org.springframework.http.HttpMethod; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; + +public class HttpComponentsClientHttpRequestFactoryBasicAuth extends HttpComponentsClientHttpRequestFactory { + + HttpHost host; + + public HttpComponentsClientHttpRequestFactoryBasicAuth(HttpHost host) { + super(); + this.host = host; + } + + protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) { + return createHttpContext(); + } + + private HttpContext createHttpContext() { + + AuthCache authCache = new BasicAuthCache(); + + BasicScheme basicAuth = new BasicScheme(); + authCache.put(host, basicAuth); + + BasicHttpContext localcontext = new BasicHttpContext(); + localcontext.setAttribute(HttpClientContext.AUTH_CACHE, authCache); + return localcontext; + } +} \ No newline at end of file diff --git a/spring-security-rest-basic-auth/src/main/java/org/baeldung/client/RestTemplateFactory.java b/spring-security-rest-basic-auth/src/main/java/org/baeldung/client/RestTemplateFactory.java index 0cec0dc5c3..5e15648e9b 100644 --- a/spring-security-rest-basic-auth/src/main/java/org/baeldung/client/RestTemplateFactory.java +++ b/spring-security-rest-basic-auth/src/main/java/org/baeldung/client/RestTemplateFactory.java @@ -1,15 +1,10 @@ package org.baeldung.client; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.HttpHost; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.http.client.ClientHttpRequestFactory; -import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.http.client.support.BasicAuthorizationInterceptor; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; @@ -40,16 +35,10 @@ public class RestTemplateFactory implements FactoryBean, Initializ @Override public void afterPropertiesSet() { - final int timeout = 5; - - final RequestConfig config = RequestConfig.custom().setConnectTimeout(timeout * 1000).setConnectionRequestTimeout(timeout * 1000).setSocketTimeout(timeout * 1000).build(); - - final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials(new AuthScope("localhost", 8082, AuthScope.ANY_REALM), new UsernamePasswordCredentials("user1", "user1Pass")); - final CloseableHttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(config).setDefaultCredentialsProvider(credentialsProvider).build(); - - final ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(client); + HttpHost host = new HttpHost("localhost", 8082, "http"); + final ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactoryBasicAuth(host); restTemplate = new RestTemplate(requestFactory); + restTemplate.getInterceptors().add(new BasicAuthorizationInterceptor("user1", "user1Pass")); } } \ No newline at end of file diff --git a/spring-security-rest-custom/pom.xml b/spring-security-rest-custom/pom.xml index 4c2fdb4709..d421f8d7b4 100644 --- a/spring-security-rest-custom/pom.xml +++ b/spring-security-rest-custom/pom.xml @@ -10,7 +10,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-security-rest-full/pom.xml b/spring-security-rest-full/pom.xml index e9580d357d..43d14af5ea 100644 --- a/spring-security-rest-full/pom.xml +++ b/spring-security-rest-full/pom.xml @@ -10,7 +10,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-security-rest/README.md b/spring-security-rest/README.md index a1dfa32c6d..92b759a66a 100644 --- a/spring-security-rest/README.md +++ b/spring-security-rest/README.md @@ -13,3 +13,4 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com - [Custom Error Message Handling for REST API](http://www.baeldung.com/global-error-handler-in-a-spring-rest-api) - [An Intro to Spring HATEOAS](http://www.baeldung.com/spring-hateoas-tutorial) - [Spring Security Context Propagation with @Async](http://www.baeldung.com/spring-security-async-principal-propagation) +- [Servlet 3 Async Support with Spring MVC and Spring Security](http://www.baeldung.com/spring-mvc-async-security) diff --git a/spring-security-stormpath/pom.xml b/spring-security-stormpath/pom.xml new file mode 100644 index 0000000000..44c6595e64 --- /dev/null +++ b/spring-security-stormpath/pom.xml @@ -0,0 +1,85 @@ + + 4.0.0 + com.baeldung + spring-security-stormpath + war + 1.0-SNAPSHOT + spring-security-stormpath + http://maven.apache.org + + + + abhinabkanrar@gmail.com + Abhinab Kanrar + https://github.com/AbhinabKanrar + abhinabkanrar + + + + + UTF-8 + UTF-8 + 1.8 + + + + org.springframework.boot + spring-boot-starter-parent + 1.5.1.RELEASE + + + + + org.springframework.boot + spring-boot-starter-web + + + com.stormpath.spring + stormpath-default-spring-boot-starter + 1.5.4 + + + + + + spring-releases + Spring Releases + https://repo.spring.io/libs-release + + + + + spring-security-stormpath + + + src/main/resources + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + repackage + + + + + + + + diff --git a/spring-security-stormpath/src/main/java/com/baeldung/Application.java b/spring-security-stormpath/src/main/java/com/baeldung/Application.java new file mode 100644 index 0000000000..3d1409eaeb --- /dev/null +++ b/spring-security-stormpath/src/main/java/com/baeldung/Application.java @@ -0,0 +1,25 @@ +/** + * + */ +package com.baeldung; + +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author abhinab + * + */ +@SpringBootApplication +public class Application implements CommandLineRunner { + + @Override + public void run(String... args) throws Exception { + } + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/spring-security-stormpath/src/main/java/com/baeldung/security/SecurityConfiguration.java b/spring-security-stormpath/src/main/java/com/baeldung/security/SecurityConfiguration.java new file mode 100644 index 0000000000..5d75ecea8a --- /dev/null +++ b/spring-security-stormpath/src/main/java/com/baeldung/security/SecurityConfiguration.java @@ -0,0 +1,24 @@ +/** + * + */ +package com.baeldung.security; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +import static com.stormpath.spring.config.StormpathWebSecurityConfigurer.stormpath; + +/** + * @author abhinab + * + */ +@Configuration +public class SecurityConfiguration extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.apply(stormpath()); + } + +} diff --git a/spring-security-stormpath/src/main/resources/application.properties b/spring-security-stormpath/src/main/resources/application.properties new file mode 100644 index 0000000000..64a9ca456c --- /dev/null +++ b/spring-security-stormpath/src/main/resources/application.properties @@ -0,0 +1,6 @@ +security.basic.enabled = false + +stormpath.web.stormpathFilter.order = 0 + +stormpath.client.apiKey.id = 668HU0EOZQ7F4MT53ND2HSGBA +stormpath.client.apiKey.secret = RPTaYX07csTJR0AMKjM462KRdiP6q037kBWoDrBC3DI diff --git a/spring-security-x509/pom.xml b/spring-security-x509/pom.xml index 8596223cf4..b76bf4a23f 100644 --- a/spring-security-x509/pom.xml +++ b/spring-security-x509/pom.xml @@ -16,7 +16,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-session/pom.xml b/spring-session/pom.xml index c247d8a065..2c8b15a6eb 100644 --- a/spring-session/pom.xml +++ b/spring-session/pom.xml @@ -11,7 +11,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-sleuth/README.md b/spring-sleuth/README.md new file mode 100644 index 0000000000..47aa126939 --- /dev/null +++ b/spring-sleuth/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Spring Cloud Sleuth in a Monolith Application](http://www.baeldung.com/spring-cloud-sleuth-single-application) diff --git a/spring-social-login/pom.xml b/spring-social-login/pom.xml index 4369ec4e7c..1462611cfc 100644 --- a/spring-social-login/pom.xml +++ b/spring-social-login/pom.xml @@ -9,7 +9,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/spring-zuul/pom.xml b/spring-zuul/pom.xml index 2107892667..50b20b8791 100644 --- a/spring-zuul/pom.xml +++ b/spring-zuul/pom.xml @@ -10,7 +10,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 1.4.4.RELEASE diff --git a/static-analysis/README.md b/static-analysis/README.md new file mode 100644 index 0000000000..74cc64b90d --- /dev/null +++ b/static-analysis/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Introduction to PMD](http://www.baeldung.com/pmd) diff --git a/struts2/WebContent/WEB-INF/web.xml b/struts2/WebContent/WEB-INF/web.xml index 3aa1d1d173..8f1b55943c 100644 --- a/struts2/WebContent/WEB-INF/web.xml +++ b/struts2/WebContent/WEB-INF/web.xml @@ -1,16 +1,12 @@ - - - MyStrutsApp - - struts2 - org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter - - - - struts2 - /* - + + + struts + + struts2 + org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter + + + struts2 + /* + \ No newline at end of file diff --git a/struts2/pom.xml b/struts2/pom.xml index 9b9adeaf46..983f18903b 100644 --- a/struts2/pom.xml +++ b/struts2/pom.xml @@ -1,48 +1,66 @@ - 4.0.0 - com.baeldung - struts2 - 0.0.1-SNAPSHOT - war - struts2 - - - src - - - src - - **/*.java - - - - - - maven-compiler-plugin - 3.5.1 - - 1.8 - 1.8 - - - - maven-war-plugin - 3.0.0 - - WebContent - - - - - - - - - org.apache.struts - struts2-core - 2.5.5 - - - + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + com.baeldung + MyStrutsApp + 0.0.1-SNAPSHOT + war + struts + + src/main/java + + + src/main/resources + + + + + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + maven-war-plugin + 3.0.0 + + WebContent + + + + + + + junit + junit + 4.12 + + + org.apache.struts + struts2-core + 2.5.5 + + + org.apache.struts + struts2-junit-plugin + 2.5.5 + + + org.apache.struts + struts2-convention-plugin + 2.5.8 + + + javax.servlet + javax.servlet-api + 3.0.1 + + + org.springframework + spring-core + 4.3.6.RELEASE + + \ No newline at end of file diff --git a/struts2/src/com/baeldung/struts/CarAction.java b/struts2/src/main/java/com/baeldung/struts/CarAction.java similarity index 67% rename from struts2/src/com/baeldung/struts/CarAction.java rename to struts2/src/main/java/com/baeldung/struts/CarAction.java index a96aa440b6..478f3b4cc2 100644 --- a/struts2/src/com/baeldung/struts/CarAction.java +++ b/struts2/src/main/java/com/baeldung/struts/CarAction.java @@ -1,7 +1,13 @@ package com.baeldung.struts; -public class CarAction { +import org.apache.struts2.convention.annotation.Action; +import org.apache.struts2.convention.annotation.Namespace; +import org.apache.struts2.convention.annotation.Result; +@Namespace("/tutorial") +@Action("/car") +@Result(name = "success", location = "/result.jsp") +public class CarAction { private String carName; private String carMessage; private CarMessageService carMessageService = new CarMessageService(); diff --git a/struts2/src/com/baeldung/struts/CarMessageService.java b/struts2/src/main/java/com/baeldung/struts/CarMessageService.java similarity index 64% rename from struts2/src/com/baeldung/struts/CarMessageService.java rename to struts2/src/main/java/com/baeldung/struts/CarMessageService.java index fef9c1719d..34d3ca3d76 100644 --- a/struts2/src/com/baeldung/struts/CarMessageService.java +++ b/struts2/src/main/java/com/baeldung/struts/CarMessageService.java @@ -4,12 +4,15 @@ public class CarMessageService { public String getMessage(String carName) { System.out.println("inside getMessage()" + carName); - if (carName.equalsIgnoreCase("ferrari")) + if (carName.equalsIgnoreCase("ferrari")){ return "Ferrari Fan!"; - else if (carName.equalsIgnoreCase("bmw")) + } + else if (carName.equalsIgnoreCase("bmw")){ return "BMW Fan!"; - else + } + else{ return "please choose ferrari Or bmw"; + } } } diff --git a/struts2/src/struts.xml b/struts2/src/struts.xml deleted file mode 100644 index 1c117ac900..0000000000 --- a/struts2/src/struts.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - /result.jsp - - - \ No newline at end of file diff --git a/struts2/src/test/java/com/baeldung/struts/test/CarActionTest.java b/struts2/src/test/java/com/baeldung/struts/test/CarActionTest.java new file mode 100644 index 0000000000..64b640edfb --- /dev/null +++ b/struts2/src/test/java/com/baeldung/struts/test/CarActionTest.java @@ -0,0 +1,29 @@ +//package com.baeldung.struts.test; +// +//import org.apache.struts2.StrutsTestCase; +//import org.junit.Test; +// +//import com.baeldung.struts.CarAction; +//import com.opensymphony.xwork2.ActionProxy; +// +//public class CarActionTest extends StrutsTestCase { +// +// public void testgivenCarOptions_WhenferrariSelected_ThenShowMessage() throws Exception { +// request.setParameter("carName", "ferrari"); +// ActionProxy proxy = getActionProxy("/tutorial/car.action"); +// CarAction carAction = (CarAction) proxy.getAction(); +// String result = proxy.execute(); +// assertEquals(result, "success"); +// assertEquals(carAction.getCarMessage(), "Ferrari Fan!"); +// } +// +// public void testgivenCarOptions_WhenbmwSelected_ThenShowMessage() throws Exception { +// request.setParameter("carName", "bmw"); +// ActionProxy proxy = getActionProxy("/tutorial/car.action"); +// CarAction carAction = (CarAction) proxy.getAction(); +// String result = proxy.execute(); +// assertEquals(result, "success"); +// assertEquals(carAction.getCarMessage(), "BMW Fan!"); +// } +// +//} diff --git a/testng/pom.xml b/testng/pom.xml new file mode 100644 index 0000000000..272b1d316d --- /dev/null +++ b/testng/pom.xml @@ -0,0 +1,115 @@ + + + 4.0.0 + com.baeldung + testng + 0.1.0-SNAPSHOT + jar + testng + + + + + + + org.slf4j + slf4j-api + ${org.slf4j.version} + + + ch.qos.logback + logback-classic + ${logback.version} + + + + + + org.testng + testng + ${testng.version} + test + + + + + + testng + + + src/main/resources + true + + + + + src/main/resources + true + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + **/*IntegrationTest.java + **/*LongRunningUnitTest.java + **/*ManualTest.java + + true + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-dependencies + prepare-package + + copy-dependencies + + + ${project.build.directory}/libs + + + + + + + + + + + + 1.7.21 + 1.1.7 + + + 6.10 + + + 3.6.0 + 2.19.1 + + + + + \ No newline at end of file diff --git a/testng/src/test/java/baeldung/com/DependentTests.java b/testng/src/test/java/baeldung/com/DependentTests.java new file mode 100644 index 0000000000..b60f8a6c0d --- /dev/null +++ b/testng/src/test/java/baeldung/com/DependentTests.java @@ -0,0 +1,25 @@ +package baeldung.com; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.Assert; +import org.testng.annotations.Test; + +public class DependentTests { + + private static final Logger LOGGER = LoggerFactory.getLogger(DependentTests.class); + + private String email = "abc@qwe.com"; + + @Test + public void givenEmail_ifValid_thenTrue() { + boolean valid = email.contains("@"); + Assert.assertEquals(valid, true); + } + + @Test(dependsOnMethods = {"givenEmail_ifValid_thenTrue"}) + public void givenValidEmail_whenLoggedIn_thenTrue() { + LOGGER.info("Email {} valid >> logging in", email); + } +} + diff --git a/testng/src/test/java/baeldung/com/ParametrizedTests.java b/testng/src/test/java/baeldung/com/ParametrizedTests.java new file mode 100644 index 0000000000..d3813f5382 --- /dev/null +++ b/testng/src/test/java/baeldung/com/ParametrizedTests.java @@ -0,0 +1,77 @@ +package baeldung.com; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Parameters; +import org.testng.annotations.Test; + +public class ParametrizedTests { + + private static final Logger LOGGER = LoggerFactory.getLogger(ParametrizedTests.class); + + @Test + @Parameters({"value", "isEven"}) + public void givenNumberFromXML_ifEvenCheckOK_thenCorrect(int value, boolean isEven) { + Assert.assertEquals(isEven, value % 2 == 0); + } + + @DataProvider(name = "numbers") + public static Object[][] evenNumbers() { + return new Object[][]{{1, false}, {2, true}, {4, true}}; + } + + @Test(dataProvider = "numbers") + public void givenNumberFromDataProvider_ifEvenCheckOK_thenCorrect(Integer number, boolean expected) { + Assert.assertEquals(expected, number % 2 == 0); + } + + @Test(dataProvider = "numbersObject") + public void givenNumberObjectFromDataProvider_ifEvenCheckOK_thenCorrect(EvenNumber number) { + Assert.assertEquals(number.isEven(), number.getValue() % 2 == 0); + } + + @DataProvider(name = "numbersObject") + public Object[][] parameterProvider() { + return new Object[][]{{new EvenNumber(1, false)}, {new EvenNumber(2, true)}, {new EvenNumber(4, true),}}; + } + +} + + +class EvenNumber { + private int value; + private boolean isEven; + + public EvenNumber(int number, boolean isEven) { + this.value = number; + this.isEven = isEven; + } + + public int getValue() { + return value; + } + + public void setValue(int value) { + this.value = value; + } + + public boolean isEven() { + return isEven; + } + + public void setEven(boolean even) { + isEven = even; + } + + @Override + public String toString() { + return "EvenNumber{" + + "value=" + value + + ", isEven=" + isEven + + '}'; + } +} + + diff --git a/testng/src/test/java/baeldung/com/RegistrationTest.java b/testng/src/test/java/baeldung/com/RegistrationTest.java new file mode 100644 index 0000000000..ec551d9c27 --- /dev/null +++ b/testng/src/test/java/baeldung/com/RegistrationTest.java @@ -0,0 +1,14 @@ +package baeldung.com; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.Test; + +public class RegistrationTest { + private static final Logger LOGGER = LoggerFactory.getLogger(RegistrationTest.class); + + @Test + public void whenCalledFromSuite_thanOK() { + LOGGER.info("Registration successful"); + } +} diff --git a/testng/src/test/java/baeldung/com/SignInTest.java b/testng/src/test/java/baeldung/com/SignInTest.java new file mode 100644 index 0000000000..f0547374d1 --- /dev/null +++ b/testng/src/test/java/baeldung/com/SignInTest.java @@ -0,0 +1,14 @@ +package baeldung.com; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.Test; + +public class SignInTest { + private static final Logger LOGGER = LoggerFactory.getLogger(SignInTest.class); + + @Test + public void whenCalledFromSuite_thanOK() { + LOGGER.info("SignIn successful"); + } +} diff --git a/testng/src/test/java/baeldung/com/SummationServiceTest.java b/testng/src/test/java/baeldung/com/SummationServiceTest.java new file mode 100644 index 0000000000..f377a009df --- /dev/null +++ b/testng/src/test/java/baeldung/com/SummationServiceTest.java @@ -0,0 +1,98 @@ +package baeldung.com; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.Assert; +import org.testng.TestNG; +import org.testng.annotations.*; + +import java.util.ArrayList; +import java.util.List; + +public class SummationServiceTest extends TestNG { + private static final Logger LOGGER = LoggerFactory.getLogger(DependentTests.class); + + private List numbers; + + private int testCount = 0; + + @BeforeClass + public void initialize() { + numbers = new ArrayList<>(); + } + + @AfterClass + public void tearDown() { + numbers = null; + } + + @BeforeSuite(groups = "regression") + public void runBeforeRegressionSuite() { + numbers = new ArrayList<>(); + numbers.add(-11); + numbers.add(2); + } + + @AfterSuite(groups = "regression") + public void runAfterRegressionSuite() { + numbers = null; + } + + @BeforeGroups("negative_tests") + public void runBeforeEachNegativeGroup() { + numbers.clear(); + } + + @BeforeGroups("regression") + public void runBeforeEachRegressionGroup() { + numbers.add(-11); + numbers.add(2); + } + + @BeforeGroups("positive_tests") + public void runBeforeEachPositiveGroup() { + numbers.add(1); + numbers.add(2); + numbers.add(3); + } + + @AfterGroups("positive_tests,regression,negative_tests") + public void runAfterEachGroup() { + numbers.clear(); + } + + @BeforeMethod + public void runBeforeEachTest() { + testCount++; + } + + @AfterMethod + public void runAfterEachTest() { + + } + + + @Test(groups = "positive_tests", enabled = false) + public void givenNumbers_sumEquals_thenCorrect() { + int sum = numbers.stream().reduce(0, Integer::sum); + Assert.assertEquals(sum, 6); + } + + @Test(groups = "negative_tests") + public void givenEmptyList_sumEqualsZero_thenCorrect() { + int sum = numbers.stream().reduce(0, Integer::sum); + Assert.assertEquals(0, sum); + } + + @Test(groups = "regression") + public void givenNegativeNumber_sumLessthanZero_thenCorrect() { + int sum = numbers.stream().reduce(0, Integer::sum); + Assert.assertTrue(sum < 0); + } + + @Test(expectedExceptions = ArithmeticException.class) + public void givenNumber_whenThrowsException_thenCorrect() { + int i = 1 / 0; + } + +} diff --git a/testng/src/test/java/baeldung/com/TestGroup.java b/testng/src/test/java/baeldung/com/TestGroup.java new file mode 100644 index 0000000000..08bb5c996e --- /dev/null +++ b/testng/src/test/java/baeldung/com/TestGroup.java @@ -0,0 +1,44 @@ +package baeldung.com; + +import org.testng.annotations.AfterGroups; +import org.testng.annotations.BeforeGroups; +import org.testng.annotations.Test; + +public class TestGroup { + + @BeforeGroups("database") + public void setupDB() { + System.out.println("setupDB()"); + } + + @AfterGroups("database") + public void cleanDB() { + System.out.println("cleanDB()"); + } + + @Test(groups= "selenium-test") + public void runSelenium() { + System.out.println("runSelenium()"); + } + + @Test(groups= "selenium-test") + public void runSelenium1() { + System.out.println("runSelenium()1"); + } + + @Test(groups = "database") + public void testConnectOracle() { + System.out.println("testConnectOracle()"); + } + + @Test(groups = "database") + public void testConnectMsSQL() { + System.out.println("testConnectMsSQL"); + } + + @Test(dependsOnGroups = {"database","selenium-test"}) + public void runFinal() { + System.out.println("runFinal"); + } + +} \ No newline at end of file diff --git a/testng/src/test/java/baeldung/com/TimeOutTest.java b/testng/src/test/java/baeldung/com/TimeOutTest.java new file mode 100644 index 0000000000..d54a914e08 --- /dev/null +++ b/testng/src/test/java/baeldung/com/TimeOutTest.java @@ -0,0 +1,11 @@ +package baeldung.com; + +import org.testng.annotations.Test; + +public class TimeOutTest { + + @Test(timeOut = 1000, enabled = false) + public void givenExecution_takeMoreTime_thenFail() { + while (true) ; + } +} diff --git a/testng/src/test/resources/logback.xml b/testng/src/test/resources/logback.xml new file mode 100644 index 0000000000..e9ae1894a6 --- /dev/null +++ b/testng/src/test/resources/logback.xml @@ -0,0 +1,14 @@ + + + + + web - %date [%thread] %-5level %logger{36} - %message%n + + + + + + + + + \ No newline at end of file diff --git a/testng/src/test/resources/parametrized_test.xml b/testng/src/test/resources/parametrized_test.xml new file mode 100644 index 0000000000..932af30e4e --- /dev/null +++ b/testng/src/test/resources/parametrized_test.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/testng/src/test/resources/test_group.xml b/testng/src/test/resources/test_group.xml new file mode 100644 index 0000000000..26868375f2 --- /dev/null +++ b/testng/src/test/resources/test_group.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/testng/src/test/resources/test_setup.xml b/testng/src/test/resources/test_setup.xml new file mode 100644 index 0000000000..7d9708193e --- /dev/null +++ b/testng/src/test/resources/test_setup.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/testng/src/test/resources/test_suite.xml b/testng/src/test/resources/test_suite.xml new file mode 100644 index 0000000000..0fe5d1cc40 --- /dev/null +++ b/testng/src/test/resources/test_suite.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file