0

TL;DR Am using org.mortbay.jetty:jetty:6.1.26 in my JUnits to Stub a server. I was hoping to get predetermined content in output. However am getting exception java.net.ConnectException: Connection refused: no further information. When I hit the endpoint from web browser, I do not get response immediately but after all JUnits are completed and Jetty shut the server (I get expected response in browser as well as Socket closed exception in app logs). I searched few stackoverflow posts but couldn't progress much and hence need help

Details: Application code we have is (successfully) getting required information from external clients by reading that data, parsing it and finally saving that data. Below is how code looks like

            HTTPUtilities.performGet(uri)
                .thenApply(HTTPUtilities::httpResponseToReader)
                .thenApply(reader -> parseContent(reader, id))
                .thenAccept(idDetailsList -> idRepository.saveAll(idDetailsList))
                .whenComplete((resp, err) -> {
                    if (err == null) {
                        log.info("Data for {} is successfully saved", id);
                    } else {
                        log.error("Exception encountered for URI {} / id : {}. Message: -> {} ", uri, id, err.getMessage());
                    }
                });

My intent is to Stub first method of above CompletableFuture which is HTTPUtilities.performGet(uri). It's a static method and its code looks like below

    HttpUriRequest request = RequestBuilder.get()
            .setUri(uri)
            .setHeader(HttpHeaders.ACCEPT, HEADER_ACCEPT_CONSTANT)
            .setHeader(HttpHeaders.USER_AGENT, HEADER_USER_AGENT_CONSTANT)
            .build();

    CompletableFuture<HttpResponse> resp = new CompletableFuture<>();
    executorService.execute(() -> {
        try (CloseableHttpClient httpclient = HttpClients.custom().setDefaultRequestConfig(config).build();
             CloseableHttpResponse response = httpclient.execute(request)) {
                resp.complete(response);
                log.info("Successfully returning response for URL: {}", uri);
        } catch (NullPointerException ex) {
            log.error("NullPointerException encountered when performing GET against URL {} with message {}", uri, ex.getCause());
            resp.completeExceptionally(ex);
        } catch (IOException ex) {
            log.error("IOException encountered when performing GET against URL {} with message {}", uri, ex.getCause());
            resp.completeExceptionally(ex);
        }
    });

    return resp;

This code works fine for actual calls. However, it fails with below stack trace when run from JUnits where HTTP calls are stubbed using Jetty. Below stacktrace is generated when code reaches CloseableHttpResponse response = httpclient.execute(request) line in above call.

java.net.ConnectException: Connection refused: no further information
    at java.base/sun.nio.ch.Net.pollConnect(Native Method)
    at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:672)
    at java.base/sun.nio.ch.NioSocketImpl.timedFinishConnect(NioSocketImpl.java:542)
    at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:597)
    at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327)
    at java.base/java.net.Socket.connect(Socket.java:633)
    at org.apache.http.conn.socket.PlainConnectionSocketFactory.connectSocket(PlainConnectionSocketFactory.java:75)
    at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:376)

Below is code from JUnit Test class

@ExtendWith(MockitoExtension.class)
public class IdRetreieveAndSaveTest {

    @InjectMocks
    UpdateIdData updateIdData;

    @BeforeAll
    static void initial() throws Exception {

        //Stub to replace actual call
        Server server = new Server(stubbedPort);
        Context contentOkContext = new Context(server, stubbedContext);
        contentOkContext.setHandler(new HttpCustomHandler());
        server.setStopAtShutdown(true);
        server.start();

    }
    
    @Test
    void updateIdDataTest() {
    
        List<IdData> resp = new ArrayList<>();
        updateIdData.invokeHttpAndSave(id);
        assertEquals(100, resp.size());
    
    }

}

and finally helper class for JUnit

public class HttpCustomHandler extends AbstractHandler {

    @Override
    public void handle(String s, HttpServletRequest httpServletRequest, HttpServletResponse response, int i) throws IOException {
        OutputStream out = response.getOutputStream();
        try (ByteArrayISO8859Writer writer = new ByteArrayISO8859Writer()) {
            writer.write(codeThatReturnsSampleDataFromExternalClient());
            writer.flush();
            response.setIntHeader(HttpHeaders.CONTENT_LENGTH, writer.size());
            writer.writeTo(out);
            out.flush();
        };
    }

}

I verified that port is up and listening during Junit execution. Below is response when at breakpoint during JUnit execution in debug mode and these lines disappear for same command once JUnit test execution completes

netstat -ano | Select-String -pattern "65500"

  TCP    0.0.0.0:65500          0.0.0.0:0              LISTENING       27448
  TCP    [::]:65500             [::]:0                 LISTENING       27448

Thank you in advance

2
  • 1
    Jetty 6.x was declared End of Life back in 2010 (current supported versions of Jetty are 10.x, 11.x, and even 12.x) - Your version contains none of the fixes mandated by various browsers (like Chrome and Safari) and does not represent the nature of HTTP in today's internet. (yes, it has changed, HTTP 1.x RFC2616, was replaced by RFC7230 for HTTP/1.1, which was replaced by RFC9112 for HTTP/1.1), along with a long collection of related spec changes (like Cookie and Host) Commented Feb 6, 2023 at 2:31
  • That helped resolve issue Commented Feb 12, 2023 at 19:29

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.