1

I send a post request from a java springboot application like this:

String requestBody = gson.toJson(sbert);
        System.out.println(requestBody); // If I print this, and use this in postman it works!
        HttpRequest add_request = HttpRequest.newBuilder()
                .uri(URI.create("http://localhost:4557/sbert_similarity"))
                .POST(HttpRequest.BodyPublishers.ofString(requestBody))
                .header("Content-Type", "application/json")
                .build();
        HttpResponse<String> response = client.sendAsync(add_request,
                HttpResponse.BodyHandlers.ofString()).get();

This is essentially what my fastapi service looks like:

from fastapi import FastAPI, Request
from pydantic import BaseModel
from sentence_transformers import SentenceTransformer, util
model = SentenceTransformer('all-MiniLM-L6-v2')
import pprint as pp
import uvicorn
from typing import Any

app = FastAPI()
class Item(BaseModel):
    user_input: str
    document: str
    
class ResponseItem(BaseModel):
    similarity: float

@app.post("/sbert_similarity")
def check_similarity(item: Item) -> ResponseItem:
    pp.pprint(item)
    sentences1 = [item.user_input]
    sentences2 = [item.document]
    cosine_score = 0
    embeddings1 = model.encode(sentences1, convert_to_tensor=True)
    embeddings2 = model.encode(sentences2, convert_to_tensor=True)
    cosine_score = util.cos_sim(embeddings1, embeddings2)
    
    return {
        "similarity" : cosine_score
    }

if __name__=="__main__":
    uvicorn.run("similarity_server:app",host='0.0.0.0', port=4557, reload=True, workers=3)

When I print out the returned json object I get:

{"detail":[{"loc":["body"],"msg":"field required","type":"value_error.missing"}]}

Which doesn't make sense considering the same json object I use for the post request works perfectly fine when I use it in postman.

My fastapi server says: INFO: 127.0.0.1:65066 - "POST /sbert_similarity HTTP/1.1" 422 Unprocessable Entity

Anyone know what's going on?

Thanks!

Edit:

So just a quick update it seems like from this code:

@app.post("/sbert_similarity_v3")
async def check_similarity(request: Request) -> Any:
    content_type = request.headers.get('Content-Type')
    
    if content_type is None:
        return 'No Content-Type provided.'
    elif content_type == 'application/json':
        try:
            json = await request.json()
            return json
        except JSONDecodeError:
            return 'Invalid JSON data.'
    else:
        return 'Content-Type not supported.'

there was a JSONDecodeError for all post requests sent from the Java Springboot application, I still don't know why that is though?

Second Edit:

So, now I have to ask why is the http client sending a null object as opposed to it's actual json object?

Chris
  • 18,724
  • 6
  • 46
  • 80
Steveit
  • 51
  • 1
  • 9
  • Hi, yes this is correct. The issue lies within Java, but I don't know why I am having this issue in java when I have the exact fields, I don't understand it at all, and most tutorials do the post request in this exact way so I still don't understand what's going on. – Steveit Jun 03 '23 at 06:25
  • Not only that, but the error message given by fastapi specifies what's missing and what's not and I assure you none of the fields are missing and none of the values are missing. If I send a postman request with those exact same details it sends but not in Java for some reason which is ridiculous. How is something so simple, so complicated, I don't even know where to look to resolve this issue. – Steveit Jun 03 '23 at 06:27

1 Answers1

1

The example below deomonstrates how to make a JSON POST request using HttpURLConnection. The issue in your code might or might not be with Apache's HttpClient (you would need to test this on your own), but might be originated from the requestBody you send to the server; hence, I would suggest you manually specify a JSON string first (before using other Java serialization libraries, such as gson, to convert Java Objects into JSON), as shown below, and see how that works.

Working Example

Python FastAPI server (taken from this answer)

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()


class User(BaseModel):
    user: str


@app.post('/')
def main(user: User):
    return user

Java Client example

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;


public class PostJSON {

    public static void main(String[] args) throws IOException {
        URL url = new URL("http://127.0.0.1:8000/");
        HttpURLConnection con = (HttpURLConnection) url.openConnection();
        con.setRequestMethod("POST");
        con.setRequestProperty("Content-Type", "application/json");
        con.setRequestProperty("Accept", "application/json");
        con.setDoOutput(true);
        String jsonInputString = "{\"user\": \"foo\"}";

        try (OutputStream os = con.getOutputStream()) {
            byte[] input = jsonInputString.getBytes(StandardCharsets.UTF_8);
            os.write(input, 0, input.length);
        }

        try (BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), StandardCharsets.UTF_8))) {
            StringBuilder response = new StringBuilder();
            String responseLine = null;
            while ((responseLine = br.readLine()) != null) {
                response.append(responseLine.trim());
            }
            System.out.println(con.getResponseCode() + " " + response);
        }
    }

}
Chris
  • 18,724
  • 6
  • 46
  • 80
  • 1
    Woah, that actually works. From further testing, it wasn't the JSON object that was the problem but rather it was something to do with the http client. I have no idea what the actual problem is though and I'm not sure how to figure out exactly what's going wrong with the http client. But yeah, thank you so much for your response! I was running into this issue quite a bit, I used the Java.net httpclient and the apache http client, both ways sometimes gave me this issue and sometimes it didnt, which makes it even more difficult to figure out what's wrong! – Steveit Jun 03 '23 at 08:56