diff --git a/core-java/README.md b/core-java/README.md
index 3cefb5820d..cc3097006c 100644
--- a/core-java/README.md
+++ b/core-java/README.md
@@ -140,3 +140,4 @@
- [Introduction to SSL in Java](http://www.baeldung.com/java-ssl)
- [Java KeyStore API](http://www.baeldung.com/java-keystore)
- [Using Java Assertions](http://www.baeldung.com/java-assert)
+- [Guide to Java Clock Class](http://www.baeldung.com/java-clock)
diff --git a/core-java/src/main/java/com/baeldung/stringisnumeric/IsNumericDriver.java b/core-java/src/main/java/com/baeldung/stringisnumeric/IsNumericDriver.java
index 3dc2b6632a..c0a6edae50 100644
--- a/core-java/src/main/java/com/baeldung/stringisnumeric/IsNumericDriver.java
+++ b/core-java/src/main/java/com/baeldung/stringisnumeric/IsNumericDriver.java
@@ -1,12 +1,13 @@
package com.baeldung.stringisnumeric;
-import static com.baeldung.designpatterns.util.LogerUtil.LOG;
+import org.apache.log4j.Logger;
public class IsNumericDriver {
private static IsNumeric isNumeric;
-
+ private static Logger LOG = Logger.getLogger(IsNumericDriver.class);
static {
isNumeric =new IsNumeric();
+
}
public static void main(String[] args) {
diff --git a/libraries/pom.xml b/libraries/pom.xml
index f4bf994a58..678ba3279c 100644
--- a/libraries/pom.xml
+++ b/libraries/pom.xml
@@ -680,6 +680,12 @@
${unirest.version}
+
+
+ io.javalin
+ javalin
+ 1.6.0
+
io.atlassian.fugue
diff --git a/libraries/src/main/java/com/baeldung/javalin/JavalinApp.java b/libraries/src/main/java/com/baeldung/javalin/JavalinApp.java
new file mode 100644
index 0000000000..33d2c7083f
--- /dev/null
+++ b/libraries/src/main/java/com/baeldung/javalin/JavalinApp.java
@@ -0,0 +1,16 @@
+package com.baeldung.javalin;
+
+import com.baeldung.javalin.User.UserController;
+import io.javalin.Javalin;
+
+public class JavalinApp {
+ public static void main(String[] args) {
+ Javalin app = Javalin.create()
+ .port(7000)
+ .start();
+
+ app.get("/hello", ctx -> ctx.html("Hello, Javalin!"));
+ app.get("/users", UserController.fetchAllUsernames);
+ app.get("/users/:id", UserController.fetchById);
+ }
+}
diff --git a/libraries/src/main/java/com/baeldung/javalin/User/User.java b/libraries/src/main/java/com/baeldung/javalin/User/User.java
new file mode 100644
index 0000000000..09f710453b
--- /dev/null
+++ b/libraries/src/main/java/com/baeldung/javalin/User/User.java
@@ -0,0 +1,11 @@
+package com.baeldung.javalin.User;
+
+public class User {
+ public final int id;
+ public final String name;
+
+ public User(int id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+}
diff --git a/libraries/src/main/java/com/baeldung/javalin/User/UserController.java b/libraries/src/main/java/com/baeldung/javalin/User/UserController.java
new file mode 100644
index 0000000000..fd713606cf
--- /dev/null
+++ b/libraries/src/main/java/com/baeldung/javalin/User/UserController.java
@@ -0,0 +1,24 @@
+package com.baeldung.javalin.User;
+
+import io.javalin.Handler;
+
+import java.util.Objects;
+
+public class UserController {
+ public static Handler fetchAllUsernames = ctx -> {
+ UserDao dao = UserDao.instance();
+ Iterable allUsers = dao.getAllUsernames();
+ ctx.json(allUsers);
+ };
+
+ public static Handler fetchById = ctx -> {
+ int id = Integer.parseInt(Objects.requireNonNull(ctx.param("id")));
+ UserDao dao = UserDao.instance();
+ User user = dao.getUserById(id);
+ if (user == null) {
+ ctx.html("Not Found");
+ } else {
+ ctx.json(user);
+ }
+ };
+}
diff --git a/libraries/src/main/java/com/baeldung/javalin/User/UserDao.java b/libraries/src/main/java/com/baeldung/javalin/User/UserDao.java
new file mode 100644
index 0000000000..1cbf3012a8
--- /dev/null
+++ b/libraries/src/main/java/com/baeldung/javalin/User/UserDao.java
@@ -0,0 +1,33 @@
+package com.baeldung.javalin.User;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+class UserDao {
+
+ private final List users = Arrays.asList(
+ new User(0, "Steve Rogers"),
+ new User(1, "Tony Stark"),
+ new User(2, "Carol Danvers")
+ );
+
+ private static UserDao userDao = null;
+
+ private UserDao() {
+ }
+
+ static UserDao instance() {
+ if (userDao == null) {
+ userDao = new UserDao();
+ }
+ return userDao;
+ }
+
+ Optional getUserById(int id) { return users.stream().filter(u -> u.id == id).findFirst(); }
+
+ Iterable getAllUsernames() {
+ return users.stream().map(user -> user.name).collect(Collectors.toList());
+ }
+}
diff --git a/spring-rest/src/main/java/com/baeldung/propertyeditor/PropertyEditorApplication.java b/spring-rest/src/main/java/com/baeldung/propertyeditor/PropertyEditorApplication.java
new file mode 100644
index 0000000000..f98648c6b2
--- /dev/null
+++ b/spring-rest/src/main/java/com/baeldung/propertyeditor/PropertyEditorApplication.java
@@ -0,0 +1,12 @@
+package com.baeldung.propertyeditor;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class PropertyEditorApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(PropertyEditorApplication.class, args);
+ }
+}
diff --git a/spring-rest/src/main/java/com/baeldung/propertyeditor/PropertyEditorRestController.java b/spring-rest/src/main/java/com/baeldung/propertyeditor/PropertyEditorRestController.java
new file mode 100644
index 0000000000..02edc96cf6
--- /dev/null
+++ b/spring-rest/src/main/java/com/baeldung/propertyeditor/PropertyEditorRestController.java
@@ -0,0 +1,36 @@
+package com.baeldung.propertyeditor;
+
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.WebDataBinder;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.InitBinder;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.baeldung.propertyeditor.creditcard.CreditCard;
+import com.baeldung.propertyeditor.exotictype.editor.CustomExoticTypeEditor;
+import com.baeldung.propertyeditor.exotictype.model.ExoticType;
+
+@RestController
+@RequestMapping(value = "/property-editor")
+public class PropertyEditorRestController {
+
+ @GetMapping(value = "/credit-card/{card-no}",
+ produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ public CreditCard parseCreditCardNumber(@PathVariable("card-no") CreditCard creditCard) {
+ return creditCard;
+ }
+
+ @GetMapping(value = "/exotic-type/{value}",
+ produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+ public ExoticType parseExoticType(@PathVariable("value") ExoticType exoticType) {
+ return exoticType;
+ }
+
+ @InitBinder
+ public void initBinder(WebDataBinder binder) {
+ binder.registerCustomEditor(ExoticType.class, new CustomExoticTypeEditor());
+ }
+
+}
diff --git a/spring-rest/src/main/java/com/baeldung/propertyeditor/creditcard/CreditCard.java b/spring-rest/src/main/java/com/baeldung/propertyeditor/creditcard/CreditCard.java
new file mode 100644
index 0000000000..f3adfb5d9f
--- /dev/null
+++ b/spring-rest/src/main/java/com/baeldung/propertyeditor/creditcard/CreditCard.java
@@ -0,0 +1,41 @@
+package com.baeldung.propertyeditor.creditcard;
+
+public class CreditCard {
+
+ private String rawCardNumber;
+
+ private Integer bankIdNo;
+
+ private Integer accountNo;
+
+ private Integer checkCode;
+
+ public String getRawCardNumber() {
+ return rawCardNumber;
+ }
+ public void setRawCardNumber(String rawCardNumber) {
+ this.rawCardNumber = rawCardNumber;
+ }
+
+ public Integer getBankIdNo() {
+ return bankIdNo;
+ }
+ public void setBankIdNo(Integer bankIdNo) {
+ this.bankIdNo = bankIdNo;
+ }
+
+ public Integer getAccountNo() {
+ return accountNo;
+ }
+ public void setAccountNo(Integer accountNo) {
+ this.accountNo = accountNo;
+ }
+
+ public Integer getCheckCode() {
+ return checkCode;
+ }
+ public void setCheckCode(Integer checkCode) {
+ this.checkCode = checkCode;
+ }
+
+}
diff --git a/spring-rest/src/main/java/com/baeldung/propertyeditor/creditcard/CreditCardEditor.java b/spring-rest/src/main/java/com/baeldung/propertyeditor/creditcard/CreditCardEditor.java
new file mode 100644
index 0000000000..d413afee85
--- /dev/null
+++ b/spring-rest/src/main/java/com/baeldung/propertyeditor/creditcard/CreditCardEditor.java
@@ -0,0 +1,39 @@
+package com.baeldung.propertyeditor.creditcard;
+
+import java.beans.PropertyEditorSupport;
+
+import org.springframework.util.StringUtils;
+
+public class CreditCardEditor extends PropertyEditorSupport {
+
+ @Override
+ public String getAsText() {
+ CreditCard creditCard = (CreditCard) getValue();
+
+ return creditCard == null ? "" : creditCard.getRawCardNumber();
+ }
+
+ @Override
+ public void setAsText(String text) throws IllegalArgumentException {
+ if (StringUtils.isEmpty(text)) {
+ setValue(null);
+ } else {
+ CreditCard creditCard = new CreditCard();
+ creditCard.setRawCardNumber(text);
+
+ String cardNo = text.replaceAll("-", "");
+ if (cardNo.length() != 16)
+ throw new IllegalArgumentException("Credit card format should be xxxx-xxxx-xxxx-xxxx");
+
+ try {
+ creditCard.setBankIdNo( Integer.valueOf(cardNo.substring(0, 6)) );
+ creditCard.setAccountNo( Integer.valueOf(cardNo.substring(6, cardNo.length() - 1)) );
+ creditCard.setCheckCode( Integer.valueOf(cardNo.substring(cardNo.length() - 1)) );
+ } catch (NumberFormatException nfe) {
+ throw new IllegalArgumentException(nfe);
+ }
+
+ setValue(creditCard);
+ }
+ }
+}
diff --git a/spring-rest/src/main/java/com/baeldung/propertyeditor/exotictype/editor/CustomExoticTypeEditor.java b/spring-rest/src/main/java/com/baeldung/propertyeditor/exotictype/editor/CustomExoticTypeEditor.java
new file mode 100644
index 0000000000..08dbceae3d
--- /dev/null
+++ b/spring-rest/src/main/java/com/baeldung/propertyeditor/exotictype/editor/CustomExoticTypeEditor.java
@@ -0,0 +1,23 @@
+package com.baeldung.propertyeditor.exotictype.editor;
+
+import java.beans.PropertyEditorSupport;
+
+import com.baeldung.propertyeditor.exotictype.model.ExoticType;
+
+public class CustomExoticTypeEditor extends PropertyEditorSupport {
+
+ @Override
+ public String getAsText() {
+ ExoticType exoticType = (ExoticType) getValue();
+
+ return exoticType == null ? "" : exoticType.getName();
+ }
+
+ @Override
+ public void setAsText(String text) throws IllegalArgumentException {
+ ExoticType exoticType = new ExoticType();
+ exoticType.setName(text.toUpperCase());
+
+ setValue(exoticType);
+ }
+}
diff --git a/spring-rest/src/main/java/com/baeldung/propertyeditor/exotictype/model/ExoticType.java b/spring-rest/src/main/java/com/baeldung/propertyeditor/exotictype/model/ExoticType.java
new file mode 100644
index 0000000000..95ba95643d
--- /dev/null
+++ b/spring-rest/src/main/java/com/baeldung/propertyeditor/exotictype/model/ExoticType.java
@@ -0,0 +1,14 @@
+package com.baeldung.propertyeditor.exotictype.model;
+
+public class ExoticType {
+
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+
+}
diff --git a/spring-rest/src/test/java/com/baeldung/propertyeditor/creditcard/CreditCardEditorTest.java b/spring-rest/src/test/java/com/baeldung/propertyeditor/creditcard/CreditCardEditorTest.java
new file mode 100644
index 0000000000..e87adbc712
--- /dev/null
+++ b/spring-rest/src/test/java/com/baeldung/propertyeditor/creditcard/CreditCardEditorTest.java
@@ -0,0 +1,44 @@
+package com.baeldung.propertyeditor.creditcard;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import com.baeldung.propertyeditor.creditcard.CreditCard;
+import com.baeldung.propertyeditor.creditcard.CreditCardEditor;
+
+@RunWith(MockitoJUnitRunner.class)
+public class CreditCardEditorTest {
+
+ private CreditCardEditor creditCardEditor;
+
+ @Before
+ public void setup() {
+ creditCardEditor = new CreditCardEditor();
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void whenInvalidCardNoWithLessDigits_thenThrowsException() {
+ creditCardEditor.setAsText("123-123-123-123");
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void whenInvalidCardNoWithNonDigits_thenThrowsException() {
+ creditCardEditor.setAsText("1234-1234-xxxx-yyyy");
+ }
+
+ @Test
+ public void whenCardNoWithNonDigits_parseCreditCard() {
+ creditCardEditor.setAsText("1234-5678-9123-4560");
+
+ CreditCard creditCard = (CreditCard) creditCardEditor.getValue();
+ Assert.assertNotNull(creditCard);
+
+ Assert.assertEquals(123456, creditCard.getBankIdNo().intValue());
+ Assert.assertEquals(789123456, creditCard.getAccountNo().intValue());
+ Assert.assertEquals(0, creditCard.getCheckCode().intValue());
+ }
+
+}