Spring Data Cassandra не отображает запрос JSON, если ключ POJO является составным

Я пытаюсь сохранить запрос к Data Stax-Cassandra. Компоненты: EventController: @RestEndPoint OneKeyClass: для сложного ключа (с несколькими столбцами) Я использую стандартную модель репозитория Spring для сохранения и извлечения данных.

Gradle:
plugins {
    id "org.springframework.boot" version "1.5.3.RELEASE"
}

apply plugin: 'java'

jar {
    baseName = 'sample-boot-with-cassandra'
    version = '0.0.1-SNAPSHOT'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
    mavenCentral()
}


dependencies {
    compile('org.springframework.boot:spring-boot-starter-data-cassandra')
    compile('org.springframework.boot:spring-boot-starter-web')
    compile('org.springframework.kafka:spring-kafka')
        compile('org.springframework.kafka:spring-kafka-test')


    testCompile('org.springframework.boot:spring-boot-starter-test')
}

Контроллер:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.company.employee.model.Event;
import com.company.employee.service.EventService;

@RestController
@RequestMapping("/event")
public class EventController {

    @Autowired
    private EventService eventService;

    @PostMapping
    public ResponseEntity<Event> saveEvent(@RequestBody Event event){
        return new ResponseEntity<Event>(eventService.saveEvent(event), HttpStatus.CREATED);
    }
}

EventServiceImpl

package com.company.employee.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.company.employee.model.Event;
import com.company.employee.model.LoginEvent;
import com.company.employee.repository.EventRepository;
import com.company.employee.repository.LoginEventRepository;

@Service
public class EventServiceImpl implements EventService {
    private EventRepository eventRepository;

    private LoginEventRepository loginEventRepository;
    private Logger logger=LoggerFactory.getLogger(EmployeeServiceImpl.class);

    @Autowired
     public EventServiceImpl(EventRepository eventRepository,LoginEventRepository loginEventRepository) {
         this.eventRepository=eventRepository;
         this.loginEventRepository=loginEventRepository;
     }

    @Override
    public Event saveEvent(Event event) {
        logger.info("saving event"+event.toString());
        return eventRepository.save(event);
    }

    @Override
    public LoginEvent saveEvent(LoginEvent event) {
        return loginEventRepository.save(event);
    }

}

Репозиторий:

package com.company.employee.repository;

import org.springframework.data.cassandra.repository.CassandraRepository;

import com.company.employee.model.Event;

public interface EventRepository extends CassandraRepository<Event> {

}

Событие:

package com.company.employee.model;

import org.springframework.data.cassandra.mapping.Column;
import org.springframework.data.cassandra.mapping.PrimaryKey;
import org.springframework.data.cassandra.mapping.Table;

@Table(value="event")
public class Event {

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("Event [eventKey=").append(eventKey).append(", transactionstatus=").append(transactionstatus)
                .append("]");
        return builder.toString();
    }

    @PrimaryKey
    private EventKey eventKey;

    public EventKey getEventKey() {
        return eventKey;
    }

    public void setEventKey(EventKey eventKey) {
        this.eventKey = eventKey;
    }

    public String getTransactionstatus() {
        return transactionstatus;
    }

    public void setTransactionstatus(String transactionstatus) {
        this.transactionstatus = transactionstatus;
    }

    @Column(value="transactionstatus")
    private String transactionstatus;
}

EventKey пакет com.company.employee.model;

import java.io.Serializable;

import org.springframework.cassandra.core.Ordering;
import org.springframework.cassandra.core.PrimaryKeyType;
import org.springframework.data.cassandra.mapping.PrimaryKeyClass;
import org.springframework.data.cassandra.mapping.PrimaryKeyColumn;

@PrimaryKeyClass
public class EventKey implements Serializable {

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("EventKey [eventsource=").append(eventsource).append(", eventid=").append(eventid)
                .append(", eventstate=").append(eventstate).append("]");
        return builder.toString();
    }
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + eventid;
        result = prime * result + ((eventsource == null) ? 0 : eventsource.hashCode());
        result = prime * result + ((eventstate == null) ? 0 : eventstate.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        EventKey other = (EventKey) obj;
        if (eventid != other.eventid)
            return false;
        if (eventsource == null) {
            if (other.eventsource != null)
                return false;
        } else if (!eventsource.equals(other.eventsource))
            return false;
        if (eventstate == null) {
            if (other.eventstate != null)
                return false;
        } else if (!eventstate.equals(other.eventstate))
            return false;
        return true;
    }
    public String getEventsource() {
        return eventsource;
    }
    public void setEventsource(String eventsource) {
        this.eventsource = eventsource;
    }
    public EventKey(String eventsource, int eventid, String eventstate) {
        super();
        this.eventsource = eventsource;
        this.eventid = eventid;
        this.eventstate = eventstate;
    }
    public int getEventid() {
        return eventid;
    }
    public void setEventid(int eventid) {
        this.eventid = eventid;
    }
    public String getEventstate() {
        return eventstate;
    }
    public void setEventstate(String eventstate) {
        this.eventstate = eventstate;
    }
    @PrimaryKeyColumn(name="eventsource",ordinal=0,type=PrimaryKeyType.PARTITIONED)
    private String eventsource;

    @PrimaryKeyColumn(name="eventid",ordinal=1,type=PrimaryKeyType.CLUSTERED,ordering=Ordering.ASCENDING)
    private int eventid;

    @PrimaryKeyColumn(name="eventstate",ordinal=2,type=PrimaryKeyType.CLUSTERED,ordering=Ordering.ASCENDING)
    private String eventstate;


}

Ошибка: java.lang.IllegalArgumentException: целевой компонент не должен быть нулевым!

сохранение eventEvent [eventKey=null, transactionstatus=success]

Входящая полезная нагрузка:

{
  "eventsource" : "terminal",
  "eventid": "23232",
  "eventstate" : "CI",
  "transactionstatus" : "success"
}

Я подписался на https://docs.spring.io/spring-data/cassandra/docs/1.0.2.RELEASE/reference/html/cassandra.core.html

Заранее спасибо за поиск и попытку помочь.


person MrWayne    schedule 15.12.2017    source источник
comment
Пожалуйста, включите полную трассировку стека.   -  person mp911de    schedule 15.12.2017
comment
пожалуйста, найдите pastebin pastebin.com/wBzZLhMb   -  person MrWayne    schedule 15.12.2017


Ответы (1)


Полезная нагрузка JSON не соответствует структуре вашего объекта. Ваше представление JSON должно скорее соответствовать:

{
  "eventKey": {
    "eventsource" : "terminal",
    "eventid": "23232",
    "eventstate" : "CI"
  },
  "transactionstatus" : "success"
}

В качестве альтернативы вы можете встроить EventKey в Event или использовать две разные структуры данных, одну для API, а другую для хранения и запроса ваших данных в Cassandra. IMHO разделение обязанностей - лучший вариант для разделения вещей, хотя использование одних и тех же типов для представления ваших данных через ваш API и в его постоянной форме требует меньше кода и не требует сопоставления.

person mp911de    schedule 15.12.2017
comment
да, это правда. Я давал неправильный json. Также обоим POJO нужны конструкторы по умолчанию, иначе jackosn не сможет сопоставить json с классом - person MrWayne; 15.12.2017