0
votes

Les Websockets Springboot ne parviennent pas à établir la connexion java.lang.NoSuchMethodError

J'essaie d'utiliser des websockets dans mon application pour fournir une messagerie privée un à un. J'ai suivi ce projet dans ma mise en œuvre. Avec mon projet frontal en angulaire, je suis capable d'établir la connexion avec le service de chat cloné des auteurs github, mais lorsque j'essaye de me connecter au mien, j'obtiens cette erreur:

<?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>
    <groupId>pl.edu.pjatk.mroz</groupId>
    <artifactId>project-API</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>project-API</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>11</java.version>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

    <dependencies>

        <!--SPRING-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>5.3.1.RELEASE</version>
        </dependency>

        <!--SPRINGBOOT-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot</artifactId>
            <version>2.2.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.2.6.RELEASE</version>

        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <version>2.2.6.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
            <version>2.2.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <version>2.2.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
            <version>2.3.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
            <version>2.3.4.RELEASE</version>
        </dependency>


        <dependency>
            <groupId>com.corundumstudio.socketio</groupId>
            <artifactId>netty-socketio</artifactId>
            <version>1.7.18</version>
        </dependency>



        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>42.2.12</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.mindrot</groupId>
            <artifactId>jbcrypt</artifactId>
            <version>0.4</version>
        </dependency>

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>
        <!-- API, java.xml.bind module -->
        <dependency>
            <groupId>jakarta.xml.bind</groupId>
            <artifactId>jakarta.xml.bind-api</artifactId>
            <version>2.3.2</version>
        </dependency>

        <!-- Runtime, com.sun.xml.bind module -->
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>2.3.2</version>
        </dependency>

        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk-s3</artifactId>
            <version>1.11.885</version>
        </dependency>


        <!--testing-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>2.2.6.RELEASE</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <version>5.3.1.RELEASE</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>

    </dependencies>

    <build>
        <finalName>rental</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.3.4.RELEASE</version>
            </plugin>
        </plugins>
    </build>

</project>

La seule différence entre mon projet et l'autre est que j'utilise postgres, donc mon repo et mon service diffèrent, mais ce code n'est jamais atteint avant l'erreur, car je place des points d'arrêt partout et aucun ne frappe. Je ne peux pas comprendre ce que l'erreur signifie vraiment, car elle est très vague et ne me dirige pas dans une direction spécifique.

Ma config:

import * as Stomp from 'stompjs';
import * as SockJS from 'sockjs-client';
// ...

  connect() {
    const sockJS = new SockJS(API_URL + 'ws');
    this.stompClient = Stomp.over(sockJS);
    this.stompClient.connect({}, this.onConnected, this.onError);
  }

Contrôleur de chat:

@Controller
public class ChatController {

    @Autowired private SimpMessagingTemplate messagingTemplate;
    @Autowired private ChatMessageService chatMessageService;
    @Autowired private ChatRoomService chatRoomService;

    @MessageMapping("/chat")
    public void processMessage(@Payload ChatMessage chatMessage) {
        var chatId = chatRoomService
                .getChatId(chatMessage.getSenderId(), chatMessage.getRecipientId(), true);
        chatMessage.setChatId(chatId.get());

        ChatMessage saved = chatMessageService.save(chatMessage);
        messagingTemplate.convertAndSendToUser(
                chatMessage.getRecipientId().toString(),"/queue/messages",
                new ChatNotification(
                        saved.getId(),
                        saved.getSenderId(),
                        saved.getSenderName()));
    }

    @GetMapping("/messages/{senderId}/{recipientId}/count")
    public ResponseEntity<Long> countNewMessages(
            @PathVariable UUID senderId,
            @PathVariable UUID recipientId) {

        return ResponseEntity
                .ok(chatMessageService.countNewMessages(senderId, recipientId));
    }

    @GetMapping("/messages/{senderId}/{recipientId}")
    public ResponseEntity<?> findChatMessages ( @PathVariable UUID senderId,
                                                @PathVariable UUID recipientId) {
        return ResponseEntity
                .ok(chatMessageService.findChatMessages(senderId, recipientId));
    }

    @GetMapping("/messages/{id}")
    public ResponseEntity<?> findMessage ( @PathVariable UUID id) {
        return ResponseEntity
                .ok(chatMessageService.findById(id));
    }
}

Comme je l'ai dit, mon front-end ne devrait pas être un problème, car il se connecte à l'autre backend, mais juste pour être sûr, voici mon extrait angulaire:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/user");
        config.setApplicationDestinationPrefixes("/app");
        config.setUserDestinationPrefix("/user");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry
                .addEndpoint("/ws")
                .setAllowedOrigins("*")
                .withSockJS();
    }

    @Override
    public boolean configureMessageConverters(List<MessageConverter> messageConverters) {
        DefaultContentTypeResolver resolver = new DefaultContentTypeResolver();
        resolver.setDefaultMimeType(MimeTypeUtils.APPLICATION_JSON);
        MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
        converter.setObjectMapper(new ObjectMapper());
        converter.setContentTypeResolver(resolver);
        messageConverters.add(converter);
        return false;
    }
}

J'apprécierais volontiers de l'aide, car je ne sais même pas ce qui pourrait être cassé / manquant, c'est ma première fois même en utilisant des websockets et je ne peux pas trouver des problèmes similaires en ligne.

EDIT: ajout du fichier pom comme demandé:

2020-11-04 19:21:53.918 ERROR 21648 --- [nio-7000-exec-9] o.s.w.s.m.StompSubProtocolHandler        : Failed to parse TextMessage payload=[CONNECT
ac..], byteCount=56, last=true] in session 0vmhpgm0. Sending STOMP ERROR to client.

java.lang.NoSuchMethodError: 'java.lang.String org.springframework.util.StreamUtils.copyToString(java.io.ByteArrayOutputStream, java.nio.charset.Charset)'
    at org.springframework.messaging.simp.stomp.StompDecoder.readCommand(StompDecoder.java:220) ~[spring-messaging-5.2.10.RELEASE.jar:5.2.10.RELEASE]
    at org.springframework.messaging.simp.stomp.StompDecoder.decodeMessage(StompDecoder.java:143) ~[spring-messaging-5.2.10.RELEASE.jar:5.2.10.RELEASE]
    at org.springframework.messaging.simp.stomp.StompDecoder.decode(StompDecoder.java:115) ~[spring-messaging-5.2.10.RELEASE.jar:5.2.10.RELEASE]


2 commentaires

À en juger par l'erreur, vous avez des versions incompatibles dans votre gestion des dépendances. Ce qui signifie probablement que vous essayez de déjouer la solution de gestion des dépendances que vous utilisez. Veuillez ajouter votre fichier pom ou build à la question.


Merci, a mis à jour la question.


3 Réponses :


1
votes

Puisque vous utilisez Spring Boot, vous devez utiliser la même version pour tous les artefacts.

Par exemple, dans pom.xml, vous devriez avoir quelque chose comme ces lignes:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.1.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
    <version>2.1.1.RELEASE</version>
</dependency>

Assurez-vous que vous utilisez les mêmes versions des dépendances springboot.

modifier après avoir ajouté pom.xml:

Juste au cas où essayez l'initialiseur de printemps ici: https://start.spring.io/ pour vous assurer que vous avez toutes les bonnes versions. Comparez le pom.xml généré avec le vôtre.


1 commentaires

Merci, je n'ai pas remarqué que mon pom était maussade en raison du fait que le projet a commencé il y a longtemps. Fonctionne comme un charme maintenant, meilleurs voeux!



1
votes

Vous semblez avoir gâché les dépendances lorsque vous utilisez différentes versions de printemps.

Le coupable de ce problème est -

<dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot</artifactId>
                <version>${spring.boot.version}</version>
            </dependency>

En raison de cette dépendance, vous avez spring-core-5.2.5.RELEASE .

Les journaux montrent que vous utilisez la version spring-messaging-5.2.10.RELEASE qui utilise la méthode StreamUtils copyToString qui a été ajoutée avec la version 5.2.6.

Si vous vous assurez d'utiliser la version spring-core-5.2.10.RELEASE , cela devrait résoudre le problème.

Vous devriez utiliser la section des propriétés de votre pom. Ajoutez une nouvelle propriété pour la version Spring Boot. Notez que la botte à ressort 2.3.1 tirera les versions du ressort 5.2.10.RELEASE.

<properties>
        <java.version>11</java.version>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>

        <spring.boot.version>2.3.1.RELEASE</spring.boot.version>
</properties>

Ensuite, utilisez-le dans des dépendances comme -

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot</artifactId>
            <version>2.2.6.RELEASE</version>
        </dependency>

Vous devriez le faire de la même manière pour toutes les dépendances de démarrage de printemps. De plus, supprimez ces dépendances de ressort explicites telles que spring-context .


1 commentaires

Merci, c'est ce que j'ai fini par faire - ajouter les dépendances nécessaires uniquement lorsque j'ai commencé à travailler sur les sockets, sans même parler de non-concordance de version. Meilleures salutations!



1
votes

Je rencontre le même problème, mais le passage à une version plus récente de springboot n'était pas possible. La solution que j'ai trouvée a été de rétrograder la version de spring-messaging vers 5.2.5.RELEASE (et la même chose pour spring-websocket) et cela a fonctionné.


0 commentaires