Raven DB 4.1.2 hangs on streaming query in Java - linux

I have a jax-rs-based REST service that I run on Tomcat 8.5 on 64bit Linux, using Java 11; this service connects to a RavenDB 4.1.2 instance, also on the same Linux machine. I make use of the streaming query to return the request result. I use Postman to submit the same request, and everything works well: the results are returned, and rather quickly.
However - it only works 10 times. When I submit the same request as previously an 11th time, the results = currentSession.advanced().stream(query); line hangs and doesn't return.
At first I thought I could have something to do with the StreamingOutput or OutputStreamWriter not being closed appropriately. or perhaps something do to with the Response - but as I stepped through the deployed code in Eclipse in debug mode, I noticed that execution hangs on that streaming line.
(I find exactly 10 times to be a peculiarly "human choice" kind of number...)
The relevant parts of my code:
#GET
#Path("/abcntr/{ccode}/{st}/{zm}")
#Produces(MediaType.TEXT_PLAIN)
#Consumes(MediaType.TEXT_PLAIN)
public Response retrieveInfo(#PathParam("ccode") String ccode, #PathParam("st") String st, #PathParam("zm") String zm)
{
(...)
StreamingOutput adminAreaStream = new StreamingOutput()
{
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
#Override
public void write(OutputStream output) throws IOException, WebApplicationException
{
try(IDocumentSession currentSession = ServiceListener.ravenDBStore.openSession())
{
Writer writer = new BufferedWriter(new OutputStreamWriter(output));
(...)
if(indexToBeQueried.startsWith("Level0"))
{
IDocumentQuery<AdministrativeArea> query = currentSession.query(area.class, Query.index(indexToBeQueried))
.whereEquals("i", ccode);
results = currentSession.advanced().stream(query);
}
else
{
IDocumentQuery<AdministrativeArea> query = currentSession.query(area.class, Query.index(indexToBeQueried))
.whereEquals("i", ccode)
.andAlso()
.whereEquals("N1", sName);
results = currentSession.advanced().stream(query); // THIS IS WHERE IT DOESNT COME BACK
}
while(results.hasNext())
{
StreamResult<AdministrativeArea> adma = results.next();
adma.getDocument().properties = retrievePropertiesForArea(adma.getDocument(), currentSession);
writer.write(ow.writeValueAsString(adma.getDocument()));
writer.write(",");
}
(...)
currentSession.advanced().clear();
currentSession.close();
}
catch (Exception e)
{
System.out.println("Exception: " + e.getMessage() + e.getStackTrace());
}
}
};
if(!requestIsValid)
return Response.status(400).build();
else
return Response.ok(adminAreaStream).build();
}
The RavenDB error logs come up empty, as do the Tomcat error logs. The only thing that remotely resembles an error message relevant to this is something that shows up from "Gather debug info":
System.ArgumentNullException: Value cannot be null.
Parameter name: source
at System.Linq.Enumerable.Any[TSource](IEnumerable`1 source, Func`2 predicate)
at Raven.Server.Documents.Handlers.Debugging.QueriesDebugHandler.QueriesCacheList() in C:\Builds\RavenDB-Stable-4.1\src\Raven.Server\Documents\Handlers\Debugging\QueriesDebugHandler.cs:line 181
at Raven.Server.ServerWide.LocalEndpointClient.InvokeAsync(RouteInformation route, Dictionary`2 parameters) in C:\Builds\RavenDB-Stable-4.1\src\Raven.Server\ServerWide\LocalEndpointClient.cs:line 61
at Raven.Server.ServerWide.LocalEndpointClient.InvokeAndReadObjectAsync(RouteInformation route, JsonOperationContext context, Dictionary`2 parameters) in C:\Builds\RavenDB-Stable-4.1\src\Raven.Server\ServerWide\LocalEndpointClient.cs:line 91
at Raven.Server.Documents.Handlers.Debugging.ServerWideDebugInfoPackageHandler.WriteForDatabase(ZipArchive archive, JsonOperationContext jsonOperationContext, LocalEndpointClient localEndpointClient, String databaseName, String path) in C:\Builds\RavenDB-Stable-4.1\src\Raven.Server\Documents\Handlers\Debugging\ServerWideDebugInfoPackageHandler.cs:line 311
Thank you for any kinds of investigation hints you can give me.
UPDATE:
Same thing when moving the compiler and Tomcat JVM back to Java 1.8.

It appears that it has nothing to do with Java 11 (or 1.8), but simply that it had slipped my attention to close CloseableIterator<StreamResult<AdministrativeArea>> results; After adding a simple results.close(); everything appears to work as it should. If this wasn't the solution, I'll come back and update.

Related

P4API.net: how to use P4Callbacks delegates

I am working on a small tool to schedule p4 sync daily at specific times.
In this tool, I want to display the outputs from the P4API while it is running commands.
I can see that the P4API.net has a P4Callbacks class, with several delegates: InfoResultsDelegate, TaggedOutputDelegate, LogMessageDelegate, ErrorDelegate.
My question is: How can I use those, I could not find a single example online of that. A short example code would be amazing !
Note: I am quite a beginner and have never used delegates before.
Answering my own questions by an example. I ended up figuring out by myself, it is a simple event.
Note that this only works with P4Server. My last attempt at getting TaggedOutput from a P4.Connection was unsuccessful, they were never triggered when running a command.
So, here is a code example:
P4Server p4Server = new P4Server(syncPath);
p4Server.TaggedOutputReceived += P4ServerTaggedOutputEvent;
p4Server.ErrorReceived += P4ServerErrorReceived;
bool syncSuccess = false;
try
{
P4Command syncCommand = new P4Command(p4Server, "sync", true, syncPath + "\\...");
P4CommandResult rslt = syncCommand.Run();
syncSuccess=true;
//Here you can read the content of the P4CommandResult
//But it will only be accessible when the command is finished.
}
catch (P4Exception ex) //Will be caught only when the command has completely failed
{
Console.WriteLine("P4Command failed: " + ex.Message);
}
And the two methods, those will be triggered while the sync command is being executed.
private void P4ServerErrorReceived(uint cmdId, int severity, int errorNumber, string data)
{
Console.WriteLine("P4ServerErrorReceived:" + data);
}
private void P4ServerTaggedOutputEvent(uint cmdId, int ObjId, TaggedObject Obj)
{
Console.WriteLine("P4ServerTaggedOutputEvent:" + Obj["clientFile"]);
}

IllegalStateException for getRequestDispatcher [duplicate]

This method throws
java.lang.IllegalStateException: Cannot forward after response has been committed
and I am unable to spot the problem. Any help?
int noOfRows = Integer.parseInt(request.getParameter("noOfRows"));
String chkboxVal = "";
// String FormatId=null;
Vector vRow = new Vector();
Vector vRow1 = new Vector();
String GroupId = "";
String GroupDesc = "";
for (int i = 0; i < noOfRows; i++) {
if ((request.getParameter("chk_select" + i)) == null) {
chkboxVal = "notticked";
} else {
chkboxVal = request.getParameter("chk_select" + i);
if (chkboxVal.equals("ticked")) {
fwdurl = "true";
Statement st1 = con.createStatement();
GroupId = request.getParameter("GroupId" + i);
GroupDesc = request.getParameter("GroupDesc" + i);
ResultSet rs1 = st1
.executeQuery("select FileId,Description from cs2k_Files "
+ " where FileId like 'M%' and co_code = "
+ ccode);
ResultSetMetaData rsm = rs1.getMetaData();
int cCount = rsm.getColumnCount();
while (rs1.next()) {
Vector vCol1 = new Vector();
for (int j = 1; j <= cCount; j++) {
vCol1.addElement(rs1.getObject(j));
}
vRow.addElement(vCol1);
}
rs1 = st1
.executeQuery("select FileId,NotAllowed from cs2kGroupSub "
+ " where FileId like 'M%' and GroupId = '"
+ GroupId + "'" + " and co_code = " + ccode);
rsm = rs1.getMetaData();
cCount = rsm.getColumnCount();
while (rs1.next()) {
Vector vCol2 = new Vector();
for (int j = 1; j <= cCount; j++) {
vCol2.addElement(rs1.getObject(j));
}
vRow1.addElement(vCol2);
}
// throw new Exception("test");
break;
}
}
}
if (fwdurl.equals("true")) {
// throw new Exception("test");
// response.sendRedirect("cs2k_GroupCopiedUpdt.jsp") ;
request.setAttribute("GroupId", GroupId);
request.setAttribute("GroupDesc", GroupDesc);
request.setAttribute("vRow", vRow);
request.setAttribute("vRow1", vRow1);
getServletConfig().getServletContext().getRequestDispatcher(
"/GroupCopiedUpdt.jsp").forward(request, response);
}
forward/sendRedirect/sendError do NOT exit the method!
A common misunderstanding among starters is that they think that the call of a forward(), sendRedirect(), or sendError() would magically exit and "jump" out of the method block, hereby ignoring the remnant of the code. For example:
protected void doXxx() {
if (someCondition) {
sendRedirect();
}
forward(); // This is STILL invoked when someCondition is true!
}
This is thus actually not true. They do certainly not behave differently than any other Java methods (expect of System#exit() of course). When the someCondition in above example is true and you're thus calling forward() after sendRedirect() or sendError() on the same request/response, then the chance is big that you will get the exception:
java.lang.IllegalStateException: Cannot forward after response has been committed
If the if statement calls a forward() and you're afterwards calling sendRedirect() or sendError(), then below exception will be thrown:
java.lang.IllegalStateException: Cannot call sendRedirect() after the response has been committed
To fix this, you need either to add a return; statement afterwards
protected void doXxx() {
if (someCondition) {
sendRedirect();
return;
}
forward();
}
... or to introduce an else block.
protected void doXxx() {
if (someCondition) {
sendRedirect();
}
else {
forward();
}
}
To naildown the root cause in your code, just search for any line which calls a forward(), sendRedirect() or sendError() without exiting the method block or skipping the remnant of the code. This can be inside the same servlet before the particular code line, but also in any servlet or filter which was been called before the particular servlet.
In case of sendError(), if your sole purpose is to set the response status, use setStatus() instead.
Do not write any string before forward/sendRedirect/sendError
Another probable cause is that the servlet writes to the response while a forward() will be called, or has been called in the very same method.
protected void doXxx() {
out.write("<p>some html</p>");
// ...
forward(); // Fail!
}
The response buffer size defaults in most server to 2KB, so if you write more than 2KB to it, then it will be committed and forward() will fail the same way:
java.lang.IllegalStateException: Cannot forward after response has been committed
Solution is obvious, just don't write to the response in the servlet. That's the responsibility of the JSP. You just set a request attribute like so request.setAttribute("data", "some string") and then print it in JSP like so ${data}. See also our Servlets wiki page to learn how to use Servlets the right way.
Do not write any file before forward/sendRedirect/sendError
Another probable cause is that the servlet writes a file download to the response after which e.g. a forward() is called.
protected void doXxx() {
out.write(bytes);
// ...
forward(); // Fail!
}
This is technically not possible. You need to remove the forward() call. The enduser will stay on the currently opened page. If you actually intend to change the page after a file download, then you need to move the file download logic to page load of the target page. Basically: first create a temporary file on disk using the way mentioned in this answer How to save generated file temporarily in servlet based web application, then send a redirect with the file name/identifier as request param, and in the target page conditionally print based on the presence of that request param a <script>window.location='...';</script> which immediately downloads the temporary file via one of the ways mentioned in this answer Simplest way to serve static data from outside the application server in a Java web application.
Do not call forward/sendRedirect/sendError in JSP
Yet another probable cause is that the forward(), sendRedirect() or sendError() methods are invoked via Java code embedded in a JSP file in form of old fashioned way <% scriptlets %>, a practice which was officially discouraged since 2003. For example:
<!DOCTYPE html>
<html lang="en">
<head>
...
</head>
<body>
...
<% sendRedirect(); %>
...
</body>
</html>
The problem here is that JSP internally immediately writes template text (i.e. HTML code) via out.write("<!DOCTYPE html> ... etc ...") as soon as it's encountered. This is thus essentially the same problem as explained in previous section.
Solution is obvious, just don't write Java code in a JSP file. That's the responsibility of a normal Java class such as a Servlet or a Filter. See also our Servlets wiki page to learn how to use Servlets the right way.
See also:
What exactly does "Response already committed" mean? How to handle exceptions then?
Unrelated to your concrete problem, your JDBC code is leaking resources. Fix that as well. For hints, see also How often should Connection, Statement and ResultSet be closed in JDBC?
even adding a return statement brings up this exception, for which only solution is this code:
if(!response.isCommitted())
// Place another redirection
Typically you see this error after you have already done a redirect and then try to output some more data to the output stream. In the cases where I have seen this in the past, it is often one of the filters that is trying to redirect the page, and then still forwards through to the servlet. I cannot see anything immediately wrong with the servlet, so you might want to try having a look at any filters that you have in place as well.
Edit: Some more help in diagnosing the problem…
The first step to diagnosing this problem is to ascertain exactly where the exception is being thrown. We are assuming that it is being thrown by the line
getServletConfig().getServletContext()
.getRequestDispatcher("/GroupCopiedUpdt.jsp")
.forward(request, response);
But you might find that it is being thrown later in the code, where you are trying to output to the output stream after you have tried to do the forward. If it is coming from the above line, then it means that somewhere before this line you have either:
output data to the output stream, or
done another redirect beforehand.
Good luck!
You should add return statement while you are forwarding or redirecting the flow.
Example:
if forwardind,
request.getRequestDispatcher("/abs.jsp").forward(request, response);
return;
if redirecting,
response.sendRedirect(roundTripURI);
return;
This is because your servlet is trying to access a request object which is no more exist..
A servlet's forward or include statement does not stop execution of method block. It continues to the end of method block or first return statement just like any other java method.
The best way to resolve this problem just set the page (where you suppose to forward the request) dynamically according your logic. That is:
protected void doPost(request , response){
String returnPage="default.jsp";
if(condition1){
returnPage="page1.jsp";
}
if(condition2){
returnPage="page2.jsp";
}
request.getRequestDispatcher(returnPage).forward(request,response); //at last line
}
and do the forward only once at last line...
you can also fix this problem using return statement after each forward() or put each forward() in if...else block
I removed
super.service(req, res);
Then it worked fine for me
Bump...
I just had the same error. I noticed that I was invoking super.doPost(request, response); when overriding the doPost() method as well as explicitly invoking the superclass constructor
public ScheduleServlet() {
super();
// TODO Auto-generated constructor stub
}
As soon as I commented out the super.doPost(request, response); from within doPost() statement it worked perfectly...
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//super.doPost(request, response);
// More code here...
}
Needless to say, I need to re-read on super() best practices :p
After return forward method you can simply do this:
return null;
It will break the current scope.
If you see this on a Spring based web application, make sure you have your method annotated with #ResponseBody or the controller annotated with #RestController instead of #Controller. It will also throw this exception if a method returns JSON, but has not been configured to have that as the response, Spring will instead look for a jsp page to render and throw this exception.

IOException message not printed correctly when using Java 9 on Windows 10 set to Japan locale and language

An Exception is thrown in this particular block.
try
{
transport.m_readListener.onReadTransport(transport);
}
catch (IOException e)
{
->onIOException(e,transport);
}
The onIOException() method puts it on the log:
private void onIOException(IOException e, AbstractConnection connection)
{
String reason = e.getMessage();
...
log.error("Closing ",connection," because ",reason);
}
The reason variable in Java 8 shows a correct japanese phrase:
reason : 既存の接続はリモート ホストに強制的に切断されました。
(meaning: The existing connection was forcibly disconnected to the remote host)
When ran on Java 9, the exception message is now broken:
reason : 譌「蟄倥?ョ謗・邯壹?ッ繝ェ繝「繝シ繝? 繝帙せ繝医↓蠑キ蛻カ逧?縺ォ蛻?譁ュ縺輔l縺セ縺励◆縲?
The code block that checks if the Socket port is still open is inside a try catch block that catches the IOException. The message from the IOException is acquired via
String reason = e.getMessage();
if (null == reason) reason = e.toString();
Tried running the app with java.locale.providers=COMPAT,CLDR,SPI to make it behave like in Java 8 but nothing happens. Anyone has an idea on this issue? Can anyone help? Thanks!

ArangoDB Java-driver in web-environment: configure.init() blocks

i have a problem to run configure.init() in my Jetty-container (run-jetty-run in Eclipse with Springframework )
After reaching configure.init() the client-service blocks without any notice or exception.
If i run the same code in a console-java program it works.
I would expect output:
Enter init()
OK init()
Server-Version:2.6.1
Does somebody has any idea or experience with it ?
Java-Driver-version is 2.5.7.
Codesnippet:
public void arangoVersion() {
try {
configure = new ArangoConfigure();
write("Enter init()");
configure.init();
write("OK init()"); // never reached :(
arangoDriver = new ArangoDriver(configure);
write("Server-Version:" + arangoDriver.getVersion().getVersion());
} catch (ArangoException ax) {
write("Arango-Exception" + ax.getErrorMessage() + " , Nr. : "
+ ax.getCode());
} catch (Exception ex) {
write("Exception" + ex.getMessage() );
}
}
public void write( String text ) {
System.out.println( text );
// for web: logger.debug( text );
}
Thanks in advance
SOLVED
Are there different versions of httpclient.jar in your maven
dependencies? The java driver uses httpclient 4.3.6 which is not
compatible with older versions. – fceller Aug 28 at 8:20
Yes, indeed there was the mentioned version conflict with httpclient. An older httpclient-version was in an included (Eclipse-)project.
So configure.init() is working now.
(I would propose to catch the no-class-found-exception explitely in the Arango-Java-Driver and to make a version-check and output for httpclient. httpclient is widely spread.)
After updating the httpclient and resolving some small incompatibilities with my application the second problem occurs:
Now the ArangoDriver ran into the void with no visible reaction in my spring-application.
A debugging-session revealed that the actions of ArangoDriver where encapsulated in Springframework-transactions due AOP-coverage for all Spring-services and throws a NoClassFound-exception for the ArangoDriver.
After moving the Arango-java-driver in the same Maven-POM-layer as the SpringTX it was running perfectly.
Thanks to all.

play file wav j2me - IllegalArgumentException at Manager.createPlayer()

I got problem about play wav file in my application.
This is my error:
java.lang.IllegalArgumentException
at javax.microedition.media.Manager.createPlayer(), bci=8
at Tajwid.Tajwid.run(Tajwid.java:649)
at Tajwid.Tajwid.actionPerformed(Tajwid.java:186)
at com.sun.lwuit.util.EventDispatcher.fireActionSync(), bci=19
at com.sun.lwuit.util.EventDispatcher.fireActionEvent(EventDispatcher.java:257)
This is my code:
public void run() {
try {
InputStream is = getClass().getResourceAsStream("/tes.wav");
player = Manager.createPlayer(is, "audio/x-wav");
player.realize();
// get volume control for player and set volume to max
vc = (VolumeControl) player.getControl("VolumeControl");
if (vc != null) {
vc.setLevel(100);
}
player.prefetch();
player.start();
} catch (Exception e) {
e.printStackTrace();
}
Device Configuration : CLDC-1.1
Device Profile MIDP 2.0
Error message you've got has sufficient information to figure what went wrong in the code.
Look at it a bit closer:
java.lang.IllegalArgumentException
at javax.microedition.media.Manager.createPlayer()...
It says something went wrong in Manager.createPlayer(). From your code, it is apparent that you use method Manager.createPlayer(java.io.InputStream stream, java.lang.String type).
If you look into API documentation for the method you use (available online), you'll find the explanation when this exception occurs:
Throws:
java.lang.IllegalArgumentException - Thrown if stream is null.
Above means that stream parameter (is in your code) passed to the method is null.
You could add some logging right after initialization of the is to debug this issue easier:
InputStream is = getClass().getResourceAsStream("/tes.wav");
// add some logging to see if initialization was OK or not:
System.out.println("input stream is null: [" + (is == null) + "]");
That way, when running your MIDlet in emulator, you will see whether is was initialized as expected or not.
Actually, looking at the code I would guess that you made a typo in file name passed to getResourceAsStream: "/tes.wav" looks like a mis-typed "/test.wav".

Resources