SpringBoot to Flutter Stream using application/x-ndjson - flutter

I am trying to get a Flutter app to process a NDJSON stream properly, but cannot get it to work.
I have a SpringBoot server that the Flutter app requests a stream from.
SpringBoot side:
#GetMapping(value = "/streaming", produces = {
// MediaType.APPLICATION_JSON_VALUE,
MediaType.APPLICATION_NDJSON_VALUE
})
public Flux<String> getItemsStream(){
FluxSinkImpl<String> fluxSinkConsumer = new FluxSinkImpl<>();
try {
logger.info("streaming New Stream!");
synchronized (fluxSinkConsumers) {
fluxSinkConsumers.add(fluxSinkConsumer);
}
return Flux.create(fluxSinkConsumer).doOnNext(s -> {
logger.info("streaming doOnNext ["+s+"]");
}).doFinally(signalType -> {
logger.info("streaming Done ["+signalType+"]");
synchronized (fluxSinkConsumers) {
fluxSinkConsumers.remove(fluxSinkConsumer);
}
});
} catch (Exception e) {
logger.error("Failed to register Stream",e);
throw e;
}
}
private synchronized void publishEvent(String jsonStr) {
Set<FluxSinkImpl> fluxSinkConsumersCopy;
synchronized (fluxSinkConsumers) {
fluxSinkConsumersCopy = new HashSet<>(fluxSinkConsumers);
}
fluxSinkConsumersCopy.forEach(fluxSink -> {
try {
logger.info("streaming publishEvent");
fluxSink.publishEvent(jsonStr);
} catch (Throwable t) {
logger.info("streaming Failed to publish");
t.printStackTrace();
synchronized (fluxSinkConsumers) {
fluxSinkConsumers.remove(fluxSink);
}
}
});
}
The flutter side:
void startStreamListener2() async {
try {
final client = new http.Client();
http.Request request = http.Request("GET", Uri.parse(host+'streaming'));
request.headers['Content-type'] = 'application/x-ndjson';
request.headers['Accept'] = 'application/x-ndjson';
Future<http.StreamedResponse> streamedResponseFuture = client.send(request);
Stream<http.StreamedResponse> asStream = streamedResponseFuture.asStream();
print('startStreamListener1 [${host+'streaming'}]');
final StreamController<http.StreamedResponse> controller2 = new StreamController<http.StreamedResponse>();
asStream.asyncMap((event) {
event.stream.listen((value) {
print('startStreamListener4 listen [${utf8.decode(value)}]');
});
});
controller2.stream.listen((http.StreamedResponse event) {
event.stream.listen((value) {
print('startStreamListener3 listen [${utf8.decode(value)}]');
});
});
StreamSubscription<http.StreamedResponse> listen = asStream.listen((http.StreamedResponse event) {
event.stream.listen((value) {
print('startStreamListener2 listen [${utf8.decode(value)}]');
});
});
listen.onDone(() {
print('startStreamListener2 Done');
});
listen.onError((error) {
print('startStreamListener2 Error[$error] runtimeType[${error.runtimeType}]');
if (error is ClientException) {
print('ClientException [${(error as ClientException).message}]');
}
});
} catch (error) {
print('startStreamListener error [$error]');
}
}
When I use a Browser to connect directly to the stream, it works just fine. I see pushed messages as they are generated. The Stream is supposed to be open for a long time with asynchronous messages being pushed towards listeners (Flutter in this case).
Flutter does register, but does not trigger onData on single message. It does register the SpringBoot server restarting.

Related

Rare error when trying to save data "unhandled exception on the current circuit"

I am using VS 2022, Blazor server project. When I trying to save data
async public static Task<bool> updateObject(Firecall obj)
{
Firecall r;
try
{
using (var context = new sptContext())
{
r = context.Firecalls.Where(c => c.Mguid == obj.Mguid).FirstOrDefault();
bool новое = (r == null);
if (новое)
{
r = new Firecall();
}
r.comment = obj.comment;
if (новое)
await context.Firecalls.AddAsync(r);
if (busy)
return false;
try
{
busy = true;
await context.SaveChangesAsync();
}
catch (Exception)
{
return false;
}
finally {
busy = false;
}
}
return true;
}
catch (Exception)
{
return false;
}
}
sometimes I get error:
Sometimes an error occurs, sometimes not. No error in debugger.
How to solve problem?
P.S. Data in each operation is saved as expected. Only after the operation is completed the indicated error message appear
And calling savechanges method from #code block of .razor view:
async private void SaveChanges()
{
bool rez = await firecallRepository.updateObject(_currentFireCall);
}

How to merge aqueduct Future<RequestOrResponse> with dart console app?

Thanks to Bryan from voidrealms. I was struggling last 2 days (and weeks of resarch) and now I can get big data using dart tcp socket from the old system very fast. The process with dart console app is much faster than the dart Future project.
Now problem to mixing dart console app to aqueduct Future app. In below I put my questions after (********).
If I use Socket.connect("192..... Inside Future the process will be very slow and sometimes returns null response. So, my question is how to merge aqueduct Future with dart console app.
aqueduct.io part
class NtmsApiController extends Controller {
#override
Future<RequestOrResponse> handle(Request request) async {
try {
if (request.path.remainingPath != null) {
_requestValue = request.path.remainingPath;
// (********) In here I need to add below code, how?
}
} else {
_secureResponse = "$_errorData";
}
} catch (e) {
_secureResponse = "$_errorData";
}
return new Response.ok("$_secureResponse")
..contentType = ContentType.json;
}
}
dart console app
import 'dart:io';
import 'dart:async';
Socket socket;
String _response;
String _requestedData;
Stopwatch _stopWatch;
void main() {
_stopWatch = Stopwatch()..start();
_response = "";
_requestedData = "Q77:_:NBRT:_:6785417534\r\n";
Socket.connect("192.168.22.120", 3000).then((Socket sock) {
socket = sock;
socket.write('$_requestedData\r\n');
socket.listen(dataHandler,
onError: errorHandler,
onDone: doneHandler,
cancelOnError: false);
}).catchError((AsyncError e) {
print("Unable to connect: $e");
});
print("_requestedData: $_requestedData");
}
void dataHandler(data){
_response = new String.fromCharCodes(data).trim();
_printResponse(_response);
}
void errorHandler(error, StackTrace trace){
print(error);
}
void doneHandler(){
socket.destroy();
}
void _printResponse(String _response) {
// approximately I get 500 rows with 20 column data in 250ms
print("$_response ... (${_stopWatch.elapsedMilliseconds} ms)");
_stopWatch..stop();
if(_stopWatch.isRunning == false) {
socket.close();
// (********)return response object to aqueduct Future request_response--- how?
}
}

Javafx Task for Bluetooth data reciever

I am creating javafx application where I have this case that I need to listen for data sent over Bluetooth.
I have one fxml window on which I need to initialize Bluetooth and start listening from data.
Following is my Code for fxml controller:
//all imports
public class NewBarcodeInvoicePaneController implements Initializable{
private BluetoothController bc;
public BluetoothController getBc() {
return bc;
}
#Override
public void initialize(URL location, ResourceBundle resources) {
try {
bc = new BluetoothController();
new Thread(bc).start();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
And BluetoothController is task where I initialize bluettoth and listen to the data
public class BluetoothController extends Task<Void> {
#Override
protected Void call() throws Exception {
LocalDevice local = null;
StreamConnectionNotifier notifier;
StreamConnection connection = null;
// setup the server to listen for connection
try {
local = LocalDevice.getLocalDevice();
try {
local.setDiscoverable(DiscoveryAgent.GIAC);
} catch (BluetoothStateException e) {
}
UUID uuid = new UUID(80087355); // "04c6093b-0000-1000-8000-00805f9b34fb"
String url = "btspp://localhost:" + uuid.toString() + ";name=RemoteBluetooth";
notifier = (StreamConnectionNotifier) Connector.open(url);
} catch (Exception e) {
e.printStackTrace();
return null;
}
try {
System.err.println("THIS IS HAPENING");
connection = notifier.acceptAndOpen();
System.err.println("HAPENING???????????????????????????");
InputStream inputStream = connection.openInputStream();
BufferedReader bReader = new BufferedReader(new InputStreamReader(inputStream));
String lineRead = bReader.readLine();
connection.close();
inputStream.close();
notifier.close();
local.setDiscoverable(DiscoveryAgent.NOT_DISCOVERABLE);
JSONParser parser = new JSONParser();
Object obj = parser.parse(lineRead);
JSONArray array = (JSONArray) obj;
array.stream().map((o) -> (String) o).forEach((stringObj) -> {
System.out.println(stringObj);
});
System.out.println("AFTER DATA RECIEVED");
} catch (Exception e) {
e.printStackTrace();
return null;
}
return null;
}
}
It Works fine if I send data over bluetooth and blocking call to notifier.acceptAndOpen() is unblocked.
My problem is when we do not pass any data and I just want to close the window I opened..
It still have blocking call open with extra thread by the task.
I tried to cancel BluetoothController task in Main controller where I open this window like following
private void openNewBarcodeInvoicePane(ActionEvent ae) {
//following are custom classes to open windows from fxml and getting controller back for further manipulation
PostoryModalWindow modalWindow = new PostoryModalWindow();
modalWindow.openNewModalPaneWithParent("New Invoice", "fxml/newbarcodeinvoicepane.fxml", ae);
//getting controller object
NewBarcodeInvoicePaneController controller = (NewBarcodeInvoicePaneController) modalWindow.getDswFromController();
controller.getWindowStage().showAndWait();
BluetoothController bc = controller.getBc();
if(bc != null){
System.err.println("CANCELLING");
bc.cancel(true);
}
}
But it doesn't throw InterrupttedExeption (In which I might have Choice to close Bluetooth thread) and after research I found that waiting on Socket doesn't work on interrupt.
Any help on this?
Thanks
Got Solution After Some Research.
I just added new task to call notifier.acceptAndOpen();
And added method to close Bluetooth notifier.
public class BluetoothController extends Task<Void> {
private final ObservableList<Item> items = FXCollections.observableArrayList();
public ObservableList<Item> getItems() {
return items;
}
StreamConnectionNotifier notifier;
#Override
protected Void call() throws Exception {
try {
BluetoothConnectionTask bct = new BluetoothConnectionTask(items);
new Thread(bct).start();
Thread.sleep(2000);
notifier = bct.getNotifier();
} catch (Exception e) {
e.printStackTrace();
return null;
}
return null;
}
public void cancelandExit() {
try {
if (notifier != null) {
notifier.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Here is new task for blocking call
public class BluetoothConnectionTask extends Task<Void>{
private StreamConnectionNotifier notifier;
private StreamConnection connection;
private ObservableList<Item> items = FXCollections.observableArrayList();
public StreamConnection getConnection() {
return connection;
}
public StreamConnectionNotifier getNotifier() {
return notifier;
}
public BluetoothConnectionTask(ObservableList<Item> is){
items = is;
}
#Override
protected Void call() throws Exception {
try {
LocalDevice local = LocalDevice.getLocalDevice();
try {
local.setDiscoverable(DiscoveryAgent.GIAC);
} catch (BluetoothStateException e) {
}
UUID uuid = new UUID(80087355); // "04c6093b-0000-1000-8000-00805f9b34fb"
String url = "btspp://localhost:" + uuid.toString() + ";name=RemoteBluetooth";
notifier = (StreamConnectionNotifier) Connector.open(url);
} catch (Exception e) {
e.printStackTrace();
return null;
}
connection = notifier.acceptAndOpen();
InputStream inputStream = connection.openInputStream();
BufferedReader bReader = new BufferedReader(new InputStreamReader(inputStream));
String lineRead = bReader.readLine();
connection.close();
inputStream.close();
notifier.close();
LocalDevice local = LocalDevice.getLocalDevice();
local.setDiscoverable(DiscoveryAgent.NOT_DISCOVERABLE);
JSONParser parser = new JSONParser();
Object obj = parser.parse(lineRead);
JSONArray array = (JSONArray) obj;
ItemDAO idao = new ItemDAO();
array.stream().map((o) -> (String) o).forEach((stringObj) -> {
String barcode = (String) stringObj;
Item i = idao.getItemByBarCode(barcode);
System.err.println("Adding Item "+i.getName());
items.add(i);
});
System.out.println("AFTER DATA RECIEVED");
return null;
}
}
Now for cancelling closing my bluetooth thread I am calling cancelandExit() after window is closed.

addautomtioneventhandler on web pages

I'm trying to add an automation event handler for a ui button. I've tested on desktop applications and it's working but I've a problem with buttons in web pages.In fact I can invoke them with InvokePattern.Invoke() but I don't see the handler working after that!
this is my code :
if ((wantedElement != null))
{
element = wantedElement;
buttonEvent = new AutomationEventHandler(close_event);
Automation.AddAutomationEventHandler(InvokePattern.InvokedEvent, element,TreeScope.Element,buttonEvent );
object pattern;
if (wantedElement.TryGetCurrentPattern(InvokePattern.Pattern, out pattern))
{
InvokePattern invokePattern = (InvokePattern)pattern;
invokePattern.Invoke();
}
}
...
private static void close_event(object sender, AutomationEventArgs e)
{
AutomationElement sourceElement;
try
{
sourceElement = sender as AutomationElement;
Console.WriteLine("button try");
}
catch (ElementNotAvailableException)
{
return;
}
if (e.EventId == InvokePattern.InvokedEvent)
{
// TODO Add handling code.
Console.WriteLine("button invoked");
}
else
{
// TODO Handle any other events that have been subscribed to.
Console.WriteLine("button event");
}
}

Show previous instance of RCP application

I had an rcp application which runs for only first run, when a user attempts to re-execute the application, second instance behaves as a client which encodes and sends its arguments over the socket to the first instance which acts as a server and then exits silently. The first instance receives and decodes that message, then behaves as if it had been invoked with those arguments.
so far so good i made internal protocol specification for passing arguments between two instances.
I could not bring the first instance(RCP application) to front. It is in minimized state only,
this is in continuation to my previous question
the change i made to previous post is start method of application class
public Object start(IApplicationContext context) throws Exception {
if (!ApplicationInstanceManager.registerInstance()) {
return IApplication.EXIT_OK;
}
ApplicationInstanceManager
.setApplicationInstanceListener(new ApplicationInstanceListener() {
public void newInstanceCreated() {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
System.out.println("New instance detected...");
//Display.getCurrent().getActiveShell()
.forceActive();// this gives null
// pointer exception
// hence commented
}
});
}
});
Display display = PlatformUI.createDisplay();
try {
int returnCode = PlatformUI.createAndRunWorkbench(display,
new ApplicationWorkbenchAdvisor());
if (returnCode == PlatformUI.RETURN_RESTART)
return IApplication.EXIT_RESTART;
else
return IApplication.EXIT_OK;
} finally {
display.dispose();
}
}
below line is stopping me to bring Application to front
Display.getCurrent().getActiveShell().forceActive();
generates null pointer exception at getActiveShell()
how can i maximize the previous instance or bring it to front
I wrote an instance manager to restrict my RCP to a single instance.
Here's the code that goes in Application.java, in the start method:
if (!ApplicationInstanceManager.registerInstance()) {
return IApplication.EXIT_OK;
}
ApplicationInstanceManager
.setApplicationInstanceListener(new ApplicationInstanceListener() {
public void newInstanceCreated() {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
if (DEBUG)
System.out.println("New instance detected...");
Display.getCurrent().getActiveShell().forceActive();
}
});
}
});
Here's the listener interface:
public interface ApplicationInstanceListener {
public void newInstanceCreated();
}
And here's the Manager class:
public class ApplicationInstanceManager {
private static final boolean DEBUG = true;
private static ApplicationInstanceListener subListener;
/** Randomly chosen, but static, high socket number */
public static final int SINGLE_INSTANCE_NETWORK_SOCKET = 44331;
/** Must end with newline */
public static final String SINGLE_INSTANCE_SHARED_KEY = "$$RabidNewInstance$$\n";
/**
* Registers this instance of the application.
*
* #return true if first instance, false if not.
*/
public static boolean registerInstance() {
// returnValueOnError should be true if lenient (allows app to run on
// network error) or false if strict.
boolean returnValueOnError = true;
// try to open network socket
// if success, listen to socket for new instance message, return true
// if unable to open, connect to existing and send new instance message,
// return false
try {
final ServerSocket socket = new ServerSocket(
SINGLE_INSTANCE_NETWORK_SOCKET, 10, InetAddress
.getLocalHost());
if (DEBUG)
System.out
.println("Listening for application instances on socket "
+ SINGLE_INSTANCE_NETWORK_SOCKET);
Thread instanceListenerThread = new InstanceListenerThread(socket);
instanceListenerThread.start();
// listen
} catch (UnknownHostException e) {
EclipseLogging.logError(RabidPlugin.getDefault(),
RabidPlugin.PLUGIN_ID, e);
return returnValueOnError;
} catch (IOException e) {
return portTaken(returnValueOnError, e);
}
return true;
}
private static boolean portTaken(boolean returnValueOnError, IOException e) {
if (DEBUG)
System.out.println("Port is already taken. "
+ "Notifying first instance.");
try {
Socket clientSocket = new Socket(InetAddress.getLocalHost(),
SINGLE_INSTANCE_NETWORK_SOCKET);
OutputStream out = clientSocket.getOutputStream();
out.write(SINGLE_INSTANCE_SHARED_KEY.getBytes());
out.close();
clientSocket.close();
System.out.println("Successfully notified first instance.");
return false;
} catch (UnknownHostException e1) {
EclipseLogging.logError(RabidPlugin.getDefault(),
RabidPlugin.PLUGIN_ID, e);
return returnValueOnError;
} catch (IOException e1) {
EclipseLogging
.logError(
RabidPlugin.getDefault(),
RabidPlugin.PLUGIN_ID,
"Error connecting to local port for single instance notification",
e);
return returnValueOnError;
}
}
public static void setApplicationInstanceListener(
ApplicationInstanceListener listener) {
subListener = listener;
}
private static void fireNewInstance() {
if (subListener != null) {
subListener.newInstanceCreated();
}
}
public static void main(String[] args) {
if (!ApplicationInstanceManager.registerInstance()) {
// instance already running.
System.out.println("Another instance of this application "
+ "is already running. Exiting.");
System.exit(0);
}
ApplicationInstanceManager
.setApplicationInstanceListener(new ApplicationInstanceListener() {
public void newInstanceCreated() {
System.out.println("New instance detected...");
// this is where your handler code goes...
}
});
}
public static class InstanceListenerThread extends Thread {
private ServerSocket socket;
public InstanceListenerThread(ServerSocket socket) {
this.socket = socket;
}
#Override
public void run() {
boolean socketClosed = false;
while (!socketClosed) {
if (socket.isClosed()) {
socketClosed = true;
} else {
try {
Socket client = socket.accept();
BufferedReader in = new BufferedReader(
new InputStreamReader(client.getInputStream()));
String message = in.readLine();
if (SINGLE_INSTANCE_SHARED_KEY.trim().equals(
message.trim())) {
if (DEBUG)
System.out.println("Shared key matched - "
+ "new application instance found");
fireNewInstance();
}
in.close();
client.close();
} catch (IOException e) {
socketClosed = true;
}
}
}
}
}
}
After your IApplication start up, you can also check and lock the OSGi instance location using org.eclipse.osgi.service.datalocation.Location.isSet() and org.eclipse.osgi.service.datalocation.Location.lock()
The location is usually retrieved from your Activator using code like:
public Location getInstanceLocation() {
if (locationTracker == null) {
Filter filter = null;
try {
filter = context.createFilter(Location.INSTANCE_FILTER);
} catch (InvalidSyntaxException e) {
// ignore this. It should never happen as we have tested the
// above format.
}
locationTracker = new ServiceTracker(context, filter, null);
locationTracker.open();
}
return (Location) locationTracker.getService();
}