Q:

How to start a shell terminal session in Java and use it to put commands and read their results keeping the previous context

I have a web application that has to mirror a Linux shell, that is to say, the users will have a screen that simulates the shell and will have an actual shell in the server side.
I have implemented a quick & dirty solution to test the interaction with the shell Process but it doesn't seem to work: this is a simple Spring Controller where the user passes commands and should get their results:
@RestController
public class ShController{

    @GetMapping("/sh")
    public DeferredResult<String> shSessionCommand(@RequestParam String command) throws IOException, InterruptedException {
        DeferredResult<String> dr = new DeferredResult<>();

        ProcessBuilder pb = new ProcessBuilder("sh");
        //START SHELL
        Process p = pb.start();

        InputStream inputStream = p.getInputStream();
        Thread t = new Thread(() -> {
            //BACKGROUND SHELL OUTPUT READ
            byte[] read = new byte[2048];
            try {
                inputStream.read(read);
                dr.setResult(new String(read));
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        t.start();
        //TO ALLOW THE SHELL READER TO START BEFORE PASSING THE COMMAND
        Thread.sleep(5000);
        //WRITE THE USER COMMAND
        OutputStream outputStream = p.getOutputStream();
        outputStream.write(command.getBytes());
        outputStream.flush();

        return dr;
    }
}

When I call /sh?command=ls outputStream.write(command.getBytes()); writes ls but inputStream.read(read) is blocked for ever. Why?
UPDATE: 
Clarifications:

Every user needs to have its own shell Process
Every user shell session will be used for a long time to keep its context

I have updated the Controller to reflect this. There is a Map where I keep the relation between users and their shell Process. Now I close the OutputStream and the inputStream.read(read); does read the command result, BUT, only the first time. Subsequent calls to issue more commands throw java.io.IOException: Stream closed when invoking outputStream.write(command.getBytes());. Any ideas?
@RestController
public class ShController{

    private Map<String, Process> shellMap = new HashMap<>();

    @GetMapping("/sh")
    public DeferredResult<String> shSessionCommand(@RequestParam String command, HttpSession session) throws IOException, InterruptedException {
        DeferredResult<String> dr = new DeferredResult<>();

        Process p = getUserShell(session.getId());

        InputStream inputStream = p.getInputStream();
        Thread t = new Thread(() -> {
            System.out.println("****THREAD");
            byte[] read = new byte[2048];
            try {
                inputStream.read(read);
                dr.setResult(new String(read));
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        t.start();

        Thread.sleep(1000);
        System.out.println("****COMMAND");
        OutputStream outputStream = p.getOutputStream();
        outputStream.write(command.getBytes());
        outputStream.flush();
        outputStream.close();

        return dr;
    }

    private Process getUserShell(String user) throws IOException {
        if(this.shellMap.get(user) == null){
            System.out.println("****Creating process");
            ProcessBuilder pb = new ProcessBuilder("sh");
            Process process = pb.start();
            shellMap.put(user, process);
        }
        return shellMap.get(user);
    }
}

A:

The problem is I wasn't sending the new line (enter) character, it's as if I never submitted the command. This is the solution:
@RestController
public class ShController{

    private Map<String, Process> shellMap = new HashMap<>();

    @GetMapping("/sh")
    public String shSessionCommand(@RequestParam String command, HttpSession session) throws IOException, InterruptedException {

        String result = "";
        Process process = getUserShell(session.getId());
        InputStream out = process.getInputStream();
        OutputStream in = process.getOutputStream();

        byte[] buffer = new byte[4000];
        boolean read = false;
        boolean written = false;
        while (!read) {
            int no = out.available();
            if (no > 0) {
                int n = out.read(buffer, 0, Math.min(no, buffer.length));
                result = new String(buffer, 0, n);
                read = true;
            }

            if(!written) {
                in.write((command + "\n").getBytes());
                in.flush();
                written = true;
            }

            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
              e.printStackTrace();
            }
        }

        return result;
    }

    private Process getUserShell(String user) throws IOException {
        if(this.shellMap.get(user) == null){
            System.out.println("****Creating process");
            ProcessBuilder pb = new ProcessBuilder("sh", "-i");
            Process process = pb.start();
            shellMap.put(user, process);
        }
        return shellMap.get(user);
    }
}

