Concept:
JAX-RS provides a Client API for creating clients to connect to the services with its fluent API approach.
The instances of Client are expensive to initialise, so there should be a minimum set of its reuse. WebTarget represents the specific
URI that will be invoked so it can easily be set into an instance of the Client before requesting.
For the Forecast Service (ForecastResource.java) given in the previous section, we can implement a web target to create the location web target
when requested.
WebTargetProducer created to implement this concepts of pooling Web target into an existing Forecast Service (ForeCastResource.java)
@ApplicationScoped
public class WebTargetProducer {
private Client client;
@PostConstruct
private void postConstruct() {
this.client = ClientBuilder.newClient();
}
@Produces
@Dependent
public WebTarget produceLocationWebTarget() {
return client.target("
http://192.168.0.38:8080")
.path("forecast-service")
.path("smartcity")
.path("location");
}
}
Commented out code replaced with the new class WebTargetProducer.
@Path("/forecast")
public class ForecastResource {
/* @Uri("location")
private WebTarget producer; */
private WebTargetProducer producer = new WebTargetProducer();
@Uri("temperature/{city}")
private WebTarget temperatureTarget;
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getLocationWithTemperature() {
long startTime = System.currentTimeMillis();
ServiceResponse response = new ServiceResponse();
/* List<Location> locations = locationTarget.request()
.get(new GenericType<List<Location>>() {}); */
List<Location> locations = producer.produceLocationWebTarget()
.request()
.get(new GenericType<List<Location>>() {});
locations.forEach(location -> {
Temperature temperature = temperatureTarget
.resolveTemplate("city", location.getName())
.request()
.get(Temperature.class);
response.getForecast()
.add(new Forecast(location,temperature));
});
long endTime = System.currentTimeMillis();
response.setProcessingTime(endTime-startTime);
return Response.ok(response).build();
}
}
ISSUE
only the following url is producing the error with this new code implementation
HTTP Status 500 - Internal Server Error
type Exception report
messageInternal Server Error
descriptionThe server encountered an internal error that prevented it from fulfilling this request.
exception
javax.servlet.ServletException: java.lang.NullPointerException: Cannot invoke "javax.ws.rs.client.Client.target(String)" because "this.client" is null
root cause
java.lang.NullPointerException: Cannot invoke "javax.ws.rs.client.Client.target(String)" because "this.client" is null
Payara Console.
Payara Micro URLs:
http://192.168.0.38:8080/forecast-service
'forecast-service' REST Endpoints:
GET /forecast-service/smartcity/application.wadl
GET /forecast-service/smartcity/forecast
GET /forecast-service/smartcity/location
GET /forecast-service/smartcity/temperature/{city}
]]
[2021-03-16T23:33:43.911+0000] [] [INFO] [] [PayaraMicro] [tid: _ThreadID=1 _ThreadName=main] [timeMillis: 1615937623911] [levelValue: 800] Payara Micro 5.2021.1 #badassmicrofish (b
uild 2818) ready in 10,979 (ms)
[2021-03-16T23:34:01.025+0000] [] [WARNING] [] [javax.enterprise.web] [tid: _ThreadID=86 _ThreadName=http-thread-pool::http-listener(1)] [timeMillis: 1615937641025] [levelValue: 900]
[[
StandardWrapperValve[com.smartcity.domain.SmartCityServices]: Servlet.service() for servlet com.smartcity.domain.SmartCityServices threw exception
java.lang.NullPointerException: Cannot invoke "javax.ws.rs.client.Client.target(String)" because "this.client" is null
at com.smartcity.services.WebTargetProducer.produceLocationWebTarget(WebTargetProducer.java:24)
at com.smartcity.services.ForecastResource.getLocationWithTemperature(ForecastResource.java:51)
Regards
Zahid