I created a Spring boot application that sends messages to Kafka queues (using spring integrations kafka support). I want to send arbitrary json-serialized objects.
Is there a way to get/inject a json-de-/serializer within my spring boot application?
Or how to ad hoc de-/ serialize an object?
what are good practices to apply serialization?
Apache Kafka stores and transports Byte arrays in its topics. It ships with a number of built in (de)serializers but a JSON one is not included. Luckily, the Spring Kafka framework includes a support package that contains a JSON (de)serializer that uses a Jackson ObjectMapper under the covers.
You can add a config file like this
#Configuration
public class KafkaConfiguration {
#Bean
public ConsumerFactory<String, Operation> consumerFactory(KafkaProperties kafkaProperties) {
return new DefaultKafkaConsumerFactory<>(kafkaProperties.buildConsumerProperties(), new StringDeserializer(), new JsonDeserializer<>(Operation.class));
}
#Bean
public ConcurrentKafkaListenerContainerFactory<String, Operation> kafkaListenerContainerFactory(ConsumerFactory<String, Operation> consumerFactory) {
ConcurrentKafkaListenerContainerFactory<String, Operation> factory = new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(consumerFactory);
return factory;
}
}
Replace Operation with your class which you want to deserialize.
Related
There is a klaxon library - JSON parser for kotlin
How to configure Spring Boot for using it to make a REST API in this way:
#RestController
class SampleController {
#RequestMapping("/test", method = [RequestMethod.POST])
fun test(#RequestBody body:JsonObject): JsonObject {
//work with body val (KLAXON object)
//return KLAXON object
}
}
#RequestBody body:JsonObject - is a Klaxon object, so we do not want to use standard Jackson2ObjectMapperBuilder for RequestBody. For simplicity we do not want to use it for Response body too.
Post body is some kind of dynamic data, so I want to use a Low level API in lib, not a Object binding API.
No, at the moment it's not possible.
Reference
I have tried doing some poc on springfox swagger with spring boot. It does generate swagger ui on the same host and port as my application is running.
http://localhost:8080/swagger-ui.html
My application is composed of multiple microservices deployed on a cloud infrastructure. This way i may end up having multiple swagger hub ui as
http://microservice1:8080/swagger-ui.html
http://microservice2:8081/swagger-ui.html
http://microservice3:8082/swagger-ui.html
How i can host all of my springfox swagger hub application on same host. So that i can have a consolidate webpage to have all my api documentation at single place.
For spring rest doc, i could generate a single html document using asciidoctor for my microservice. Again i had different html docs for different microservices.
Is this feature available with spring rest doc? or in spring cloud where consolidate all my documents in one single web application.
Create a Zuul filter concept. Create a Zuul filter service and add swagger2 dependency in your pom.xml and create a configuration class in this service as mentioned below
#EnableSwagger2
#Configuration
#Component
#Primary
public class SwaggerConfig implements SwaggerResourcesProvider {
#Override
public List<SwaggerResource> get() {
List resources = new ArrayList<>();
resources.add(swaggerResource("microservice1", "/microservice1/v2/api-docs", "2.0"));
resources.add(swaggerResource("microservice2", "/microservice2/v2/api-docs", "2.0"));
resources.add(swaggerResource("microservice3", "/microservice3/v2/api-docs", "2.0"));
return resources;
}
private SwaggerResource swaggerResource(String name, String location, String version) {
SwaggerResource swaggerResource = new SwaggerResource();
swaggerResource.setName(name);
swaggerResource.setLocation(location);
swaggerResource.setSwaggerVersion(version);
return swaggerResource;
}
}
Add below mentioned configuration in the other three microservices(microservice1,microservice2,microservice3..)
#Configuration
#EnableSwagger2
public class SwaggerConfig {
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2).select()
.apis(RequestHandlerSelectors.basePackage("com.stackoverflow.login.controller"))
.paths(PathSelectors.regex("/.*")).build().apiInfo(apiEndPointsInfo());
}
private ApiInfo apiEndPointsInfo() {
return new ApiInfoBuilder().title("Spring Boot REST API").description("Employee Management REST API")
.contact(new Contact("stackoverflow", "www.stackoverflow.com", ""))
.license("Apache 2.0").licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html").version("1.0.0")
.build();
}
}
I am new to Springboot and Webservices.Using springboot i need to expose a rest endpoint. Some data provider will call the rest endpoint to post the data. Then i need to start processing the posted json and convert it into a java object. So using spring boot I need to expose a rest webservice to accept and process the json posted to the webservice created. How should I do it. Any example would help
Its so simple.
We need to have a Springboot restcontroller to expose rest endpoint. And then using #Requestbody we need to get the Objects directly from the json message passed .
#RestController
public class JsonObjectRestController {
#RequestMapping(value="/rest/pushjson",method = RequestMethod.POST)
public ResponseEntity<PushedJsonObject> getJsonObject(#RequestBody PushedJsonObject jsonObject)
{
if(jsonObject != null)
{
//process the json object
}
return new ResponseEntity<PushedJsonObject >(jsonObject, HttpStatus.OK);
}
}
Explanation:
We need to have a model class representing the json sent(Here its PushedJsonObject). Have your controller annotated with the new Spring4 #RestController.
The #RequestBody method parameter annotation should bind the json value in the HTTP request body to the java object by using a HttpMessageConverter. Make sure Jackson is in the classpath so that spring boot configures it automatically to use the MappingJackson2MessageConverter.
I have a jersey webservice running 1.17 and supports returning responses via both XML and JSON via the #Produces annotation. I am assuming it uses JAXB by default when returning JSON responses but I have no way to confirm it. As of now, my existing clients also use the same JAXB serializer/deserializer. I want to create a new client that uses Jackson without impacting the existing clients.
The JAXB JSON response is incompatible for Jackson for Maps. the JSON for a map using JAXB is of the form
"mapName":{"entry":[{"key":"key1","value":"value1"},{"key":"key2","value":"value2"}]}
and Jackson fails to parse this. Is there any way to make jackson parse this JSON?
Another Attempt: Switching Jersey to use Jackson
This isn't the preferred option but I tried setting "com.sun.jersey.api.json.POJOMappingFeature" to true to allow it to use Jackson for JSON Serialization/Deserialization however the service ends up returning 500s on response without logging any exceptions. the log4j logger level is set to TRACE. I enabled the ContainerRepsonseFilter to confirm 500s in the response and to my surprise, it logs the successful 2xx response. My guess is the problem occurs somewhere further down the stack but I don't know where.
I ended up with using MOXy which is able to parse the above json format.
#Provider
public class JsonMoxyConfigurationContextResolver implements ContextResolver {
private final MoxyJsonConfig config;
public JsonMoxyConfigurationContextResolver() {
final Map<String, String> namespacePrefixMapper = new HashMap<String, String>();
namespacePrefixMapper.put("http://www.w3.org/2001/XMLSchema-instance", "xsi");
config = new MoxyJsonConfig()
.setNamespacePrefixMapper(namespacePrefixMapper)
.setNamespaceSeparator(':');
}
#Override
public MoxyJsonConfig getContext(Class<?> objectType) {
return config;
}
}
and enabled it Jersey 2.x client using
cc.register(JsonMoxyConfigurationContextResolver.class);
Does anyone know if Spring has any extensions that allow for configuring its ApplicationContext via JSON (or really any other format) rather than XML? I couldn't find anything in the official docs, but I was wondering if there were any other open source extensions that could allow this.
Just to be clear, I'm not talking about configuring SpringMVC to set up a RESTful JSON-based web service or anything like that, just if it's possible to do Spring app configuration via JSON instead of XML.
As far as I know there is no project to support JSON as configuration source. It should be relatively easy to kick-start, (Spring container has no dependency on XML, it is just a way to construct bean definitions). However it is much more work than you might think.
Note that Spring provides xml-schema to assist you in writing correct XML. You won't get that much in JSON. Also many DSLs were built on top of Spring XML and custom namespaces support (spring-integration, mule-esb and others use it).
If you hate XML (many do), try out Java Configuration, available since 3.0 and improved in 3.1:
#Configuration
public class MyBeans {
#Bean
public Foo foo() {
return new Foo();
}
#Bean
public Bar bar() {
return new Bar(foo());
}
#Bean
public Buzz buzz() {
Buzz buzz = new Buzz();
buzz.setFoo(foo());
return buzz;
}
}
Interesting fact: thanks to some fancy proxying, foo() is called exactly once here, even though referenced twice.
Try JSConf library available on maven central, it's support Properties, HOCON and JSON format.
You can inject values from external file to your service and more !
Sample usage of JavaConfig :
You data stored on file app.conf
{
"root":{
"simpleConf":{
"url":"Hello World",
"port":12,
"aMap":{
"key1":"value1",
"key2":"value2"
},
"aList":[
"value1",
"value2"
]
}}
You service where your configuration must be inject
#Service("service")
public class Service {
#Autowired
private ConfigBean configBean;
}
Declare a interface to access your configuration values from your service
#ConfigurationProperties("root/simpleConf")
public interface ConfigBean {
String getUrl();
int getPort();
Map getAMap();
List getAList();
}
And your Spring configuration bean :
#Configuration
public class ContextConfiguration {
#Bean
public static ConfigurationFactory configurationFactory() {
return new ConfigurationFactory().withResourceName("app.conf") //
.withScanPackage("org.jsconf.core.sample.bean");
}
}