6

I need to provide data for google APIs table... so I'll send it from servlet to JSP

but how can I access this data in "googles" javascript?

I'll provide sample of another JS - very simple one - just to let me learn how to make what topic says

    <script>
        function showTable()
        {
            <%
                Object obj = session.getAttribute("list");
                List<String> list = new ArrayList<String>();
                int size = 0; 

                if (obj != null) {
                    list = (ArrayList<String>) obj;
                    size = (Integer) session.getAttribute("size");
                }

                for (int i = 0 ; i < size ; i++) {
                    String value = list.get(i);

            %>
                    alert('<%= i %> = <%= value %> ');
            <%
                }

            %>                
        }
    </script>

It has to print elements of given list... but now it's just a big scriplet with alert inside of it... for to refactor it? I don't like having to much java in JSPs, because servlet is where it should be placed

EDIT: just to sum up - I would prefer "normal" JS for loop here... Generally I'd prefer to minimize java code, and maximize JS

dantuch
  • 9,123
  • 6
  • 45
  • 68

3 Answers3

21

Convert it to JSON in doGet() of a preprocessing servlet. You can use among others Google Gson for this. Assuming that you've a List<Person>:

List<Person> persons = createItSomehow();
String personsJson = new Gson().toJson(persons);
request.setAttribute("personsJson", personsJson);
request.getRequestDispatcher("/WEB-INF/persons.jsp").forward(request, response);

(note that I made it a request attribute instead of session attribute, you're free to change it, but I believe it doesn't necessarily need to be a session attribute as it does not represent sessionwide data)

Assign it to a JS variable in JSP as follows:

<script>
    var persons = ${personsJson};
    // ...
</script>

This way it's available as a fullworthy JS object. You could feed it straight to the Google API.

Now invoke the URL of the servlet instead of the JSP. For example, when it's mapped on an URL pattern of /persons, invoke it by http://localhost:8080/contextname/persons.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 1
    wow, thanks Balus. It looks great. And... it even works :) I've used some other JSON implementation, but code looked similar. Readability is awesome :) – dantuch Aug 30 '11 at 12:36
  • But btw. I found out, that I passed List object to request instead of jsonarray, and it worked fine. So what's the benefit of using json? It's only for escaping special characters? – dantuch Aug 30 '11 at 12:46
  • 1
    It works indeed when you use `List`. The [`List#toString()`](http://download.oracle.com/javase/6/docs/api/java/util/AbstractCollection.html#toString%28%29) has the coincidence that it matches the JS array syntax. But you shouldn't rely on it. Definitely not when you have a `List` of which each item is represented by `SomeComplexObject#toString()`. And yes, JSON format is also much more robust when it comes to handling special characters. – BalusC Aug 30 '11 at 12:47
  • It was worthy to me because I couldn't access SessionScope variables due to it was java objects. With Gson, now I'm able to treat it. – Alex Mar 12 '13 at 18:55
3

JavaScript is executed at client side, and scriptlets, EL, and JSP tags at server side. From the point of view of the server-side code, JavaScript is just generated text, just like HTML markup.

So, if you want to have a JavaScript loop which loops over a JavaScript array in the generated HTML page, you need to generate the JavaScript code which initializes the array, and the JavaScript loop.

Here's the JSP code

var theArray = [<c:forEach items="${sessionScope.list}" var="item" varStatus="loopStatus">'${item}' <c:if ${!loopStatus.last}>, </c:if></c:forEach>];
for (var i = 0; i < theArray.length; i++) {
    alert(theArray[i]);
}

This JSP code will generate the following JavaScript code, assuming the list in the session attribute contains "banana", "apple" and "orange":

var theArray = ['banana', 'apple', 'orange', ];
for (var i = 0; i < theArray.length; i++) {
    alert(theArray[i]);
}

Make sure, though, to properly escape the values of the list in order to generate valid JavaScript code. For example, if one of the values was "I'm cool", the generated JavaScript would be

var theArray = ['I'm cool', 'apple', 'orange', ];

which is not valid anymore. Use commons-lang StringEscapeUtils.escapeEcmaScript to escape the values.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • note that the ['banana',] array will have 2 values the last being undefined – Liviu T. Aug 30 '11 at 10:31
  • @Liviu: thanks for this useful note. I tested on Firefox, and it only contains the 3 fruits. On IE, though, it contains the 3 fruits + undefined. Anyway, I just wanted to show the idea of generating a JavaScript array. I'll fix it to avoid the last comma. – JB Nizet Aug 30 '11 at 10:45
  • `error: missing = in XML attribute var theArray = ['' , ]; ` what's wrong with it and can I fix this? List is created by: ` List list = new ArrayList(); list.add("1"); list.add("2222"); list.add("3333"); session.setAttribute("list", list);` – dantuch Aug 30 '11 at 11:30
0

since the ArrayList is having objects of Strings you can simply use split() method on the value of the array list. Something like as below;

function showTable() {  
  <%
       Object obj = session.getAttribute("list");
       List list = null;
       if (obj != null) {
           list = (ArrayList<String>) obj;
       } else list = new ArrayList<String>();  %>
var jsList = <%=list.toString()%>

//remove [] from content
jsList = jsList.replace("[","");
jsList = jsList.replace("]","");

//split the contents var splitContent = jsList.split(","); //an array of element

for(var i=0;i<splitContent.length;++i) {
  alert(splitContent[i]);
}

}

I hope this will help you solve this.

Naved
  • 4,020
  • 4
  • 31
  • 45