I started a Quarkus project, which (in part) shall watch for file changes on a text-file, read the added line(s) and then sends the added line(s) through a websocket connection to a client.
For watching the file changes and reading those I created the following class:
public class McServerService {
private String directory;
private List<String> currentLog;
private Observable<List<String>> observableLog;
private Thread logObserverThread;
public McServerService (String directory) {
this.currentLog = new ArrayList<String>();
this.observableLog = Observable.fromCallable(() -> this.currentLog);
this.directory = directory;
}
public void startWatching () {
this.logObserverThread = new Thread(new LogObserverThreadImpl(this.directory));
this.logObserverThread.start();
}
public void subscribeToLog (Observer<? super List<String>> observer) {
this.observableLog.subscribe(observer);
}
private class LogObserverThreadImpl implements Runnable {
BufferedReader br;
WatchService watchService;
private LogObserverThreadImpl (String directory) {
try {
this.br = new BufferedReader(new java.io.FileReader(directory + "\\" + "latest.log"));
String nextLine;
while ((nextLine = this.br.readLine()) != null) {
McServerService.this.currentLog.add(nextLine);
System.out.println(nextLine);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void run() {
Path path = Paths.get(directory);
try {
System.out.println("entered try");
this.watchService = FileSystems.getDefault().newWatchService();
path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY);
WatchKey key;
while ((key = this.watchService.take()) != null) {
for (WatchEvent<?> event : key.pollEvents()) {
if (event.context().toString().equals("latest.log")) {
String line = this.br.readLine();
McServerService.this.currentLog.add(line);
System.out.println(line);
}
}
key.reset();
}
System.out.println("after while");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Now the websocket would be handled by this class:
#ServerEndpoint("/test")
#ApplicationScoped
public class McServerWebSocket {
Map<String, Session> sessions = new ConcurrentHashMap<>();
McServerService mss = new McServerService("D:\\Spiele\\Minecraft");
#OnOpen
public void onOpen(Session session, #PathParam("name") String name) {
sessions.put(name, session);
}
#OnClose
public void onClose(Session session, #PathParam("name") String name) {
sessions.remove(name);
}
#OnError
public void onError(Session session, #PathParam("name") String name, Throwable throwable) {
sessions.remove(name);
}
#OnMessage
public void onMessage(String message, #PathParam("name") String name) {
Session c_session = sessions.get(name);
c_session.getAsyncRemote().sendObject("insert");
}
private class ConsoleLogObserverImpl implements Observer<List<String>>{
private ConsoleLogObserverImpl () {
}
#Override
public void onSubscribe(#NonNull Disposable d) {
// TODO Auto-generated method stub
System.out.println("subscribed");
}
#Override
public void onNext(#NonNull List<String> t) {
System.out.println(t.toString());
}
#Override
public void onError(#NonNull Throwable e) {
// TODO Auto-generated method stub
}
#Override
public void onComplete() {
// TODO Auto-generated method stub
System.out.println("finished");
}
}
}
I didnt implement the websocket yet, because my problem lies with observing the changes of
private List<String> currentLog; in the McServerServive class.
Unfortunately I deleted the main method in McServerWebSocket, that I used to test this, but that main method would essentially just create an instance of McServerWebSocket and then call the startWatching() method of its McServerService mss = new McServerService("D:\\Spiele\\Minecraft"); and its
public void subscribeToLog (Observer<? super List<String>> observer) {
this.observableLog.subscribe(observer);
}
method with the inner class:
private class ConsoleLogObserverImpl implements Observer<List<String>>
But the behaviour was not as I would have exspected. The output was:
subscribed
[]
finished
The observable was imediately terminating. Did I do something wrong when creating the Observable or did I completly misunderstand the usage RxJava?
How can I create an Observable class field and an Observer that triggers an action when the Observable is changed with RxJava/some Quarkus extension?
I keep getting this error, the path has been specified in yml and even in the console it is going to the relative path but not reading the file or finding it, how can I get past this ?
I have attached the picture and below is the code in my main method. Any input is deeply appreciated. Thanks!
#SpringBootApplication
#EnableConfigurationProperties(DataStaxAstraProperties.class)
public class BookAppApplication {
#Autowired AuthorRepostories authorRepostories;
#Value("${datadump.location.author}")
private String authorDumpsLocation;
#Value("${datadump.location.works}")
private String authorWorksLocation;
public static void main(String[] args) {
SpringApplication.run(BookAppApplication.class, args);
}
private void initAuthors() {
Path path = Paths.get(authorDumpsLocation);
System.out.println(path.toAbsolutePath());
try(Stream<String> lines = Files.lines(path)){
lines.forEach(line->{
String jsonStr = line.substring(line.indexOf("{"));
try {
JSONObject jsonObject = new JSONObject(jsonStr);
Author author = new Author();
author.setName(jsonObject.optString("name"));
author.setPersonalName(jsonObject.optString("personal_name"));
author.setId(jsonObject.optString("key").replace("/authors/",""));
System.out.println("Saving author" + author.getName() + "....");
authorRepostories.save(author);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
private void initWorks() {
}
#PostConstruct
public void start() {
initAuthors();
initWorks();
}
#Bean
public CqlSessionBuilderCustomizer sessionBuilderCustomizer(DataStaxAstraProperties astraProperties) {
Path bundle = astraProperties.getSecureConnectBundle().toPath();
return builder -> builder.withCloudSecureConnectBundle(bundle);
}
}
found the issue. Had to do with access rights. Java couldn't access the files because it was secured after changing the property of a file, it worked.
Update: came up with new error about the provided java class
I have a tutorial for building an app for an external barcode scanner(use USB port) by using Java + provided Jar Library. I'm trying to build the same app by using the Xamarin.Forms and that Jar Library(through BindingsLibrary Project). However, I got an error
"Java.Lang.NoClassDefFoundError: " when I compiled my code. Does anybody have an idea about what I'm doing wrong?
This my java classes:
The USBScanFactory
package com.unistrong.qrcode;
import com.unistrong.pin.GOPOManager;
public class USBQRscanFactory {
private static USBQRscanFactory factory = new USBQRscanFactory();
static boolean mIsScanContinue = false;
private GOPOManager mGopoManager = GOPOManager.getInstance();
private OnScanListener mScanListener;
private QRScanManagerJNI qrScanManagerJNI;
private USBQRscanFactory() {
}
public static USBQRscanFactory createInstance() {
return factory;
}
public void init(OnScanListener onScanListener) {
this.mGopoManager.Pin11_High();
this.qrScanManagerJNI = new QRScanManagerJNI(onScanListener);
this.qrScanManagerJNI.callbackInit();
}
public void enableAddKeyValue(int i) {
QRScanManagerJNI.AddKeyValue(i);
}
public void open() {
this.mGopoManager.Pin11_Low();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
QRScanManagerJNI.OpenDev();
}
public void powerOn() {
this.mGopoManager.Pin11_High();
this.mGopoManager.openPower5V_3V3();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void powerOff() {
this.mGopoManager.Pin11_High();
this.mGopoManager.closePower5V_3V3();
}
public void scan_start() {
QRScanManagerJNI.QRScan();
}
On ScanListener:
package com.unistrong.qrcode;
public interface OnScanListener {
void scanReport(byte[] bArr);
void statusReport(int i);
}
And here is my code on Xamain:
public class OnScanListener : Java.Lang.Object, IOnScanListener
{
H myH = new H();
public void ScanReport(byte[] byteArray)
{
lock (myH)
{
if (null != byteArray && byteArray.Length > 0)
{
myH.SendMessage(myH.ObtainMessage(0, byteArray));
}
}
}
public void StatusReport(int i)
{
lock (myH)
{
myH.SendEmptyMessage(i);
}
}
}
#endregion
public MainPage()
{
usbScan = USBQRscanFactory.CreateInstance();
InitializeComponent();
}
int count = 0;
private void scanBtn_Clicked(object sender, EventArgs e)
{
count++;
//usbScan.Init(OnScanListener);
OnScanListener myOnScanListener = new OnScanListener();
usbScan.PowerOn();
usbScan.Init(myOnScanListener);
Barcode.Text = "";
openScanner(true);
usbScan.Scan_start();
}
//Open Scanner
private void openScanner(bool open)
{
if (open == mWorkingStateFlag) return;
if (open)
{
try
{
Java.Lang.Thread.Sleep(50);
usbScan.Open();
usbScan.EnableAddKeyValue(0);
}
catch (Java.Lang.InterruptedException e)
{
// TODO Auto-generated catch block
e.PrintStackTrace();
}
}
}
I try to implement a remote stateless bean. For the methods in this bean, the return values can be correctly returned. However, for "println" in these methods cannot print any thing to the console.
The interface is
public interface HelloWorld {
public void SayHelloWorld(String name);
public String SayHello(String name);
}
The implementation is
#Stateless
#Remote(HelloWorld.class)
public class HelloWorldBean implements HelloWorld {
#Override
public void SayHelloWorld(String name) {
System.out.println(name + " say hello to the world!");
}
#Override
public String SayHello(String nameString) {
System.out.println("This is SayHello()");
return nameString;
}
}
The client is
public class HelloWorldTest {
public static void main(String[] args) {
try {
FileInputStream inputStream = new FileInputStream("ejb.properties");
Properties pro = new Properties();
pro.load(inputStream);
InitialContext icContext = new InitialContext(pro);
HelloWorld hw = (HelloWorld) icContext.lookup("ejb/HelloWorldBean!com.ejbinterface.HelloWorld");
hw.SayHelloWorld("tom");
String aa = hw.SayHello("tom");
System.out.println(aa);
} catch (NamingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I do not know why the println in method "SayHelloWorld" and "SayHello" is not executed. However, the variable "aa"(in client) correctly get the return value.
It prints to the console of the server (or, if redirected, to some log file - but this is merely a configuration issue). Just look for the output, if the methods get executed, then the output is there.
Can someone help me to find a tutorial or sample java code to
read a file from any machine which is in the same network
The simplest way to do this would be to read it using regular file paths.
On Windows:
new File("\\\\server\\path\\to\\file.txt")
// (double-backslashes required for backslashes in path)
On Unix:
First mount the share using Samba (SMB, NFS or whatever other protocol) to some location like /mnt/network. Then you can use:
new File("/mnt/network/path/to/file.txt")
Once you have the File object you can use FileInputStream, FileReader or whatever else you want to read the file in.
Edit for comments response. If you are using an Applet, you probably want to pull the file from a web server. You can use the built in java.net.URL class but I would recommend this if you have to do more than just simple stuff: http://hc.apache.org/httpclient-3.x/index.html
Example (from the Commons HTTP Site):
// Create an instance of HttpClient.
HttpClient client = new HttpClient();
// Create a method instance.
GetMethod method = new GetMethod(url);
try {
// Execute the method.
int statusCode = client.executeMethod(method);
if (statusCode != HttpStatus.SC_OK) {
System.err.println("Method failed: " + method.getStatusLine());
}
// Read the response body.
byte[] responseBody = method.getResponseBody();
// Deal with the response.
// Use caution: ensure correct character encoding and is not binary data
System.out.println(new String(responseBody));
} catch (HttpException e) {
System.err.println("Fatal protocol violation: " + e.getMessage());
e.printStackTrace();
} catch (IOException e) {
System.err.println("Fatal transport error: " + e.getMessage());
e.printStackTrace();
} finally {
// Release the connection.
method.releaseConnection();
}
}
}
This is not that simple! To use Server Client Aplications you need a Network API.
I have 1 by DeBukkit and an extended version. If you would to send Files I will suggest my one (Server Client Extended .jar) becazse there is an Option to send Files (FilePacket.java).
This are the links to the libs: All Libs
Code for Server for Client Server Extended:
public class TestServer extends Server {
public TestServer() {
super(29898, true, true,true);
registerMethod("bt", new FileReciver() {
#Override
public void onCompleteRecive(FileInfo data) {
System.out.println("Completely recived : "+data);
Path p = Paths.get(data.getName());
try {
Files.createFile(p);
Files.write(p, data.getContent());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* #see com.bebukkit.niton.network.packets.buffer.BufferedPacketReciver#run(com.bebukkit.niton.network.packets.Packet, java.net.Socket)
*/
#Override
public void run(Packet<? extends Serializable> msg, Socket socket) {
super.run(msg, socket);
sendMessage(new Packet<Boolean>("", null), socket);
}
});
}
#Override
public void preStart()
{
registerMethod("msg", new ReciveMethod() {
#Override
public void run(Packet<? extends Serializable> msg, Socket socket) {
broadcastMessage(msg);
}
});
}
#Override
public void onWrongDataPacketException(ClassNotFoundException e) {
// TODO Auto-generated method stub
}
#Override
public void onReceivePacketError(IOException e) {
// TODO Auto-generated method stub
}
#Override
public void onPacketReckognized(ServerSocket socket) {
// TODO Auto-generated method stub
}
#Override
public void onPacketSendException(Exception e, Packet<? extends Serializable> message, Socket socket2) {
// TODO Auto-generated method stub
}
#Override
public void onSendPacketToNotConnectedClient(Packet<? extends Serializable> message, Socket socket2) {
// TODO Auto-generated method stub
}
#Override
public void onBrodcast(Packet<? extends Serializable> pack) {
// TODO Auto-generated method stub
}
#Override
public void onServerStartError(IOException e) {
// TODO Auto-generated method stub
}
#Override
public void onServerStop() {
// TODO Auto-generated method stub
}
}
Code for Client:
package com.bebukkit.niton.network.test;
import java.io.IOException;
import java.io.Serializable;
import java.net.Socket;
import java.util.Scanner;
import com.bebukkit.niton.network.Client;
import com.bebukkit.niton.network.packets.Packet;
import com.bebukkit.niton.network.packets.ReciveMethod;
public class TestClient extends Client {
public TestClient() {
super("localhost", 29898, 5000, false,true);
registerMethod("msg", new ReciveMethod() {
#Override
public void run(Packet<? extends Serializable> msg, Socket socket) {
System.out.println(msg.getData());
}
});
registerMethod("replay", new ReciveMethod() {
#Override
public void run(Packet<? extends Serializable> msg, Socket socket) {
System.out.println("REREplay");
}
});
}
#Override
public void onSocketClosingFail() {
// TODO Auto-generated method stub
}
#Override
public void onLoginPacketSendingFailed(IOException ex) {
// TODO Auto-generated method stub
}
#Override
public void onConnectionError(IOException ex) {
// TODO Auto-generated method stub
}
#Override
public void onMessageReciveError(Exception ex) {
// TODO Auto-generated method stub
}
#Override
public void onPacketSendError(Exception ex, Packet<? extends Serializable> pack) {
// TODO Auto-generated method stub
}
#Override
public void start() {
super.start();
}
}
You need a seperated Server + Client Starter:
package com.bebukkit.niton.network.test;
public class ServerStarter {
public static void main(String[] args) {
new TestServer();
}
}
Client:
package com.bebukkit.niton.network.test;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import javax.swing.JFileChooser;
import com.bebukkit.niton.network.packets.Packet;
import com.bebukkit.niton.network.packets.buffer.BufferedPacket;
import com.bebukkit.niton.network.packets.file.FileInfo;
import com.bebukkit.niton.network.packets.file.FilePacket;
public class ClientStarter {
public static void main(String[] args) throws IOException {
TestClient tc = new TestClient();
tc.start();
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
JFileChooser c = new JFileChooser("Choose a file to upload");
c.setFileSelectionMode(JFileChooser.FILES_ONLY);
c.showDialog(null,"Upload");
File f = c.getSelectedFile();
try {
tc.sendMessage(new FilePacket("file", f));
tc.sendMessage(new Packet<String>("replay","test"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}
}
If your file path in a different pc (i.e. Network devices) but connected to the same LAN, then you can easily access it by using these 2 steps.
Step 1: you need to map the network drive (i.e. your desired folder) into a physical drive, for example:
In Windows, \\10.221.222.6/some/path/of/images path mapped into a Drive like Z:\ or Y:\
Step 2:
String externalSharedFilePath = "file:Z:/images/";
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/images/**").addResourceLocations(externalSharedFilePath);
}
Try the following URL for a tutorial http://www.roseindia.net/java/beginners/construct_file_name_path.shtml
I think the best way is to use java.net.URL to open a InputSteam, because you can generalize it to files, that are not necessarily on the same network.