diff --git a/jee-kotlin/README.md b/jee-kotlin/README.md new file mode 100644 index 0000000000..7d843af9ea --- /dev/null +++ b/jee-kotlin/README.md @@ -0,0 +1 @@ +### Relevant Articles: diff --git a/jee-kotlin/pom.xml b/jee-kotlin/pom.xml new file mode 100644 index 0000000000..963c03d0df --- /dev/null +++ b/jee-kotlin/pom.xml @@ -0,0 +1,289 @@ + + + + 4.0.0 + + parent-modules + com.baeldung + 1.0.0-SNAPSHOT + + + jee-kotlin + jee-kotlin + war + + + UTF-8 + false + 8.0 + + + 1.3.41 + official + true + + + 8.2.1.Final + 3.2.3 + 2.21.0 + 3.1.1 + + 1.4.1.Final + 2.0.1.Final + 1.0.0.Alpha4 + + 4.12 + 3.8.0.Final + 2.9.8 + 3.1.3 + + + + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + ${kotlin.version} + + + org.jetbrains.kotlin + kotlin-test-junit + ${kotlin.version} + test + + + junit + junit + ${junit.version} + test + + + javax + javaee-api + ${javaee-api.version} + jar + provided + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson.version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + test + + + org.jboss.arquillian.junit + arquillian-junit-container + ${arquillian_core.version} + test + + + org.jboss.shrinkwrap.resolver + shrinkwrap-resolver-depchain + ${shrinkwrap.version} + pom + test + + + org.jboss.arquillian.extension + arquillian-rest-client-impl-jersey + ${arquillian-rest-client.version} + + + org.jetbrains.kotlin + kotlin-test + ${kotlin.version} + test + + + + + src/main/kotlin + src/test/kotlin + + + + org.jetbrains.kotlin + kotlin-maven-plugin + ${kotlin.version} + + + compile + compile + + compile + + + + test-compile + test-compile + + test-compile + + + + + 1.8 + + + + + org.apache.maven.plugins + maven-war-plugin + ${mvn-war-plugin.version} + + webapp + kotlin + + + + org.apache.maven.plugins + maven-compiler-plugin + + + default-compile + none + + + default-testCompile + none + + + compile + compile + + compile + + + + testCompile + test-compile + + testCompile + + + + + + + + + + + org.jboss.arquillian + arquillian-bom + ${arquillian_core.version} + import + pom + + + org.jboss.arquillian.extension + arquillian-drone-bom + ${arquillian-drone-bom.version} + pom + import + + + + + + + wildfly-managed-arquillian + + true + + + + org.wildfly + wildfly-arquillian-container-embedded + ${wildfly.version} + + + org.wildfly + wildfly-embedded + ${wildfly.version} + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + ${maven-dependency-plugin.version} + + + unpack + process-test-classes + + unpack + + + + + org.wildfly + wildfly-dist + ${wildfly.version} + zip + false + target + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + always + + org.jboss.logmanager.LogManager + ${project.basedir}/target/wildfly-${wildfly.version} + ${project.basedir}/target/wildfly-${wildfly.version}/modules + + false + + + + + + + wildfly-remote-arquillian + + + org.jboss.resteasy + resteasy-client + ${resteasy.version} + test + + + org.jboss.resteasy + resteasy-jaxb-provider + ${resteasy.version} + test + + + org.jboss.resteasy + resteasy-json-p-provider + ${resteasy.version} + test + + + org.wildfly.arquillian + wildfly-arquillian-container-remote + 2.2.0.Final + test + + + + + diff --git a/jee-kotlin/src/main/kotlin/com/baeldung/jeekotlin/entity/Student.kt b/jee-kotlin/src/main/kotlin/com/baeldung/jeekotlin/entity/Student.kt new file mode 100644 index 0000000000..07f54a39d1 --- /dev/null +++ b/jee-kotlin/src/main/kotlin/com/baeldung/jeekotlin/entity/Student.kt @@ -0,0 +1,22 @@ +package com.baeldung.jeekotlin.entity + +import com.fasterxml.jackson.annotation.JsonProperty +import javax.persistence.* + +@Entity +data class Student constructor ( + + @SequenceGenerator(name = "student_id_seq", sequenceName = "student_id_seq", allocationSize = 1) + @GeneratedValue(generator = "student_id_seq", strategy = GenerationType.SEQUENCE) + @Id + var id: Long?, + + var firstName: String, + + var lastName: String + +) { + constructor() : this(null, "", "") + + constructor(firstName: String, lastName: String) : this(null, firstName, lastName) +} diff --git a/jee-kotlin/src/main/kotlin/com/baeldung/jeekotlin/rest/ApplicationConfig.kt b/jee-kotlin/src/main/kotlin/com/baeldung/jeekotlin/rest/ApplicationConfig.kt new file mode 100644 index 0000000000..12511ed320 --- /dev/null +++ b/jee-kotlin/src/main/kotlin/com/baeldung/jeekotlin/rest/ApplicationConfig.kt @@ -0,0 +1,9 @@ +package com.baeldung.jeekotlin.rest + +import javax.ws.rs.ApplicationPath +import javax.ws.rs.core.Application + +@ApplicationPath("/") +class ApplicationConfig : Application() { + override fun getClasses() = setOf(StudentResource::class.java) +} diff --git a/jee-kotlin/src/main/kotlin/com/baeldung/jeekotlin/rest/StudentResource.kt b/jee-kotlin/src/main/kotlin/com/baeldung/jeekotlin/rest/StudentResource.kt new file mode 100644 index 0000000000..91fa3ff62b --- /dev/null +++ b/jee-kotlin/src/main/kotlin/com/baeldung/jeekotlin/rest/StudentResource.kt @@ -0,0 +1,42 @@ +package com.baeldung.jeekotlin.rest + +import com.baeldung.jeekotlin.entity.Student +import com.baeldung.jeekotlin.service.StudentService +import javax.inject.Inject +import javax.ws.rs.* +import javax.ws.rs.core.MediaType +import javax.ws.rs.core.Response + +@Path("/student") +open class StudentResource { + + @Inject + private lateinit var service: StudentService + + @POST + open fun create(student: Student): Response { + service.create(student) + return Response.ok().build() + } + + @GET + @Path("/{id}") + open fun read(@PathParam("id") id: Long): Response { + val student = service.read(id) + return Response.ok(student, MediaType.APPLICATION_JSON_TYPE).build() + } + + @PUT + open fun update(student: Student): Response { + service.update(student) + return Response.ok(student, MediaType.APPLICATION_JSON_TYPE).build() + } + + @DELETE + @Path("/{id}") + open fun delete(@PathParam("id") id: Long): Response { + service.delete(id) + return Response.noContent().build() + } + +} \ No newline at end of file diff --git a/jee-kotlin/src/main/kotlin/com/baeldung/jeekotlin/service/StudentService.kt b/jee-kotlin/src/main/kotlin/com/baeldung/jeekotlin/service/StudentService.kt new file mode 100644 index 0000000000..3977a45e96 --- /dev/null +++ b/jee-kotlin/src/main/kotlin/com/baeldung/jeekotlin/service/StudentService.kt @@ -0,0 +1,21 @@ +package com.baeldung.jeekotlin.service + +import com.baeldung.jeekotlin.entity.Student +import javax.ejb.Stateless +import javax.persistence.EntityManager +import javax.persistence.PersistenceContext + +@Stateless +open class StudentService { + + @PersistenceContext + private lateinit var entityManager: EntityManager + + open fun create(student: Student) = entityManager.persist(student) + + open fun read(id: Long): Student? = entityManager.find(Student::class.java, id) + + open fun update(student: Student) = entityManager.merge(student) + + open fun delete(id: Long) = entityManager.remove(read(id)) +} \ No newline at end of file diff --git a/jee-kotlin/src/main/resources/META-INF/persistence.xml b/jee-kotlin/src/main/resources/META-INF/persistence.xml new file mode 100644 index 0000000000..daac86868b --- /dev/null +++ b/jee-kotlin/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,18 @@ + + + + + + org.hibernate.jpa.HibernatePersistenceProvider + + java:jboss/datasources/ExampleDS + + com.enpy.entity.Student + + + + + + + + diff --git a/jee-kotlin/src/main/webapp/WEB-INF/beans.xml b/jee-kotlin/src/main/webapp/WEB-INF/beans.xml new file mode 100644 index 0000000000..ae0f4bf2ee --- /dev/null +++ b/jee-kotlin/src/main/webapp/WEB-INF/beans.xml @@ -0,0 +1,8 @@ + + + \ No newline at end of file diff --git a/jee-kotlin/src/test/kotlin/com/baeldung/jeekotlin/StudentResourceIntegrationTest.java b/jee-kotlin/src/test/kotlin/com/baeldung/jeekotlin/StudentResourceIntegrationTest.java new file mode 100644 index 0000000000..b91b47cb1f --- /dev/null +++ b/jee-kotlin/src/test/kotlin/com/baeldung/jeekotlin/StudentResourceIntegrationTest.java @@ -0,0 +1,108 @@ +package com.baeldung.jeekotlin; + +import com.baeldung.jeekotlin.entity.Student; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.Filters; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.shrinkwrap.resolver.api.maven.Maven; +import org.junit.Test; +import org.junit.runner.RunWith; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.net.URISyntaxException; +import java.net.URL; + +import static org.junit.Assert.assertEquals; + +@RunWith(Arquillian.class) +public class StudentResourceIntegrationTest { + + @Deployment + public static WebArchive createDeployment() { + JavaArchive[] kotlinRuntime = Maven.configureResolver() + .workOffline() + .withMavenCentralRepo(true) + .withClassPathResolution(true) + .loadPomFromFile("pom.xml") + .resolve("org.jetbrains.kotlin:kotlin-stdlib") + .withTransitivity() + .as(JavaArchive.class); + + return ShrinkWrap.create(WebArchive.class, "kotlin.war") + .addPackages(true, Filters.exclude(".*Test*"), + "com.baeldung.jeekotlin" + ) + .addAsLibraries(kotlinRuntime) + .addAsResource("META-INF/persistence.xml") + .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml"); + } + + @Test + @RunAsClient + public void when_post__then_return_ok(@ArquillianResource URL url) throws URISyntaxException, JsonProcessingException { + String student = new ObjectMapper().writeValueAsString(new Student("firstName", "lastName")); + WebTarget webTarget = ClientBuilder.newClient().target(url.toURI()); + + Response response = webTarget + .path("/student") + .request(MediaType.APPLICATION_JSON) + .post(Entity.json(student)); + + assertEquals(200, response.getStatus()); + } + + @Test + @RunAsClient + public void when_get__then_return_ok(@ArquillianResource URL url) throws URISyntaxException, JsonProcessingException { + WebTarget webTarget = ClientBuilder.newClient().target(url.toURI()); + + Response response = webTarget + .path("/student/1") + .request(MediaType.APPLICATION_JSON) + .get(); + + assertEquals(200, response.getStatus()); + } + + @Test + @RunAsClient + public void when_put__then_return_ok(@ArquillianResource URL url) throws URISyntaxException, JsonProcessingException { + Student student = new Student("firstName", "lastName"); + student.setId(1L); + String studentJson = new ObjectMapper().writeValueAsString(student); + WebTarget webTarget = ClientBuilder.newClient().target(url.toURI()); + + Response response = webTarget + .path("/student") + .request(MediaType.APPLICATION_JSON) + .put(Entity.json(studentJson)); + + assertEquals(200, response.getStatus()); + } + + @Test + @RunAsClient + public void when_delete__then_return_ok(@ArquillianResource URL url) throws URISyntaxException, JsonProcessingException { + WebTarget webTarget = ClientBuilder.newClient().target(url.toURI()); + + Response response = webTarget + .path("/student/1") + .request() + .delete(); + + assertEquals(204, response.getStatus()); + } + +} \ No newline at end of file diff --git a/jee-kotlin/src/test/resources/arquillian.xml b/jee-kotlin/src/test/resources/arquillian.xml new file mode 100644 index 0000000000..5e6d7c54e8 --- /dev/null +++ b/jee-kotlin/src/test/resources/arquillian.xml @@ -0,0 +1,22 @@ + + + + + target/wildfly-8.2.1.Final + standalone.xml + true + 9990 + + + + + + 127.0.0.1 + 9990 + admin + pass + true + + + + \ No newline at end of file