Метод JPArepository.save() кидает NullpointerException

85
24 апреля 2021, 00:40

Пожалуйста помогите решить эту проблему, хотя бы в какую сторону копать решение.

Ссылка на полный проект.

Суть ошибки: при вызове метода instrumentEntityRepository.save() в классе SimpleWsHandler выбрасывается NullPointerException. Класс SimpleWsHandler является обработчиком для клиента WebSocket, используемого в бине WebSocketConnectionManager. Если вызывать метод instrumentEntityRepository.save() в классе Controller, то исключение не выбрасывается. Вероятно при вызове instrumentEntityRepository.save() в классе SimpleWsHandler при создании объекта/сущности для сохранения его id равно null и это не нравится instrumentEntityRepository, это значение заполняется само блягодаря аннотации @GeneratedValue, что не так? Если вызвать этот метод в классе Controller, то всё сохраняется как надо.

Такой stacktrace выдаёт ошибка:

java.lang.NullPointerException
at com.example.WSClient.wshandler.SimpleWsHandler.saveMessage(SimpleWsHandler.java:105)
at com.example.WSClient.wshandler.SimpleWsHandler.handleMessage(SimpleWsHandler.java:42)
at org.springframework.web.socket.handler.WebSocketHandlerDecorator.handleMessage(WebSocketHandlerDecorator.java:75)
at org.springframework.web.socket.handler.LoggingWebSocketHandlerDecorator.handleMessage(LoggingWebSocketHandlerDecorator.java:56)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.handleTextMessage(StandardWebSocketHandlerAdapter.java:113)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.access$000(StandardWebSocketHandlerAdapter.java:42)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:84)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:81)
at org.apache.tomcat.websocket.WsFrameBase.sendMessageText(WsFrameBase.java:395)
at org.apache.tomcat.websocket.WsFrameBase.processDataText(WsFrameBase.java:495)
at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:294)
at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:133)
at org.apache.tomcat.websocket.WsFrameClient.processSocketRead(WsFrameClient.java:95)
at org.apache.tomcat.websocket.WsFrameClient.resumeProcessing(WsFrameClient.java:209)
at org.apache.tomcat.websocket.WsFrameClient.access$300(WsFrameClient.java:31)
at org.apache.tomcat.websocket.WsFrameClient$WsFrameClientCompletionHandler.doResumeProcessing(WsFrameClient.java:186)
at org.apache.tomcat.websocket.WsFrameClient$WsFrameClientCompletionHandler.completed(WsFrameClient.java:163)
at org.apache.tomcat.websocket.WsFrameClient$WsFrameClientCompletionHandler.completed(WsFrameClient.java:148)
at org.apache.tomcat.websocket.AsyncChannelWrapperSecure$WrapperFuture.complete(AsyncChannelWrapperSecure.java:464)
at org.apache.tomcat.websocket.AsyncChannelWrapperSecure$ReadTask.run(AsyncChannelWrapperSecure.java:331)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)

SimpleWsHandler:

package com.example.WSClient.wshandler;
import com.example.WSClient.entity.InstrumentEntity;
import com.example.WSClient.repository.InstrumentEntityRepository;
import com.example.WSClient.service.ServiceApp;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import java.io.IOException;
@Service
public class SimpleWsHandler implements WebSocketHandler {
    @Autowired
    private InstrumentEntityRepository instrumentEntityRepository;
    private static final ObjectMapper mapper = new ObjectMapper();
    /**
    * Called when WS connects to the server.
    */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
    }
    /**
    * Main method to handle server messages.
    */
    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        //System.out.println(message.getPayload());
        saveMessage(message.getPayload());
    }
    /**
    * Error handling.
    */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
    }
    /**
    * Called when WS is closed.
    */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
    }
    @Override
    public boolean supportsPartialMessages() {
        // TODO Auto-generated method stub
        return false;
    }
    public void saveMessage (Object message) {
       try {
            JsonNode root = mapper.readTree((String) message);
            String table = root.path("table").asText();
            String action = root.path("action").asText();
            System.out.println("Значения table и partial: " + table + " " + action);
            if (table.equals("instrument") && action.equals("partial")) {
                System.out.println("Прошли условие");
                JsonNode data = root.path("data");
                if (data.isArray()) {
                    for (JsonNode curr : data) {
                        try {
                            instrumentEntityRepository.save(new InstrumentEntity(
                                curr.path("symbol").asText(),
                                Float.parseFloat(curr.path("highPrice").asText()),
                                Float.parseFloat(curr.path("lowPrice").asText()),
                                Float.parseFloat(curr.path("lastPrice").asText()),
                                Float.parseFloat(curr.path("bidPrice").asText()),
                                Float.parseFloat(curr.path("askPrice").asText())
                        ));
                        System.out.println("Сохранено!!!! БЛЯЯЯЯЯ");
                        } catch (Exception ex) {
                            ex.printStackTrace();
                        }
                    }
                }
            }
        } catch (JsonGenerationException e) {
            e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

WsClientApplication и @Bean WebSocketConnectionManager:

package com.example.WSClient;
import com.example.WSClient.wshandler.SimpleWsHandler;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.web.socket.client.WebSocketConnectionManager;
import org.springframework.web.socket.client.standard.StandardWebSocketClient;
@SpringBootApplication
@EnableJpaRepositories
public class WsClientApplication {
    private final String webSocketUri = "wss://www.bitmex.com/realtime?subscribe=instrument:XBTUSD";
    public static void main(String[] args) {
        SpringApplication.run(WsClientApplication.class, args);
    }
    @Bean
    public WebSocketConnectionManager wsConnectionManager() {
        //Generates a web socket connection
        WebSocketConnectionManager manager = new WebSocketConnectionManager(
            new StandardWebSocketClient(),
            new SimpleWsHandler(), //Must be defined to handle messages
            this.webSocketUri);
        //Will connect as soon as possible
        manager.setAutoStartup(true);
        return manager;
    }
}

Controller:

package com.example.WSClient.controller;

import com.example.WSClient.entity.InstrumentEntity;
import com.example.WSClient.repository.InstrumentEntityRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Controller {
    @Autowired
    private InstrumentEntityRepository instrumentEntityRepository;
    private InstrumentEntity instrumentEntity;
    @GetMapping("/ms")
    public ResponseEntity getData () {
        instrumentEntityRepository.save(new InstrumentEntity("XBTUSD", (float) 1.0, (float) 1.0, (float) 1.0, (float) 1.0, (float) 1.0));
        instrumentEntity = instrumentEntityRepository.findBySymbolName("XBTUSD");
        return new ResponseEntity(instrumentEntity, HttpStatus.OK);
    }
}

@Entity InstrumentEntity:

package com.example.WSClient.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
import java.util.Objects;

@Entity
@Table(name = "INSTRUMENT")
public class InstrumentEntity implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;
    @Column(name = "symbol_name")
    private String symbolName;
    @Column(name = "high_price")
    private Float highPrice;
    @Column(name = "low_price")
    private Float lowPrice;
    @Column(name = "last_price")
    private Float lastPrice;
    @Column(name = "bid_price")
    private Float bidPrice;
    @Column(name = "ask_price")
    private Float askPrice;
    public InstrumentEntity() {}
    public InstrumentEntity(String symbolName, Float highPrice, Float lowPrice, Float lastPrice, Float bidPrice, Float askPrice) {
        this.symbolName = symbolName;
        this.highPrice = highPrice;
        this.lowPrice = lowPrice;
        this.lastPrice = lastPrice;
        this.bidPrice = bidPrice;
        this.askPrice = askPrice;
    }
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getSymbolName() {
        return symbolName;
    }
    public void setSymbolName(String symbolName) {
        this.symbolName = symbolName;
    }
    public Float getHighPrice() {
        return highPrice;
    }
    public void setHighPrice(Float highPrice) {
        this.highPrice = highPrice;
    }
    public Float getLowPrice() {
        return lowPrice;
    }
    public void setLowPrice(Float lowPrice) {
        this.lowPrice = lowPrice;
    }
    public Float getLastPrice() {
        return lastPrice;
    }
    public void setLastPrice(Float lastPrice) {
        this.lastPrice = lastPrice;
    }
    public Float getBidPrice() {
        return bidPrice;
    }
    public void setBidPrice(Float bidPrice) {
        this.bidPrice = bidPrice;
    }
    public Float getAskPrice() {
        return askPrice;
    }
    public void setAskPrice(Float askPrice) {
        this.askPrice = askPrice;
    }
}

POM:

<?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   http://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.1.6.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>WSClient</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>WSClient</name>
<description>Demo project for Spring Boot</description>
<properties>
    <java.version>1.8</java.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>
</project>

application.properties:

spring.h2.console.enabled=true
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
Answer 1

Это происходит потому что вы создаете SimpleWsHandler через коснтуктор и спринг не инициализирует эту часть

@Autowired
private InstrumentEntityRepository instrumentEntityRepository;

Решение в лоб:

@Autowired
private SimpleWsHandler simpleWsHandler;
@Bean
public WebSocketConnectionManager wsConnectionManager() {
    //Generates a web socket connection
    WebSocketConnectionManager manager = new WebSocketConnectionManager(
            new StandardWebSocketClient(),
            simpleWsHandler, //Must be defined to handle messages
            this.webSocketUri);
    //Will connect as soon as possible
    manager.setAutoStartup(true);
    return manager;
}
READ ALSO
.sort() Не сортирует

.sort() Не сортирует

Размер ArrayList задаю через BufferedReader, вывожу сообщение о последнем элементе массива, далее сортируюsort()-ом

96
поиск символа в строке

поиск символа в строке

Имеется строка в которой может присутствовать любой один из пяти символов: & или @ или + или * или %

88
Какие типы изображений поддерживает iText?

Какие типы изображений поддерживает iText?

Я хочу добавить PNG-изображение в PDF-файл, но я знаю, что PDF не поддерживает PNG-файлыЗначит ли это, что я не могу использовать PNG-файлы в iText?

99
No IDEA annotations attached to the JDK

No IDEA annotations attached to the JDK

No IDEA annotations attached to the JDK 18 (D:\Program Files\Java\jdk1

97