繁体   English   中英

在 kafka 上发送 JSON object 作为消息时出错

[英]Error while sending a JSON object as message on kafka

我是一名试图了解 apache kafka 的学生。 我正在尝试发送JSON 8828282995402888作为一条消息,使用Kafka在spring启动启动,使用java启动。但是,当我尝试发送我的888361616168888888888888888888888888888888888888888888888888888号8888888 88888888888888888882615705700.AST88888888号88888 8888888888888888882在 application.properties 文件中。 例外是:

java.lang.ClassCastException: class com.example.demo.model.BookES cannot be cast to class java.lang.String (com.example.demo.model.BookES is in unnamed module of loader 'app'; java.lang.String is in module java.base of loader 'bootstrap')

我的 application.properties 文件是

server.port=8081

spring.kafka.consumer.bootstrap-servers=localhost:9092
spring.kafka.consumer.group-id=myGroup
spring.kafka.consumer.auto-offset-reset=earliest
spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer
spring.kafka.consumer.value-deserializer=org.springframework.kafka.support.serializer.JsonDeserializer

spring.kafka.producer.bootstrap-servers=localhost:9092
spring.kafka.producer.key-serializer=org.apache.common.serialization.StringSerializer
spring.kafka.producer.value-serializer=org.springframework.kafka.support.serializer.JsonSerializer

我的 controller class 我正在尝试发送消息

@PostMapping("/publish")
    public ResponseEntity<String> publish(@RequestBody BookES bookES){
        logger.info("in publish method");
        kafkaProducer.sendMessage(bookES);
        return ResponseEntity.ok("Json message sent to kafka topic");
    }

我的 Kafka 生产者 class 具有 sendMessage 方法:

package com.example.demo.kafka;

import org.apache.kafka.clients.admin.NewTopic;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.KafkaHeaders;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;

import com.example.demo.controller.BookController;
import com.example.demo.model.Book;
import com.example.demo.model.BookES;

@Service
public class KafkaProducer {
    
    @Autowired
    private NewTopic topic;
    
    Logger logger = LoggerFactory.getLogger(KafkaProducer.class);
    
    private String topicName = "bookmanagement";
    
    @Autowired
    private KafkaTemplate<String, BookES> kafkaTemplate;

    
    
    public void sendMessage(BookES bookES) {
        
        logger.info("in sendMessage method");
        logger.info(String.format("Message sent -> %s",bookES.toString()));
        
        Message<BookES> message = MessageBuilder.withPayload(bookES).setHeader(KafkaHeaders.TOPIC, topic.name()).build();
        kafkaTemplate.send(message);
        
        
        
    }
    
    
}

我的 model class:



package com.example.demo.model;

import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Document(indexName="my-application")
@Data
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class BookES{
    @Override
    public String toString() {
        return "BookES [bookId=" + bookId + ", bookName=" + bookName + ", description=" + description + "]";
    }
    @Id
    private String bookId;
    private String bookName;
    private String description;
    public String getBookId() {
        // TODO Auto-generated method stub
        return this.bookId;
    }
    public String getBookName() {
        return bookName;
    }
    public void setBookName(String bookName) {
        this.bookName = bookName;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public void setBookId(String bookId) {
        this.bookId = bookId;
    }

    
}

我的项目在github链接: github链接

我尝试使用不同的注释(如@JsonSerializer 等)对我的 model class 进行注释,但没有成功。 我在 postman 上尝试发帖时得到的回复是:



{
    "timestamp": "2022-11-22T11:24:30.738+00:00",
    "status": 500,
    "error": "Internal Server Error",
    "message": "Can't convert value of class com.example.demo.model.BookES to class org.apache.kafka.common.serialization.StringSerializer specified in value.serializer",
    "path": "/books/publish"
}

您需要提供自己的序列化程序,可以将BookES序列化为字节数组。 这是我用作通用 Json 序列化程序的 class。 它应该可以很好地处理您的 class:

package ***;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.mgnt.utils.JsonUtils;
import org.apache.kafka.common.errors.SerializationException;
import org.apache.kafka.common.serialization.Serializer;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;

    @Component
    public class GenericJsonSerializer implements Serializer<Object> {
        @Override
        public byte[] serialize(String s, Object obj) {
            byte[] result;
            try {
                result = JsonUtils.writeObjectToJsonString(obj).getBytes(StandardCharsets.UTF_8);
            } catch (JsonProcessingException e) {
                throw new SerializationException("Error occurred while serializing " + obj.getClass().getCanonicalName() + " to byte[]", e);
            }
            return result;
        }
    }

在您的属性中,您需要将此 class 注册为您的解串器。 请注意,当您回读消息时,如果您希望将其读取为BookES class ,则需要提供反序列化器 class ,它将采用字节数组并将其转换回 class BookES (您将必须实施org.apache.kafka.common.serialization.Deserializer接口)。 在我的示例中,我使用了来自开源 Java 库JsonUtils (由我编写和维护)的 class JsonUtils。 您可以轻松替换它,只需使用 Json-Jackson 库中的ObjectMapper class 或使用 GSON 库。 但使用JsonUtils可能会更简单。 如果您想在此处使用它,请参阅 JsonUtils class 的 Javadoc MgntUtils 库可以作为Maven 工件或在Github上获得

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM