How I can trigger the api reading via using a queue? - api

In my application I consume an api that receives data from a serial port:
import 'package:http/http.dart' as http;
import 'package:flutter_libserialport/flutter_libserialport.dart';
class SerialRead {
final SerialPort port;
final Api api;
SerialRead(this.port,this.api);
void read(){
if (!port.openReadWrite()) {
print(SerialPort.lastError);
exit(-1);
}
final reader = SerialPortReader(port);
reader.stream.listen((data) {
api.consume(data);
});
}
}
class Api
{
final String __base_url = "https://example.com";
final dynamic _client;
final String username;
final String password;
Api(this.username,this.password): _client=http.Client();
Fitire<void> consume(var data) async {
final Uri url = Uri.parse(__base_url + "/serial_data");
var response = await _client.post(url,[
'X-username': username,
'X-password': password
],body:data);
// Handle response here
}
}
void main(){
final Api api = Api('chuck','norris');
final SerialRead read = SerialRead('/dev/ttyACM0',api);
read.read();
}
The code above it may read and consume the data but it may be cases where too many requests are performed upon the api, that it may trigger 429 too many requests. In order to avoid I want somehow to requlate the rate I perform the http calls.
As a means to do it is to use the retry library https://pub.dev/packages/retry but if I do retry I may lose some data that has been read upon serial.
Therefore, during reading I want to enqueue it into a FiFO queue and via a seperate thread to consume the api:
import 'package:http/http.dart' as http;
import 'package:flutter_libserialport/flutter_libserialport.dart';
final Queue<dynamic> queue = Queue<dynamic>();
class SerialRead {
final SerialPort port;
SerialRead(this.port);
void read(){
if (!port.openReadWrite()) {
print(SerialPort.lastError);
exit(-1);
}
final reader = SerialPortReader(port);
reader.stream.listen((data) {
values.addLast(data);
});
}
}
class Api
{
final String __base_url = "https://example.com";
final dynamic _client;
final String username;
final String password;
Api(this.username,this.password): _client=http.Client();
void consume(){
final dynamic data = queue.removeFirst();
// For simplicity I ommit checks
final Uri url = Uri.parse(__base_url + "/serial_data");
var response = await _client.post(url,[
'X-username': username,
'X-password': password
],body:data);
// Handle response here
}
}
void main(){
final Api api = Api('chuck','norris');
final SerialRead read = SerialRead('/dev/ttyACM0',api);
// Somehow trigger the api Reading
}
In the example above how I can in some sort of seperate thread trigger the consume method at api Class?

Related

Cannot Interrupt HttpClient.GetStreamAsync by means of CancellationToken in ASP.NET Core

I'm trying to send an http request to an AXIS Camera in order to receive a stream.
Everything works fine except that I can't get to use CancellationToken to cancel the request when it is no more needed. I've the following architecture:
Blazor client:
// LiveCamera.razor
<img src="CameraSystem/getStream" onerror="[...]" alt="">
ASP.NET Core Server:
// CameraSystemController.cs
[ApiController]
[Route("[controller]")]
public class CameraSystemController : Controller
{
[HttpGet("getStream")]
public async Task<IActionResult> GetStream()
{
Stream stream = await Device_CameraStandard.GetStream();
if (stream != null) {
Response.Headers.Add("Cache-Control", "no-cache");
FileStreamResult result = new FileStreamResult(stream, _contentTypeStreaming) {
EnableRangeProcessing = true
};
return result;
} else {
return new StatusCodeResult((int)HttpStatusCode.ServiceUnavailable);
}
}
}
Class accessing the camera:
// Device_CameraStandard.cs
internal class Device_CameraStandard
{
private HttpClient _httpClient;
private static CancellationTokenSource _tokenSource;
private System.Timers.Timer _keepAliveTimer;
internal Device_CameraStandard() {
_keepAliveTimer = new System.Timers.Timer();
_keepAliveTimer.Interval = 3000;
_keepAliveTimer.Elapsed += KeepAliveTimeout;
_tokenSource = new CancellationTokenSource();
[...]
}
internal async Task<Stream> GetStream()
{
return await _httpClient.GetStreamAsync("http://[...]/axis-cgi/mjpg/video.cgi?&camera=1", _tokenSource.Token);
}
// Invoked periodically by client from LiveCamera.razor.cs, not included here
internal void KeepAlive()
{
LLogger.Debug("KeepAlive!");
_keepAliveTimer.Stop();
_keepAliveTimer.Start();
}
private void KeepAliveTimeout(object sender, ElapsedEventArgs e)
{
LLogger.Debug("Timeout!");
_keepAliveTimer.Stop();
_tokenSource.Cancel();
_tokenSource.Dispose();
_tokenSource = new CancellationTokenSource();
}
}
However, even if all clients leave LiveCamera.razor page and the _keepAliveTimer elapses and the CancellationTokenSource is canceled, the request is not canceled. I can see it from the fact that bandwidth usage does not decreases (the "receiving" bandwitdh, indicating that Server is still receiving data from camera), it only decreases if I close the browser tab.
Could you please help me to understand what am I doing wrong? Thanks
EDIT: In the end, even after following the suggestion of observing the token in all code parts where the returned stream was used, included the controller, I ended up discovering that the tag
// LiveCamera.razor
<img src="CameraSystem/getStream" onerror="[...]" alt="">
was causing the client to never stop sending requests. Thus I had to use a workaround to force client to stop sending requests before leaving LiveCamera.razor page.

Reading RequestBody distrupts flow in ASP.NET Core 2.2 gateway

I have a middleware to track performance of my custom developed gateway in ASP.NET Core 2.2 API. I have used the this post from StackOverflow.
Basically the main part is as follows :
public class ResponseRewindMiddleware {
private readonly RequestDelegate next;
public ResponseRewindMiddleware(RequestDelegate next) {
this.next = next;
}
public async Task Invoke(HttpContext context) {
Stream originalBody = context.Response.Body;
/* MY CODE COMES HERE */
try {
using (var memStream = new MemoryStream()) {
context.Response.Body = memStream;
await next(context);
memStream.Position = 0;
string responseBody = new StreamReader(memStream).ReadToEnd();
memStream.Position = 0;
await memStream.CopyToAsync(originalBody);
}
} finally {
context.Response.Body = originalBody;
}
}
This code runs OK. But I want to log the input (a JSON body) to the gateway and I add the following lines :
using (System.IO.StreamReader rd = new System.IO.StreamReader(context.Request.Body))
{
bodyStr = rd.ReadToEnd();
}
This reads the input body from Request but the flow is broken and the rest of the process does not flow resulting in a "HTTP 500 Internal Server Error". I assume reading the Request body via a Stream breaks something.
How can I read the Request body without breaking the flow?
The idea is to call EnableBuffering to enable multiple read, and then to not dispose the request body after you have done reading it. The following works for me.
// Enable the request body to be read in the future
context.Request.EnableBuffering();
// Read the request body, but do not dispose it
var stream = new StreamReader(context.Request.Body);
string requestBody = await stream.ReadToEndAsync();
// Reset to the origin so the next read would start from the beginning
context.Request.Body.Seek(0, SeekOrigin.Begin);

RabbitMQ MQTT Adapter and Paho MQTT client

I’m using RabbitMQ MQTT Adapter and Paho MQTT client.
RabbitMQ version: {rabbitmq_mqtt,"RabbitMQ MQTT Adapter","3.2.1"}
Paho MQTT client version:
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>RELEASE</version>
</dependency>
Please see code inline.
I’m trying to understand if, the subscriber queue can be durable without expiration time. And If the messages can be durable also.
As I understood from RabbitMQ documentation, each time a subscriber subscribes to a topic
RabbitMQ will create a queue with this naming convention:
mqtt-subscription-<ClientName>qos<ClientQOS>
This queue has an expiration time, how can I create a queue without an expiration time? Can I change this queue expiration time to infinite?
As for now each time I run this command: “service rabbitmq-server restart”
The messages in the queue get deleted.
How can I prevent this? Is there a way I can keep the messages in the queue after restart?
In RabbitMQ management UI, I can see under “Publish message” -> “Delivery mode:” which can be “2-persistent”.
If I use management UI to publish messages with Delivery mode = 2-persistent. The messages will be in the queue after service restart.
How can I achieve the same using Paho MQTT Client?
// Heavily based on RabbitMQ MQTT adapter test case code!
// first, import the RabbitMQ Java client
// and the Paho MQTT client classes, plus any other
// requirements
import com.rabbitmq.client.*;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttTopic;
import org.eclipse.paho.client.mqttv3.internal.NetworkModule;
import org.eclipse.paho.client.mqttv3.internal.TCPNetworkModule;
// import org.eclipse.paho.client.mqttv3.internal.trace.Trace;
import org.eclipse.paho.client.mqttv3.internal.wire.MqttOutputStream;
import org.eclipse.paho.client.mqttv3.internal.wire.MqttPublish;
import javax.net.SocketFactory;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.util.*;
/***
* MQTT v3.1 tests
* TODO: synchronise access to variables
*/
public class MqttTestClean implements MqttCallback {
// setup some variables which define where the MQTT broker is
private final String host = "0.0.0.0";
private final int port = 1883;
private final String brokerUrl = "tcp://" + host + ":" + port;
private String clientId;
private String clientId3;
private MqttClient client;
private MqttClient client3;
private MqttConnectOptions conOpt;
private ArrayList<MqttMessage> receivedMessages;
// specify a message payload - doesn't matter what this says, but since MQTT expects a byte array
// we convert it from string to byte array here
private final byte[] payload = "This payload was published on MQTT and read using AMQP.".getBytes();
// specify the topic to be used
private final String topic = "topic/proxy/1.0.0/Report/*";
private int testDelay = 2000;
private long lastReceipt;
private boolean expectConnectionFailure;
private ConnectionFactory connectionFactory;
private Connection conn;
private Channel ch;
// override 10s limit
private class MyConnOpts extends MqttConnectOptions {
private int keepAliveInterval = 60;
#Override
public void setKeepAliveInterval(int keepAliveInterval) {
this.keepAliveInterval = keepAliveInterval;
}
#Override
public int getKeepAliveInterval() {
return keepAliveInterval;
}
}
public void setUpMqtt() throws MqttException {
clientId = getClass().getSimpleName() + ((int) (10000*Math.random()));
client = new MqttClient(brokerUrl, clientId);
conOpt = new MyConnOpts();
setConOpts(conOpt);
receivedMessages = new ArrayList<MqttMessage>();
expectConnectionFailure = false;
}
public void tearDownMqtt() throws MqttException {
try {
client.disconnect();
} catch (Exception _) {}
}
private void setUpAmqp() throws Exception {
connectionFactory = new ConnectionFactory();
connectionFactory.setHost(host);
conn = connectionFactory.newConnection();
ch = conn.createChannel();
}
private void tearDownAmqp() throws IOException {
conn.close();
}
private void setConOpts(MqttConnectOptions conOpts) {
conOpts.setCleanSession(true);
conOpts.setKeepAliveInterval(60);
}
private void publish(MqttClient client, String topicName, int qos, byte[] payload) throws MqttException {
MqttTopic topic = client.getTopic(topicName);
MqttMessage message = new MqttMessage(payload);
message.setQos(qos);
MqttDeliveryToken token = topic.publish(message);
token.waitForCompletion();
}
public void connectionLost(Throwable cause) {
if (!expectConnectionFailure)
System.out.println("Connection unexpectedly lost");
}
public void messageArrived(String topic, MqttMessage message) throws Exception {
lastReceipt = System.currentTimeMillis();
System.out.println("-------------------------------------------------");
System.out.println("------------------" + lastReceipt + "-------------------------------");
System.out.println("------------------" + message.toString() + "-------------------------------");
receivedMessages.add(message);
}
public void deliveryComplete(IMqttDeliveryToken token) {
}
public void run() {
try {
setUpMqtt(); // initialise the MQTT connection
setUpAmqp(); // initialise the AMQP connection
connect();
//String queue = ch.queueDeclare().getQueue();
// String queue = ch.queueDeclare("mqtt-subscription-Snabel-3qos1", true, false, false, null).getQueue();
//ch.queueBind(queue, "amq.topic", "sci-topic.sc.proxy_1393.1.0.0.ApReport.*"/*topic*/);
client.connect(conOpt);
publish(client, "topic/proxy/1.0.0/Report/123456789",1, payload); // publish the MQTT message
client.disconnect();
Thread.sleep(testDelay);
tearDownAmqp(); // cleanup AMQP resources
tearDownMqtt(); // cleanup MQTT resources*/
disConnect();
} catch (Exception mqe) {
mqe.printStackTrace();
}
}
private void connect() throws Exception {
clientId3 = "Test-3";
client3 = new MqttClient(brokerUrl, clientId3);
MqttConnectOptions connOpts = new MqttConnectOptions();
connOpts.setCleanSession(false);
client3.connect(connOpts);
client3.setCallback(this);
client3.subscribe(topic);
if(!client3.isConnected()){
System.out.println("Not Connected");
return;
}
System.out.println("Connected");
}
private void disConnect() throws Exception {
try {
client3.disconnect();
} catch (Exception _) {}
}
public static void main(String[] args) {
MqttTest mqt = new MqttTest();
mqt.run();
}
}
This was a RabbitMQ bug:
http://rabbitmq.1065348.n5.nabble.com/MQTT-plugin-message-delivery-mode-td32925.html
It was fixed in:
http://www.rabbitmq.com/release-notes/README-3.2.4.txt

getting an error while acessing google calendar API. Null pointer exception

I get a error message below .. when I run the code for hitting google Calendar API.There is a client_secrets.json file that has the credentials (client ID and redirectID) . I unzipped and ran the package google gave, it successfully runs and I could see that by a "Success,Add code here"message. after which it throws me a nullpointer exception for which I'm not sure what has gone wrong.please help. Downloaded the sample project from here https://developers.google.com/api-client-library/java/apis/calendar/v3
May 01, 2014 12:59:42 PM com.google.api.client.util.store.FileDataStoreFactory setPermissionsToOwnerOnly
WARNING: unable to change permissions for everybody: C:\Users\Aishwarya Anand\.store\calendar_sample
May 01, 2014 12:59:42 PM com.google.api.client.util.store.FileDataStoreFactory setPermissionsToOwnerOnly
WARNING: unable to change permissions for owner: C:\Users\Aishwarya Anand\.store\calendar_sample
Success! Now add code here.
inserting event ...
Aish Event from the new Google API
2014-05-01T16:59:42.545Z
2014-05-01T17:59:42.545Z
java.lang.NullPointerException
at com.google.api.client.repackaged.com.google.common.base.Preconditions.checkNotNull(Preconditions.java:191)
at com.google.api.client.util.Preconditions.checkNotNull(Preconditions.java:127)
at com.google.api.client.json.jackson2.JacksonFactory.createJsonParser(JacksonFactory.java:96)
at com.google.api.client.json.JsonObjectParser.parseAndClose(JsonObjectParser.java:85)
at com.google.api.client.json.JsonObjectParser.parseAndClose(JsonObjectParser.java:81)
at com.google.api.client.auth.oauth2.TokenResponseException.from(TokenResponseException.java:88)
at com.google.api.client.auth.oauth2.TokenRequest.executeUnparsed(TokenRequest.java:287)
at com.google.api.client.auth.oauth2.TokenRequest.execute(TokenRequest.java:307)
at com.google.api.client.auth.oauth2.Credential.executeRefreshToken(Credential.java:570)
at com.google.api.client.auth.oauth2.Credential.refreshToken(Credential.java:489)
at com.google.api.client.auth.oauth2.Credential.intercept(Credential.java:217)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:859)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:410)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:343)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:460)
at com.google.api.services.samples.calendar.cmdline.CalendarSample.insertEventTest(CalendarSample.java:170)
at com.google.api.services.samples.calendar.cmdline.CalendarSample.main(CalendarSample.java:116)
Class here,
package com.google.api.services.samples.calendar.cmdline;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.DateTime;
import com.google.api.client.util.store.DataStoreFactory;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.calendar.Calendar;
import com.google.api.services.calendar.CalendarScopes;
import com.google.api.services.calendar.model.*;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Date;
import java.util.TimeZone;
public class CalendarSample {
/**
* Be sure to specify the name of your application. If the application name is {#code null} or
* blank, the application will log a warning. Suggested format is "MyCompany-ProductName/1.0".
*/
private static final String APPLICATION_NAME = "Caritas-CalendarAPI/1.0";
/** Directory to store user credentials. */
private static final java.io.File DATA_STORE_DIR =
new java.io.File(System.getProperty("user.home"), ".store/calendar_sample");
/**
* Global instance of the {#link DataStoreFactory}. The best practice is to make it a single
* globally shared instance across your application.
*/
private static FileDataStoreFactory dataStoreFactory;
/** Global instance of the JSON factory. */
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
/** Global instance of the HTTP transport. */
private static HttpTransport httpTransport;
#SuppressWarnings("unused")
private static Calendar client;
/** Authorizes the installed application to access user's protected data. */
private static Credential authorize() throws Exception {
// load client secrets
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY,
new InputStreamReader(CalendarSample.class.getResourceAsStream("/client_secrets.json")));
// Set up authorization code flow.
// Ask for only the permissions you need. Asking for more permissions will
// reduce the number of users who finish the process for giving you access
// to their accounts. It will also increase the amount of effort you will
// have to spend explaining to users what you are doing with their data.
// Here we are listing all of the available scopes. You should remove scopes
// that you are not actually using.
Set<String> scopes = new HashSet<String>();
scopes.add(CalendarScopes.CALENDAR);
scopes.add(CalendarScopes.CALENDAR_READONLY);
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
httpTransport, JSON_FACTORY, clientSecrets, scopes)
.setDataStoreFactory(dataStoreFactory)
.build();
// authorize
return new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
}
public static void main(String[] args) {
try {
// initialize the transport
httpTransport = GoogleNetHttpTransport.newTrustedTransport();
// initialize the data store factory
dataStoreFactory = new FileDataStoreFactory(DATA_STORE_DIR);
// authorization
Credential credential = authorize();
// set up global Calendar instance
client = new Calendar.Builder(httpTransport, JSON_FACTORY, credential).setApplicationName(APPLICATION_NAME).build();
System.out.println("Success! Now add code here.");
insertEventTest();
//getEventList();
//getEventTest();
//sertEventTest();
} catch (IOException e) {
System.err.println(e.getMessage());
} catch (Throwable t) {
t.printStackTrace();
}
System.exit(1);
}
private static void getEventList() throws IOException {
String pageToken = null;
do {
Events events = client.events().list("primary").setPageToken(pageToken).execute();
List<Event> items = events.getItems();
for (Event event : items) {
System.out.println(" id: " + event.getId() + "; summary: " + event.getSummary());
}
pageToken = events.getNextPageToken();
} while (pageToken != null);
}
private static void getEventTest() throws IOException {
String eventId = "idkoi3c55lvegs2ev333u28grk5c";
Event event = client.events().get("primary", eventId).execute();
System.out.println(event.getSummary());
}
private static void insertEventTest() throws IOException {
System.out.println("inserting event ...");
Event event = new Event();
event.setSummary("Aish Event from the new Google API");
event.setLocation("Somewhere");
System.out.println(event.getSummary());
Date startDate = new Date();
Date endDate = new Date(startDate.getTime() + 3600000);
DateTime start = new DateTime(startDate, TimeZone.getTimeZone("UTC"));
event.setStart(new EventDateTime().setDateTime(start));
System.out.println(start.toStringRfc3339());
DateTime end = new DateTime(endDate, TimeZone.getTimeZone("UTC"));
event.setEnd(new EventDateTime().setDateTime(end));
System.out.println(end.toStringRfc3339());
Event createdEvent = client.events().insert("primary", event).execute();
System.out.println("event id" + createdEvent.getId());
}
}

Maximum threads issue

To begin with, I checked the discussions regarding this issue and couldn't find an answer to my problem and that's why I'm opening this question.
I've set up a web service using restlet 2.0.15.The implementation is only for the server. The connections to the server are made through a webpage, and therefore I didn't use ClientResource.
Most of the answers to the exhaustion of the thread pool problem suggested the inclusion of
#exhaust + #release
The process of web service can be described as a single function.Receive GET requests from the webpage, query the database, frame the results in XML and return the final representation. I used a Filter to override the beforeHandle and afterHandle.
The code for component creation code:
Component component = new Component();
component.getServers().add(Protocol.HTTP, 8188);
component.getContext().getParameters().add("maxThreads", "512");
component.getContext().getParameters().add("minThreads", "100");
component.getContext().getParameters().add("lowThreads", "145");
component.getContext().getParameters().add("maxQueued", "100");
component.getContext().getParameters().add("maxTotalConnections", "100");
component.getContext().getParameters().add("maxIoIdleTimeMs", "100");
component.getDefaultHost().attach("/orcamento2013", new ServerApp());
component.start();
The parameters are the result of a discussion present in this forum and modification by my part in an attempt to maximize efficiency.
Coming to the Application, the code is as follows:
#Override
public synchronized Restlet createInboundRoot() {
// Create a router Restlet that routes each call to a
// new instance of HelloWorldResource.
Router router = new Router(getContext());
// Defines only one route
router.attach("/{taxes}", ServerImpl.class);
//router.attach("/acores/{taxes}", ServerImplAcores.class);
System.out.println(router.getRoutes().size());
OriginFilter originFilter = new OriginFilter(getContext());
originFilter.setNext(router);
return originFilter;
}
I used an example Filter found in a discussion here, too. The implementation is as follows:
public OriginFilter(Context context) {
super(context);
}
#Override
protected int beforeHandle(Request request, Response response) {
if (Method.OPTIONS.equals(request.getMethod())) {
Form requestHeaders = (Form) request.getAttributes().get("org.restlet.http.headers");
String origin = requestHeaders.getFirstValue("Origin", true);
Form responseHeaders = (Form) response.getAttributes().get("org.restlet.http.headers");
if (responseHeaders == null) {
responseHeaders = new Form();
response.getAttributes().put("org.restlet.http.headers", responseHeaders);
responseHeaders.add("Access-Control-Allow-Origin", origin);
responseHeaders.add("Access-Control-Allow-Methods", "GET,POST,DELETE");
responseHeaders.add("Access-Control-Allow-Headers", "Content-Type");
responseHeaders.add("Access-Control-Allow-Credentials", "true");
response.setEntity(new EmptyRepresentation());
return SKIP;
}
}
return super.beforeHandle(request, response);
}
#Override
protected void afterHandle(Request request, Response response) {
if (!Method.OPTIONS.equals(request.getMethod())) {
Form requestHeaders = (Form) request.getAttributes().get("org.restlet.http.headers");
String origin = requestHeaders.getFirstValue("Origin", true);
Form responseHeaders = (Form) response.getAttributes().get("org.restlet.http.headers");
if (responseHeaders == null) {
responseHeaders = new Form();
response.getAttributes().put("org.restlet.http.headers", responseHeaders);
responseHeaders.add("Access-Control-Allow-Origin", origin);
responseHeaders.add("Access-Control-Allow-Methods", "GET,POST,DELETE"); //
responseHeaders.add("Access-Control-Allow-Headers", "Content-Type");
responseHeaders.add("Access-Control-Allow-Credentials", "true");
}
}
super.afterHandle(request, response);
Representation requestRepresentation = request.getEntity();
if (requestRepresentation != null) {
try {
requestRepresentation.exhaust();
} catch (IOException e) {
// handle exception
}
requestRepresentation.release();
}
Representation responseRepresentation = response.getEntity();
if(responseRepresentation != null) {
try {
responseRepresentation.exhaust();
} catch (IOException ex) {
Logger.getLogger(OriginFilter.class.getName()).log(Level.SEVERE, null, ex);
} finally {
}
}
}
The responseRepresentation does not have a #release method because it crashes the processes giving the warning WARNING: A response with a 200 (Ok) status should have an entity (...)
The code of the ServerResource implementation is the following:
public class ServerImpl extends ServerResource {
String itemName;
#Override
protected void doInit() throws ResourceException {
this.itemName = (String) getRequest().getAttributes().get("taxes");
}
#Get("xml")
public Representation makeItWork() throws SAXException, IOException {
DomRepresentation representation = new DomRepresentation(MediaType.TEXT_XML);
DAL dal = new DAL();
String ip = getRequest().getCurrent().getClientInfo().getAddress();
System.out.println(itemName);
double tax = Double.parseDouble(itemName);
Document myXML = Auxiliar.getMyXML(tax, dal, ip);
myXML.normalizeDocument();
representation.setDocument(myXML);
return representation;
}
#Override
protected void doRelease() throws ResourceException {
super.doRelease();
}
}
I've tried the solutions provided in other threads but none of them seem to work. Firstly, it does not seem that the thread pool is augmented with the parameters set as the warnings state that the thread pool available is 10. As mentioned before, the increase of the maxThreads value only seems to postpone the result.
Example: INFO: Worker service tasks: 0 queued, 10 active, 17 completed, 27 scheduled.
There could be some error concerning the Restlet version, but I downloaded the stable version to verify this was not the issue.The Web Service is having around 5000 requests per day, which is not much.Note: the insertion of the #release method either in the ServerResource or OriginFilter returns error and the referred warning ("WARNING: A response with a 200 (Ok) status should have an entity (...)")
Please guide.
Thanks!
By reading this site the problem residing in the server-side that I described was resolved by upgrading the Restlet distribution to the 2.1 version.
You will need to alter some code. You should consult the respective migration guide.