Search code examples
javahibernatewebsocketquarkus-panache

How should I persist a PanacheEntity with data coming from a Websocket message?


I'm trying to persist the following entity when receiving a message from the client via Websocket:

import javax.persistence.Column;
import javax.persistence.Entity;
import io.quarkus.hibernate.orm.panache.PanacheEntity;

@Entity
public class Penguin extends PanacheEntity{
    @Column(name="penguin_name")
    public String name;
}

The following persist works, when receiving a POST request:

import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.transaction.Transactional;
import com.penguins.demo.pojos.Penguin;

@Path("/api")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class PenguinResource {
    
    @GET
    public List<Penguin> getPenguins(){
        return Penguin.listAll();
    }

    @POST
    @Transactional
    public Response addPenguin(Penguin penguin){
        penguin.persist();
        return Response.ok(penguin).status(201).build();
    }
}

However, the following code freezes when it reaches the persist line. The message.getPenguin() method is returning an actual Penguin reference (the MessageDecoder.class is doing it's part):

import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import com.penguins.demo.pojos.Message;
import com.penguins.demo.pojos.Penguin;

@ServerEndpoint(value = "/waddle/{user}", decoders = MessageDecoder.class, encoders = MessageEncoder.class)
public class PenguinHub {
   @OnMessage
   @Transactional
   public void onMessage(Session session, Message message) throws IOException {
        // Handle new messages
        message.setFrom(users.get(session.getId()));
        // it freezes on persist :(
        message.getPenguin().persist();
        broadcast(message);
   }
}

I'm new to Panache/Hibernate, any help would be apreciated, thank you.


Solution

  • It worked like this:

    @Inject
    ManagedExecutor managedExecutor;
    
    @Inject
    TransactionManager transactionManager;
    
    @OnMessage
    public void onMessage(Session session, Message message) throws IOException {
        message.setFrom(users.get(session.getId()));
        managedExecutor.submit(() -> {
            try{
                transactionManager.begin();
                parseMessage(message); // persist the entity here
                transactionManager.commit();
            }catch(Exception e){
                e.printStackTrace();
            } 
        });
    }