Last active
June 19, 2022 16:38
-
-
Save deepakshrma/b7ef7d9a9ccf94ff6150bd1ddd9cdd8b to your computer and use it in GitHub Desktop.
Working with XML Serialization and Response in Java and Kotlin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Working with XML Serialization and Response in Java and Kotlin | |
## PreRequisite | |
- Java 17+ | |
- [Optional] Kotlin 1.6+, Few examples will be in Kotlin | |
- [Optional] IntelliJ CE, You can use your preferred IDE | |
## Blogs Post | |
[Deepak Vishwakarma's Medium](https://medium.com/@deepak-v) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// imports | |
@SpringBootApplication | |
@RestController | |
public class XmlDemoApplication { | |
public static void main(String args[]) { | |
SpringApplication.run(XmlDemoApplication.class, args); | |
} | |
@RequestMapping( | |
value = "/xml", | |
method = RequestMethod.GET, | |
produces = {"application/xml"} | |
) | |
public String xml( | |
@RequestParam(value = "name", defaultValue = "John Doe") | |
String name | |
) { | |
return String.format("<name>%s</name>", name); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Imports | |
@SpringBootApplication | |
@RestController | |
public class XmlDemoApplication { | |
public static void main(String args[]) { | |
SpringApplication.run(XmlDemoApplication.class, args); | |
} | |
@RequestMapping(value = "/xml", method = RequestMethod.POST, produces = {"application/xml"}) | |
public String xml(@RequestBody() Person person) { | |
return """ | |
<?xml version="1.0" encoding="UTF-8" ?> | |
<Person> | |
<age>%s</age> | |
<name>%s</name> | |
<company>%s</company> | |
<email>%s</email> | |
<address> | |
<street>%s</street> | |
<city>%s</city> | |
<state>%s</state> | |
<zip>%s</zip> | |
</address> | |
</Person> | |
""".formatted( | |
person.age, person.name, person.company, person.email, | |
person.address.street, person.address.city, | |
person.address.state, person.address.zip | |
); | |
} | |
} | |
class Person { | |
public int age; | |
public String name; | |
public String company; | |
public String email; | |
public Address address; | |
} | |
class Address { | |
public String street; | |
public String city; | |
public String state; | |
public int zip; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// XmlDemoApplication.java | |
@SpringBootApplication | |
@RestController | |
public class XmlDemoApplication { | |
static Mustache mustache = new DefaultMustacheFactory().compile("person-response.mustache"); | |
@RequestMapping( | |
value = "/template", | |
method = RequestMethod.POST, | |
produces = {"application/xml"} | |
) | |
public String template(@RequestBody() Person person) throws IOException { | |
StringWriter writer = new StringWriter(); | |
mustache.execute(writer, person).flush(); | |
return writer.toString(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@SpringBootApplication | |
@RestController | |
public class XmlDemoApplication { | |
@RequestMapping( | |
value = "/serialize", | |
method = RequestMethod.POST, | |
produces = {"application/xml"} | |
) | |
public Person serialize(@RequestBody() Person person) throws IOException { | |
person.name = "[Updated] %s".formatted(person.name); | |
return person; | |
} | |
} | |
@JacksonXmlRootElement | |
@JsonRootName("person") | |
class Person { | |
public int age; | |
public String name; | |
public String company; | |
public String email; | |
public Address address; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@SpringBootApplication | |
@RestController | |
@RequestMapping(path = ["/kt/"]) | |
class XmlDemoKt { | |
@RequestMapping(value = ["/xml"], method = [RequestMethod.GET], produces = ["application/xml"]) | |
fun xml( | |
@RequestParam(value = "name", defaultValue = "John Doe") name: String? | |
) = String.format("<name>%s</name>", name) | |
} | |
fun main(args: Array<String>) { | |
runApplication<XmlDemoKt>(*args) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@SpringBootApplication | |
@RestController | |
@RequestMapping(path = ["/kt/"]) | |
class XmlDemoKt { | |
@RequestMapping(value = ["/xml"], method = [RequestMethod.POST], produces = ["application/xml"]) | |
fun xml( | |
@RequestBody p: PersonKt | |
): String { | |
return """ | |
<?xml version="1.0" encoding="UTF-8" ?> | |
<Person> | |
<age>${p.age}</age> | |
<name>${p.name}</name> | |
<company>${p.company}</company> | |
<email>${p.email}</email> | |
<address> | |
<street>${p.address.street}</street> | |
<city>${p.address.city}</city> | |
<state>${p.address.state}</state> | |
<zip>${p.address.zip}</zip> | |
</address> | |
</Person> | |
""".trimIndent() | |
} | |
} | |
fun main(args: Array<String>) { | |
runApplication<XmlDemoKt>(*args) | |
} | |
data class PersonKt( | |
val age: Long, | |
val name: String, | |
val company: String, | |
val email: String, | |
val address: AddressKt | |
) | |
data class AddressKt( | |
val street: String, | |
val city: String, | |
val state: String, | |
val zip: Long | |
) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// XmlDemoKt.kt | |
@SpringBootApplication | |
@RestController | |
@RequestMapping(path = ["/kt/"]) | |
class XmlDemoKt { | |
@RequestMapping( | |
value = ["/template"], | |
method = [RequestMethod.POST], | |
produces = ["application/xml"] | |
) | |
fun template(@RequestBody p: PersonKt): String { | |
val writer = StringWriter() | |
mustache.execute(writer, p).flush() | |
return writer.toString() | |
} | |
companion object { | |
val mustache = DefaultMustacheFactory() | |
.compile("person-response.mustache") | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@SpringBootApplication | |
@RestController | |
@RequestMapping(path = ["/kt/"]) | |
class XmlDemoKt { | |
@Bean | |
@Primary | |
fun objectMapper() = ObjectMapper() .registerModule(kotlinModule()) | |
@RequestMapping( | |
value = ["/serialize"], | |
method = [RequestMethod.POST], | |
produces = ["application/xml"] | |
) | |
fun serialize(@RequestBody p: PersonKt): PersonKt { | |
return p.copy(name = "[Updated] ${p.name}") | |
} | |
} | |
@JacksonXmlRootElement | |
@JsonRootName("person") | |
data class PersonKt( | |
val age: Long, | |
val name: String, | |
val company: String, | |
val email: String, | |
val address: AddressKt | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8" ?> | |
<Person> | |
<age>{{age}}</age> | |
<name>{{name}}</name> | |
<company>{{company}}</company> | |
<email>{{email}}</email> | |
<address> | |
<street>{{address.street}}</street> | |
<city>{{address.city}}</city> | |
<state>{{address.state}}</state> | |
<zip>{{address.zip}}</zip> | |
</address> | |
</Person> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> | |
<modelVersion>4.0.0</modelVersion> | |
<parent> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-starter-parent</artifactId> | |
<version>2.7.0</version> | |
<relativePath/> <!-- lookup parent from repository --> | |
</parent> | |
<groupId>dev.dechipher.xml</groupId> | |
<artifactId>xml-demo</artifactId> | |
<version>0.0.1-SNAPSHOT</version> | |
<name>xml-demo</name> | |
<description>Demo app for xml writing in Kotlin and Java</description> | |
<properties> | |
<java.version>17</java.version> | |
<kotlin.version>1.6.21</kotlin.version> | |
</properties> | |
<dependencies> | |
<dependency> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-starter-web</artifactId> | |
</dependency> | |
<dependency> | |
<groupId>com.fasterxml.jackson.module</groupId> | |
<artifactId>jackson-module-kotlin</artifactId> | |
</dependency> | |
<dependency> | |
<groupId>com.fasterxml.jackson.dataformat</groupId> | |
<artifactId>jackson-dataformat-xml</artifactId> | |
</dependency> | |
<dependency> | |
<groupId>org.jetbrains.kotlin</groupId> | |
<artifactId>kotlin-reflect</artifactId> | |
</dependency> | |
<dependency> | |
<groupId>org.jetbrains.kotlin</groupId> | |
<artifactId>kotlin-stdlib-jdk8</artifactId> | |
</dependency> | |
<dependency> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-starter-test</artifactId> | |
<scope>test</scope> | |
</dependency> | |
<dependency> | |
<groupId>com.github.spullara.mustache.java</groupId> | |
<artifactId>compiler</artifactId> | |
<version>0.9.4</version> | |
</dependency> | |
<dependency> | |
<groupId>dev.dechipher.xml</groupId> | |
<artifactId>xml-demo</artifactId> | |
<version>0.0.1-SNAPSHOT</version> | |
</dependency> | |
</dependencies> | |
<build> | |
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory> | |
<testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory> | |
<plugins> | |
<plugin> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-maven-plugin</artifactId> | |
</plugin> | |
<plugin> | |
<groupId>org.jetbrains.kotlin</groupId> | |
<artifactId>kotlin-maven-plugin</artifactId> | |
<configuration> | |
<args> | |
<arg>-Xjsr305=strict</arg> | |
</args> | |
<compilerPlugins> | |
<plugin>spring</plugin> | |
</compilerPlugins> | |
</configuration> | |
<dependencies> | |
<dependency> | |
<groupId>org.jetbrains.kotlin</groupId> | |
<artifactId>kotlin-maven-allopen</artifactId> | |
<version>${kotlin.version}</version> | |
</dependency> | |
</dependencies> | |
</plugin> | |
</plugins> | |
</build> | |
</project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package dev.dechipher.xml.xmldemo; | |
import com.fasterxml.jackson.annotation.JsonRootName; | |
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; | |
import com.github.mustachejava.DefaultMustacheFactory; | |
import com.github.mustachejava.Mustache; | |
import org.springframework.boot.SpringApplication; | |
import org.springframework.boot.autoconfigure.SpringBootApplication; | |
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.RestController; | |
import java.io.IOException; | |
import java.io.StringWriter; | |
// Imports | |
@SpringBootApplication | |
@RestController | |
public class XmlDemoApplication { | |
static Mustache mustache = new DefaultMustacheFactory().compile("person-response.mustache"); | |
public static void main(String args[]) { | |
SpringApplication.run(XmlDemoApplication.class, args); | |
} | |
@RequestMapping( | |
value = "/serialize", | |
method = RequestMethod.POST, | |
produces = {"application/xml"} | |
) | |
public Person serialize(@RequestBody() Person person) throws IOException { | |
person.name = "[Updated] %s".formatted(person.name); | |
return person; | |
} | |
@RequestMapping( | |
value = "/template", | |
method = RequestMethod.POST, | |
produces = {"application/xml"} | |
) | |
public String template(@RequestBody() Person person) throws IOException { | |
StringWriter writer = new StringWriter(); | |
mustache.execute(writer, person).flush(); | |
return writer.toString(); | |
} | |
@RequestMapping(value = "/xml", method = RequestMethod.POST, produces = {"application/xml"}) | |
public String xml(@RequestBody() Person person) { | |
return """ | |
<?xml version="1.0" encoding="UTF-8" ?> | |
<Person> | |
<age>%s</age> | |
<name>%s</name> | |
<company>%s</company> | |
<email>%s</email> | |
<address> | |
<street>%s</street> | |
<city>%s</city> | |
<state>%s</state> | |
<zip>%s</zip> | |
</address> | |
</Person> | |
""".formatted( | |
person.age, person.name, person.company, person.email, | |
person.address.street, person.address.city, | |
person.address.state, person.address.zip | |
); | |
} | |
} | |
@JacksonXmlRootElement | |
@JsonRootName("person") | |
class Person { | |
public int age; | |
public String name; | |
public String company; | |
public String email; | |
public Address address; | |
} | |
class Address { | |
public String street; | |
public String city; | |
public String state; | |
public int zip; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package dev.dechipher.xml.xmldemo | |
import com.fasterxml.jackson.annotation.JsonRootName | |
import com.fasterxml.jackson.databind.ObjectMapper | |
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement | |
import com.fasterxml.jackson.module.kotlin.kotlinModule | |
import com.github.mustachejava.DefaultMustacheFactory | |
import org.springframework.boot.autoconfigure.SpringBootApplication | |
import org.springframework.boot.runApplication | |
import org.springframework.context.annotation.Bean | |
import org.springframework.context.annotation.Primary | |
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.RestController | |
import java.io.StringWriter | |
@SpringBootApplication | |
@RestController | |
@RequestMapping(path = ["/kt/"]) | |
class XmlDemoKt { | |
companion object { | |
val mustache = DefaultMustacheFactory() | |
.compile("person-response.mustache") | |
} | |
@Bean | |
@Primary | |
fun objectMapper() = ObjectMapper().registerModule(kotlinModule()) | |
@RequestMapping( | |
value = ["/serialize"], | |
method = [RequestMethod.POST], | |
produces = ["application/xml"] | |
) | |
fun serialize(@RequestBody p: PersonKt): PersonKt { | |
return p.copy(name = "[Updated] ${p.name}") | |
} | |
@RequestMapping( | |
value = ["/template"], | |
method = [RequestMethod.POST], | |
produces = ["application/xml"] | |
) | |
fun template(@RequestBody p: PersonKt): String { | |
val writer = StringWriter() | |
mustache.execute(writer, p).flush() | |
return writer.toString() | |
} | |
@RequestMapping(value = ["/xml"], method = [RequestMethod.POST], produces = ["application/xml"]) | |
fun xml( | |
@RequestBody p: PersonKt | |
): String { | |
return """ | |
<?xml version="1.0" encoding="UTF-8" ?> | |
<Person> | |
<age>${p.age}</age> | |
<name>${p.name}</name> | |
<company>${p.company}</company> | |
<email>${p.email}</email> | |
<address> | |
<street>${p.address.street}</street> | |
<city>${p.address.city}</city> | |
<state>${p.address.state}</state> | |
<zip>${p.address.zip}</zip> | |
</address> | |
</Person> | |
""".trimIndent() | |
} | |
} | |
fun main(args: Array<String>) { | |
runApplication<XmlDemoKt>(*args) | |
} | |
@JacksonXmlRootElement | |
@JsonRootName("person") | |
data class PersonKt( | |
val age: Long, | |
val name: String, | |
val company: String, | |
val email: String, | |
val address: AddressKt | |
) | |
data class AddressKt( | |
val street: String, | |
val city: String, | |
val state: String, | |
val zip: Long | |
) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment