diff --git a/README.md b/README.md
index 7ee85384..e7e15e9c 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ Add Maven dependency to your project:
io.github.bobocode-breskulbring
- 1.1
+ 1.3
```
@@ -18,25 +18,40 @@ The reference [documentation](https://github.com/bobocode-breskul/bring/wiki) in
Here is a quick teaser of a complete Bring application in Java:
+Add BringContainer.run("org.example") to your main method, where "org.example" is your package name.
+
```java
-import com.breskul.bring.*;
+package org.example;
-@RestController
-@BringApplication
-public class Example {
+public class Main {
+ public static void main(String[] args) {
+ BringContainer.run("org.example");
+ }
+}
+```
- @RequestMapping("/")
- String home() {
- return "Hello World!";
- }
+Then create a new Controller with following code
- public static void main(String[] args) {
- BringApplication.run(Example.class, args);
- }
+```java
+package org.example;
+import io.github.bobocodebreskul.context.annotations.BringComponent;
+import io.github.bobocodebreskul.context.annotations.RestController;
+import io.github.bobocodebreskul.context.annotations.Get;
+
+@RestController("/hello")
+@BringComponent
+public class MyController {
+
+ @Get
+ public String getHello() {
+ return "Hello, world!";
+ }
}
```
+Now run the application and open http://localhost:8080/hello in your browser.
+
## Features
### HTTP Server
diff --git a/pom.xml b/pom.xml
index 395322c3..800f978b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -67,9 +67,18 @@
3.24.23.13.05.6.0
+ 10.1.16
+ 6.0.0
+ 2.16.0
+
+ jakarta.servlet
+ jakarta.servlet-api
+ ${jakarta.version}
+ provided
+ ch.qos.logbacklogback-classic
@@ -121,6 +130,22 @@
commons-lang3${apache.version}
+
+ org.apache.tomcat.embed
+ tomcat-embed-core
+ ${tomcat.version}
+
+
+ org.apache.tomcat.embed
+ tomcat-embed-jasper
+ ${tomcat.version}
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ ${jackson.version}
+
+
diff --git a/src/main/java/io/github/bobocodebreskul/MyController.java b/src/main/java/io/github/bobocodebreskul/MyController.java
new file mode 100644
index 00000000..fc1cb2e9
--- /dev/null
+++ b/src/main/java/io/github/bobocodebreskul/MyController.java
@@ -0,0 +1,15 @@
+package io.github.bobocodebreskul;
+
+import io.github.bobocodebreskul.context.annotations.BringComponent;
+import io.github.bobocodebreskul.context.annotations.RestController;
+import io.github.bobocodebreskul.context.annotations.Get;
+
+@RestController("/hello")
+@BringComponent
+public class MyController {
+
+ @Get
+ public String getHello() {
+ return "Hello, world!";
+ }
+}
diff --git a/src/main/java/io/github/bobocodebreskul/context/annotations/Get.java b/src/main/java/io/github/bobocodebreskul/context/annotations/Get.java
new file mode 100644
index 00000000..12ee05b6
--- /dev/null
+++ b/src/main/java/io/github/bobocodebreskul/context/annotations/Get.java
@@ -0,0 +1,31 @@
+package io.github.bobocodebreskul.context.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates that the annotated method serves as a GET request handler within a corresponding Controller.
+ * This annotation is intended for use in combination with the {@link RestController @RestController} annotation.
+ *
+ *
Usage:
+ *
+ * {@code
+ * @RestController("/sample")
+ * public class SampleController {
+ *
+ * @Get
+ * public YourClass doGet() {
+ * return new YourClass();
+ * }
+ * }}
+ *
+ *
+ * @see RestController
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Get {
+
+}
diff --git a/src/main/java/io/github/bobocodebreskul/context/annotations/Post.java b/src/main/java/io/github/bobocodebreskul/context/annotations/Post.java
new file mode 100644
index 00000000..c79f89e6
--- /dev/null
+++ b/src/main/java/io/github/bobocodebreskul/context/annotations/Post.java
@@ -0,0 +1,31 @@
+package io.github.bobocodebreskul.context.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates that the annotated method serves as a POST request handler within a corresponding Controller.
+ * This annotation is designed for use in conjunction with the {@link RestController @RestController} annotation.
+ *
+ *
Usage:
+ *
+ * {@code
+ * @RestController("/sample")
+ * public class SampleController {
+ *
+ * @Post
+ * public YourClass doPost() {
+ * return new YourClass();
+ * }
+ * }}
+ *
+ *
+ * @see RestController
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Post {
+
+}
diff --git a/src/main/java/io/github/bobocodebreskul/context/annotations/RestController.java b/src/main/java/io/github/bobocodebreskul/context/annotations/RestController.java
new file mode 100644
index 00000000..ca228e9c
--- /dev/null
+++ b/src/main/java/io/github/bobocodebreskul/context/annotations/RestController.java
@@ -0,0 +1,38 @@
+package io.github.bobocodebreskul.context.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates that the annotated class is a RestController, allowing it to be scanned by the ApplicationContext.
+ * A required request mapping value must be specified. Additionally, HTTP Request Method annotations such as
+ * {@link Get} or {@link Post} should be added to the methods within the controller. The response from these
+ * methods will be automatically converted to JSON and sent as the client's response.
+ *
+ *
Usage:
+ *
+ * {@code
+ * @RestController("/sample")
+ * public class SampleController {
+ *
+ * @Get
+ * public YourClass doGet() {
+ * return new YourClass();
+ * }
+ * }}
+ *
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface RestController {
+
+ /**
+ * Represents path to the resource.
+ *
+ * @return the filled controller path
+ */
+ String value();
+}
+
diff --git a/src/main/java/io/github/bobocodebreskul/context/registry/BringContainer.java b/src/main/java/io/github/bobocodebreskul/context/registry/BringContainer.java
index 71ed98d9..fe0139d1 100644
--- a/src/main/java/io/github/bobocodebreskul/context/registry/BringContainer.java
+++ b/src/main/java/io/github/bobocodebreskul/context/registry/BringContainer.java
@@ -5,19 +5,21 @@
import io.github.bobocodebreskul.context.exception.FeatureNotImplementedException;
import io.github.bobocodebreskul.context.exception.InstanceCreationException;
import io.github.bobocodebreskul.context.exception.NoSuchBeanDefinitionException;
-import io.github.bobocodebreskul.context.exception.NotFoundDeclaredConstructorException;
import io.github.bobocodebreskul.context.scan.RecursiveClassPathAnnotatedBeanScanner;
import io.github.bobocodebreskul.context.scan.utils.ScanUtilsImpl;
+import io.github.bobocodebreskul.server.TomcatServer;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import lombok.extern.slf4j.Slf4j;
/**
- * Implementation of the {@link ObjectFactory} as Bring beans container. Creates and holds
- * all found and registered beans.
+ * Implementation of the {@link ObjectFactory} as Bring beans container. Creates and holds all found
+ * and registered beans.
*
* @author Ruslan Hladchenko
* @author Roman Pryshchepa
@@ -36,18 +38,29 @@ public BringContainer(BeanDefinitionRegistry definitionRegistry) {
}
/**
- * Collect all bean definitions by specified scan packages and build container to create and hold all found beans.
+ * Collect all bean definitions by specified scan packages and build container to create and hold
+ * all found beans.
*
* @param scanPackages packages where to search beans
* @return created beans container
*/
public static BringContainer run(String... scanPackages) {
BeanDefinitionRegistry definitionRegistry = new SimpleBeanDefinitionRegistry();
- AnnotatedBeanDefinitionReader beanDefinitionReader = new AnnotatedBeanDefinitionReader(definitionRegistry);
- RecursiveClassPathAnnotatedBeanScanner scanner = new RecursiveClassPathAnnotatedBeanScanner(new ScanUtilsImpl(), beanDefinitionReader);
+ AnnotatedBeanDefinitionReader beanDefinitionReader = new AnnotatedBeanDefinitionReader(
+ definitionRegistry);
+ RecursiveClassPathAnnotatedBeanScanner scanner = new RecursiveClassPathAnnotatedBeanScanner(
+ new ScanUtilsImpl(), beanDefinitionReader);
scanner.scan(scanPackages);
- return new BringContainer(definitionRegistry);
+ BringContainer container = new BringContainer(definitionRegistry);
+
+ definitionRegistry.getBeanDefinitions()
+ .forEach(beanDefinition -> container.getBean(beanDefinition.getName()));
+
+ ExecutorService executor = Executors.newFixedThreadPool(1);
+ executor.submit(() -> TomcatServer.run(container));
+
+ return container;
}
// TODO: 1. add dependency injection by @Autowired field
@@ -60,7 +73,9 @@ public Object getBean(String name) {
BeanDefinition beanDefinition = definitionRegistry.getBeanDefinition(name);
if (beanDefinition == null) {
- throw new NoSuchBeanDefinitionException("BeanDefinition for bean with name %s is not found! Check configuration and register this bean".formatted(name));
+ throw new NoSuchBeanDefinitionException(
+ "BeanDefinition for bean with name %s is not found! Check configuration and register this bean".formatted(
+ name));
}
Class> beanClass = beanDefinition.getBeanClass();
try {
@@ -90,4 +105,8 @@ public Object getBean(String name) {
public Object getBean(Class> clazz) {
throw new UnsupportedOperationException();
}
+
+ public List