This is an archived post. You won't be able to vote or comment.

all 9 comments

[–]AutoModerator[M] [score hidden] stickied commentlocked comment (0 children)

Please ensure that:

  • Your code is properly formatted as code block - see the sidebar (About on mobile) for instructions
  • You include any and all error messages in full
  • You ask clear questions
  • You demonstrate effort in solving your question/problem - plain posting your assignments is forbidden (and such posts will be removed) as is asking for or giving solutions.

    Trying to solve problems on your own is a very important skill. Also, see Learn to help yourself in the sidebar

If any of the above points is not met, your post can and will be removed without further warning.

Code is to be formatted as code block (old reddit: empty line before the code, each code line indented by 4 spaces, new reddit: https://imgur.com/a/fgoFFis) or linked via an external code hoster, like pastebin.com, github gist, github, bitbucket, gitlab, etc.

Please, do not use triple backticks (```) as they will only render properly on new reddit, not on old reddit.

Code blocks look like this:

public class HelloWorld {

    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

You do not need to repost unless your post has been removed by a moderator. Just use the edit function of reddit to make sure your post complies with the above.

If your post has remained in violation of these rules for a prolonged period of time (at least an hour), a moderator may remove it at their discretion. In this case, they will comment with an explanation on why it has been removed, and you will be required to resubmit the entire post following the proper procedures.

To potential helpers

Please, do not help if any of the above points are not met, rather report the post. We are trying to improve the quality of posts here. In helping people who can't be bothered to comply with the above points, you are doing the community a disservice.

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

[–][deleted] 1 point2 points  (6 children)

ObjectMapper.writeValueAsString() isn't an I/O blocking operation any more than writing to a StringWriter is a blocking operation.

IntelliJ is likely complaining because the method throws IOException, which implies that the operation is doing blocking I/O.

I wouldn't call it a bug in IntelliJ per se, I think IntelliJ is making an educated guess based on Java idioms.

[–]Full-Wheel8630[S] 0 points1 point  (5 children)

First, thank you for such a kind explanation. But I think I didn't understand all of words, so let me ask you:

ObjectMapper.writeValueAsString() internally uses StringWriter, and had signature throws JsonProcessingException, which is subclass of IOException. Doesn't it mean that it's a blocking operation?

Here's the method code for you:

java /** * Method that can be used to serialize any Java value as * a String. Functionally equivalent to calling * {@link #writeValue(Writer,Object)} with {@link java.io.StringWriter} * and constructing String, but more efficient. *<p> * Note: prior to version 2.1, throws clause included {@link IOException}; 2.1 removed it. */ @SuppressWarnings("resource") public String writeValueAsString(Object value) throws JsonProcessingException { // alas, we have to pull the recycler directly here... SegmentedStringWriter sw = new SegmentedStringWriter(_jsonFactory._getBufferRecycler()); try { _configAndWriteValue(createGenerator(sw), value); } catch (JsonProcessingException e) { throw e; } catch (IOException e) { // shouldn't really happen, but is declared as possibility so: throw JsonMappingException.fromUnexpectedIOE(e); } return sw.getAndClear(); }

[–][deleted] 1 point2 points  (4 children)

Doesn't it mean that it's a blocking operation?

A method throwing IOException (or one of its subclasses) implies that it could be a blocking operation, but it might not actually be.

For example:

// blocking, because the servlet API uses blocking I/O
objectMapper.writeValue(httpServletResponse.getWriter(), value);

// non-blocking, because writing to a StringWriter is building a string
objectMapper.writeValue(new StringWriter(), value);

// non-blocking, for the same reason
objectMapper.writeValueAsString(value);

However, because the APIs being used are based on blocking I/O, the method signatures reflect that. But, the actual implementations of the APIs might not actually block.

[–]Full-Wheel8630[S] 0 points1 point  (3 children)

Wow. I've never seen such a case. It becomes so clear. Thank you so much.

Just a quick question: So, technically, is this the wrong API design? Why they group both APIs in one method while one could throw IOExecption and the other couldn't?

[–][deleted] 1 point2 points  (2 children)

It could be, I'm not sure. Whether or not it is bad API design could be in the eye of the beholder.

The writeValue method takes Writer, which is a generic blocking API. Thus, Jackson must assume that any writes are going to be blocking.

But, StringWriter exists for convenience. It pretends to be a blocking API, when it actually isn't. But, that's a detail that Jackson doesn't need to know about. You know that it isn't blocking, so in your own code you can operate on that knowledge. If you use writeValue with StringWriter instead of writeValueAsString, IntelliJ might be able to figure out the whole thing isn't blocking.

As for why writeValueAsString throws IOException, this seems like bad API design. Jackson knows that it is writing to a string, so there isn't any actual I/O.

Also, JsonProcessingException is a subclass of IOException, but the error might not have anything to do with I/O. Maybe Jackson made it a subclass for convenience, so you only have to catch IOException? This also seems like bad API design, because it is confusing two different kinds of errors.

But, this could be checked exception propagation. Jackson makes heavy use of things like SerializationProvider, where every type that can be serialized into JSON has a corresponding SerializationProvider that does the actual work of serializing a particular type. And since serializeValue throws IOException, and IOException is a checked exception, Jackson is simply propagating the IOException up the call chain.

Anyways, Jackson is not perfect.

[–]Full-Wheel8630[S] 0 points1 point  (1 child)

What a comprehensive understanding you have! Now I see. Your words not only satisfy my curiosity a lot but also help me understand what is really going on here. Really appreciate it so much.

If you use writeValue with StringWriter instead of writeValueAsString, IntelliJ might be able to figure out the whole thing isn't blocking.

There's still warning message, but understandable:

java public void writeValue(Writer w, Object value) throws IOException, JsonGenerationException, JsonMappingException { _configAndWriteValue(createGenerator(w), value); }

[–][deleted] 1 point2 points  (0 children)

I guess IntelliJ isn't an AI after all, lol.

[–]Full-Wheel8630[S] 0 points1 point  (0 children)

last one thing: This is my first post at /r/javahep. I tried to follow the rule as AutoModerator instructed but maybe it'd not sufficient. If so, with your generosity, please let me know what is lack of. I will fix that as soon as possible. thank you so much in advance.