изменить элемент Dom на основе событий значения администратора firebase

У меня есть простая HTML-страница, распечатанная внутри сервлета. Здесь я настроил firebase admin sdk и установил прослушиватель событий значения для пути.

Когда события срабатывают, я хочу изменить элемент Div и отобразить там результаты.

РЕДАКТИРОВАТЬ: слушатель работает над дальнейшим тестированием с помощью журналов.

Но я до сих пор не знаю, как отразить изменения внутри элемента div, поскольку слушатели являются асинхронными. Скорее всего поэтому скрипт не работает.

Может кто-нибудь, пожалуйста, направьте меня относительно того, что я должен делать. Код выглядит следующим образом:

 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintWriter;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Date;

 import javax.servlet.ServletException;
 import javax.servlet.annotation.WebServlet;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;

 import com.google.firebase.FirebaseApp;
 import com.google.firebase.FirebaseOptions;
 import com.google.firebase.auth.FirebaseCredentials;
 import com.google.firebase.database.DataSnapshot;
 import com.google.firebase.database.DatabaseError;
 import com.google.firebase.database.DatabaseReference;
 import com.google.firebase.database.FirebaseDatabase;
 import com.google.firebase.database.ValueEventListener;

 @WebServlet("/WebWaitlistViewServelet")
 public class WebWaitlistViewServelet extends HttpServlet {
private static final long serialVersionUID = 1L;

public WebWaitlistViewServelet() {
    super();
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    PrintWriter pw = response.getWriter();

    try {

        String cityName=request.getParameter("city");

        String restId = request.getParameter("restid");

        String userId = request.getParameter("userid");

        if(cityName == null || restId == null || userId == null){
            System.out.println("Error getting values");
            return;
        }else{
            System.out.println(cityName+" "+restId+" "+userId);
        }


        pw.println("<HTML>");

            pw.println("<HEAD>");

                pw.println("<script>");

                    pw.println("function changePosition(position){ document.getElementById(\"positionInList\").innerHTML = position };");

                    pw.println("function changeTimeTillTurn(timetillturn){ document.getElementById(\"timeTillTurn\").innerHTML = timetillturn };");

                    pw.println("function showTimeTillTurn(){ document.getElementById(\"timeDiv\").style.display = \"visible\" };");

                    pw.println("function hideTimeTillTurn(){ document.getElementById(\"timeDiv\").style.display = \"hidden\" };");

                pw.println("</script>");

            pw.println("</HEAD>");

            pw.println("<BODY>");

                pw.println("<DIV align=\"center\">");

                    pw.println("<B>Your position in the waitlist is:</B>");

                pw.println("</DIV><br/>");

                pw.println("<DIV id=\"positionInList\" align=\"center\" style=\"color:blue\">");

                    pw.println("Loading...");

                pw.println("</DIV><br/>");

                pw.println("<DIV id=\"timeDiv\" align=\"center\">");

                    pw.println("<B>Approximate time till your turn is: </B><span id=\"timeTillTurn\" style=\"color:blue\">Loading...</span>");

                pw.println("</DIV>");

            pw.println("<BODY>");

        pw.println("</HTML>");

        pw.flush();


        InputStream is = getServletContext().getResourceAsStream("/WEB-INF/firebaseauth/firebase_admin_sdk_key.json");

        // Initialize the app with a service account, granting admin privileges
        FirebaseOptions options = new FirebaseOptions.Builder()
            .setCredential(FirebaseCredentials.fromCertificate(is))
            .setDatabaseUrl("https://restaurantrepo.firebaseio.com")
            .build();
        try {
            FirebaseApp.initializeApp(options);
        } catch (Exception e) {
            //
        }



        // As an admin, the app has access to read and write all data, regardless of Security Rules
        DatabaseReference waitlistRef = FirebaseDatabase.getInstance().getReference().child(cityName).child(restId).child("waitlist");

        Comparator<WaitlistedPerson> sortComparator = new Comparator<WaitlistedPerson>() {
            @Override
            public int compare(WaitlistedPerson lhs, WaitlistedPerson rhs) {
                //sort ascending... the bigger the time entered, the later the person has joined... thus the higher the time entered the lower the position
                //on waitlist
                if(lhs.getTimeentered()<rhs.getTimeentered()){
                    //if time entered is lower, keep the person higher in the list
                    return -1;
                }else if(lhs.getTimeentered()==rhs.getTimeentered()){
                    //if the time entered is the same, there are two cases possible
                    //1.. one person is remotely entered and one has entered at the resto POS... in this case, give priority to POS entered user
                    //2.. both people have remotely entered ... in this case, give preference to the person with lowest userid (he/she started using our app earlier)
                    //
                    //cases that will never happen are
                    //1.. two people with same userid entered remotely at same time .. can't happen as a second entry simply overwrites the old entry
                    //2.. two people with same time entered at POS ... can't happen as the resto host can only enter one party at a time..
                    if(!lhs.isRemotelyEntered() && rhs.isRemotelyEntered()){
                        //Log.d("FragmentCreate","lhs userid "+lhs.getUserid()+" lhs remotelyentered "+lhs.isRemotelyEntered());
                        //Log.d("FragmentCreate","rhs userid "+rhs.getUserid()+" rhs remotelyentered "+rhs.isRemotelyEntered());
                        return -1;
                    }else if(lhs.isRemotelyEntered() && rhs.isRemotelyEntered()){
                        //return the lowest user id
                        //userid is of format Uxx ... so get the xx part begining from index 1 of the string and get the number
                        int lhsuserid = Integer.parseInt(lhs.getUserid().substring(1));
                        int rhsuserid = Integer.parseInt(rhs.getUserid().substring(1));

                        //Log.d("FragmentCreate"," The userids are lhsuserid "+lhsuserid+" rhsuserid"+rhsuserid);

                        //Do not get tempted to use String compareto function as this will give wrong results
                        // U11 will get priority over U4 in string compareto due to 1 being lexicographically smaller
                        //Thus never use lexicographical sorting ever.

                        //The user ids can never be equal as two remotely entered users will never have two entries (can't... it's impossible due to firebase)

                        if(lhsuserid<rhsuserid){
                            return  -1;
                        }else if(lhsuserid==rhsuserid){
                            //can never happen in real life... two remotely entered users can never have same id ever... just made for safeguard
                            return 0;
                        }else{
                            return 1;
                        }

                    }else if(!lhs.isRemotelyEntered() && !rhs.isRemotelyEntered()){
                        //both entered at POS and have same time
                        //can never happen in real life...
                        //made this just for testing scenarios in case i screw up and give wrong inputs
                        return 0;
                    }else{
                        //Log.d("FragmentCreate","lhs userid "+lhs.getUserid()+" lhs remotelyentered "+lhs.isRemotelyEntered());
                        //Log.d("FragmentCreate","rhs userid "+rhs.getUserid()+" rhs remotelyentered "+rhs.isRemotelyEntered());
                        return 1;
                    }
                }else{
                    return 1;
                }
            }
        };

        ArrayList<WaitlistedPerson> listOfPeople = new ArrayList<>();

        ValueEventListener eventListener = new ValueEventListener(){

            @Override
            public void onCancelled(DatabaseError error) {
                pw.println("<script>hideTimeTillTurn();</script>");
                pw.println("<script>changePosition('Sorry, some error occured');</script>");
                System.out.println("Sorry. some error occured");
            }

            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {

                int positionCounter=0;

                if(dataSnapshot.getChildrenCount()==1 || dataSnapshot.getChildrenCount() == 0 ){
                    //Log.d("FragmentCreate","This indicates that the restaurant probably closed down and removed all customers from the list");
                    pw.println("<script>hideTimeTillTurn();</script>");
                    pw.println("<script>changePosition('You are no longer in the waitlist');</script>");
                    System.out.println("You are no longer in the waitlist");
                }else{

                    if(dataSnapshot.hasChild(userId)){

                        double averageWaitTime=0.0d;

                        long timeEnteredInMillis=0;

                        listOfPeople.clear();

                        Iterable<DataSnapshot> peopleInList = dataSnapshot.getChildren();

                        for(DataSnapshot currentPerson : peopleInList){

                            if(currentPerson.getKey().equals("dummy")){
                                continue;
                            }

                            if(currentPerson.getKey().equals(userId)){
                                //This is our node.... break the loop and enjoy using the counter
                                averageWaitTime = currentPerson.child("averagewaittimeperparty").getValue(Double.class);
                                timeEnteredInMillis = currentPerson.child("timeentered").getValue(Long.class);
                                listOfPeople.add(new WaitlistedPerson(currentPerson));
                            }else{
                                listOfPeople.add(new WaitlistedPerson(currentPerson));
                            }

                        }

                        //sort the list using our custom comparator and the get the index

                        Collections.sort(listOfPeople,sortComparator);

                        //find the position of the user now

                        for(WaitlistedPerson person : listOfPeople){
                            ++positionCounter;
                            if(person.getUserid().equals(userId)){
                               break;
                            }
                        }

                        double timetillturn = Math.round(averageWaitTime * ((double)positionCounter));

                        long timeShouldComeAt = timeEnteredInMillis + (long)(timetillturn*60000);

                        Date timeWhenTurnArrives = new Date(timeShouldComeAt);

                        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");

                        pw.println("<script>showTimeTillTurn();</script>");
                        pw.println("<script>changePosition('"+positionCounter+"');</script>");
                        pw.println("<script>changeTimeTillTurn('"+sdf.format(timeWhenTurnArrives)+"');</script>");
                        System.out.println(positionCounter+" "+sdf.format(timeWhenTurnArrives));

                    }else{
                        pw.println("<script>hideTimeTillTurn();</script>");
                        pw.println("<script>changePosition('You are no longer in the waitlist');</script>");
                        System.out.println("You are no longer in the waitlist");

                    }

                }

            }

        };

        waitlistRef.addValueEventListener(eventListener);

    } catch (Exception e) {
        e.printStackTrace();
    }finally{
        try {
            pw.close();
        } catch (Exception e) {
            //do nothing here
        }
    }


}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    doGet(request, response);
}

}

person Kushan    schedule 18.08.2017    source источник
comment
Почему вы пометили вопрос как JavaScript, когда код, которым вы делитесь, — это Java?   -  person Frank van Puffelen    schedule 18.08.2017
comment
Я думаю, что для изменения dom необходимы вызовы JavaScript или jquery... Вот где я не знаю, что делать... Java-часть работает, но html-страница не показывает вывод :( я не знаю Ajax поэтому я не знаю, как печатать вывод на страницу асинхронно   -  person Kushan    schedule 18.08.2017


Ответы (2)


С сервлетами ваши клиенты не увидят никаких обновлений страниц, пока они не отправят новый запрос на ваш сервер приложений. Что вы можете сделать, так это заставить свой ValueEventListener обновить состояние объекта в памяти. Затем ваш сервлет может считывать последнее состояние этого объекта при построении вывода HTML.

person Hiranya Jayathilaka    schedule 18.08.2017
comment
Вам нужно каким-то образом передать ссылку на этот объект в сервлет. Проще всего было бы использовать шаблон singleton, но я уверен, что доступны и другие варианты. - person Hiranya Jayathilaka; 21.08.2017

Так что мне удалось решить эту проблему, используя JSP вместо сервлета.

В любом случае решением было перенести всю логику в функцию JavaScript. Затем вызов указанной функции при загрузке тела.

onload=callthefunction()

Слушатели firebase были преобразованы из java в версию JavaScript:

on()
off()

Таким образом, необходимо вызвать ajax или что-то еще, а элементы, которые необходимо изменить, можно напрямую изменить из JavaScript.

person Kushan    schedule 20.08.2017