Hi there, I've come across an issue while trying to get all the records from a SQL database in java.
A bit of necessary introduction here.
I'm not using any framework just JDBC and the getAllBooks method is part of a REST call. The failing method is essentially doing this:
-getting the number of all records in the db;
-getting all the ids and use them to get the records, store them in an array and return that array;
Unfortunately the call generates the following error in the while loop:
SEVERE: Servlet.service() for servlet [Jersey Web Application] in context with path [/book-storage-REST] threw exception
java.lang.IllegalArgumentException: the object parameter to marshal() is not marshallable
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:280)
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:163)
at com.sun.jersey.json.impl.provider.entity.JSONListElementProvider.writeList(JSONListElementProvider.java:145)
at com.sun.jersey.core.provider.jaxb.AbstractListElementProvider.writeTo(AbstractListElementProvider.java:264)
at com.sun.jersey.spi.container.ContainerResponse.write(ContainerResponse.java:302)
at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1510)
at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1419)
at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1409)
at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:409)
at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:558)
at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:733)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:690)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Ok, the code now:
public Book[] getAllBooks()
{
Book[] books = null;
try
{
resultSet = statement.executeQuery(SqlStrings.SELECT_NUMBER_ALL_RECORDS);//runs "SELECT COUNT(*) from books";
resultSet.next();
int dbRecordNo = resultSet.getInt(1);//get number of record
resultSet = statement.executeQuery("SELECT books.id FROM books");//get all ids
books = new Book[dbRecordNo];
int i = 0;
while(resultSet.next() && i < dbRecordNo)
{
int bookId = Integer.parseInt(resultSet.getString("id"));
books[i] = getBook(bookId);
System.out.println();
i++;
}
return books;
}
catch (SQLException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
The problem seems to be occurring because I use && i < dbRecordNo
in while(resultSet.next() && i < dbRecordNo)
. I run a few tests and if I remove that && statement the while loop runs absolutely fine. So, I can't quite understand why this while(resultSet.next())
goes through the resultSet absolutely fine and this instead while(resultSet.next() && i < dbRecordNo)
goes through only once then returns and generates the error.
I could probably try other ways (I haven't explored any other yet but I guess I could create a hashmap of ids and book objects and then extract the book objects from there) but I'm interested to know why this isn't working as it's just a simple while loop with an additional condition. Debugging doesn't really clarify it because, as I said, it only runs for i = 0, when i is 1 it fails to get the record