My application listens on some directory and it's sub directories. For listening on directory I use JNotify. When new file is created on directory application checks the files and processes it in some way. Below is code:
import net.contentobjects.jnotify.JNotify;
import net.contentobjects.jnotify.JNotifyListener;
public class JNotifyDemo {
public void sample() throws Exception {
// path to watch
//String path = System.getProperty("user.home");
String path = "/folder";
System.out.println(path);
// watch mask, specify events you care about,
// or JNotify.FILE_ANY for all events.
int mask = JNotify.FILE_CREATED
| JNotify.FILE_DELETED
| JNotify.FILE_MODIFIED
| JNotify.FILE_RENAMED;
// watch subtree?
boolean watchSubtree = true;
// add actual watch
int watchID = JNotify.addWatch(path, mask, watchSubtree, new Listener());
// sleep a little, the application will exit if you
// don't (watching is asynchronous), depending on your
// application, this may not be required
Thread.sleep(1000000);
// to remove watch the watch
boolean res = JNotify.removeWatch(watchID);
if (!res) {
// invalid watch ID specified.
}
}
class Listener implements JNotifyListener {
public void fileRenamed(int wd, String rootPath, String oldName,
String newName) {
print("renamed " + rootPath + " : " + oldName + " -> " + newName);
}
public void fileModified(int wd, String rootPath, String name) {
print("modified " + rootPath + " : " + name);
}
public void fileDeleted(int wd, String rootPath, String name) {
print("deleted " + rootPath + " : " + name);
}
public void fileCreated(int wd, String rootPath, String name) {
print("created " + rootPath + " : " + name);
//check file whether it is xml or not
//validate xml
//do some internal processing of file
// and do other jobs like inserting into database
}
void print(String msg) {
System.err.println(msg);
}
}
public static void main(String[] args) throws Exception {
new JNotifyDemo().sample();
}
}
As you can see from code, application processes one file per time. Any advice speeding up this application like using threading or anything else?
I'd recomand you to use java.nio.file.Path which extends Watchable interface, it may be registered with a watch service so that it can be watched for changes and events.
This event-driven approach speed-up your application. Take a look of example.
Path and Watchable both included in java 7.
how much processing is actually going on? keep in mind that IO is very slow, and, unless your processing takes considerable amount of time, multithreaded solution will be bottlenecked on reading the file.
anyways, quick way to implement parallel processing is to start an ExecutorService and submit it a Runnable with file path as a parameter.
Related
How can I check whether my Java application is running as "SYSTEM"/"Local System" (as seen on Windows Service list)?
I tried using this:
System.out.println("Running with user: " + System.getenv().get("USERDOMAIN") + "\\" + System.getenv().get("USERNAME"));
... but it seems to return DOMAIN\COMPUTERNAME according where the program is run. So it can be like DOMAIN1\COMPUTER1 and somewhere else it is FOO\SERVER451 and both still means "SYSTEM" account.
For background information, my Java application is wrapped to a Windows Service with 'Apache Commons Daemon Service Runner' and by default it will run as "Local System" (same way as in example image).
I really would want to simplify my code to print either SYSTEM or MYDOMAIN\JackTheUser depending on user type... Is there a way to do it with Java?
EDIT 20/12/02:
This is what I have done meanwhile the SO army working to find the correct answer:
Main:
String username = System.getenv().get("USERNAME");
String userdomain = System.getenv().get("USERDOMAIN");
String servername = getComputerName();
if (username.equalsIgnoreCase((servername + "$"))) {
System.out.println("Running with user: 'Local System'("
+ userdomain + "\\" + username + ")");
} else {
System.out.println("Running with user: '" + userdomain + "\\"
+ username + "'");
}
Methods:
private static String getComputerName() {
Map<String, String> env = System.getenv();
if (env.containsKey("COMPUTERNAME"))
return env.get("COMPUTERNAME");
else if (env.containsKey("HOSTNAME"))
return env.get("HOSTNAME");
else
return "Unknown Host name";
}
Prints:
Running with user: 'MYDOMAIN\jokkeri' or Running with user: 'Local System'(MYSERVER\SERVER_1$)
(not a perfect solution and I'm sure there are many occasions where it won't work but it's a starting point)
EDIT2 20/12/02:
Some good information about SYSTEM account was found from this thread from superuser: https://superuser.com/questions/265216/windows-account-ending-with
That’s the best I can come up so far
private static final String APP_NAME = "Some App";
private static final Configuration CONFIG = new Configuration() {
public #Override AppConfigurationEntry[] getAppConfigurationEntry(String name) {
return name.equals(APP_NAME)?
new AppConfigurationEntry[] { new AppConfigurationEntry(
"com.sun.security.auth.module.NTLoginModule",
LoginModuleControlFlag.REQUIRED, Collections.emptyMap())}:
null;
}
};
static final boolean DEBUG = true;
public static void main(String[] args) throws LoginException {
LoginContext lc = new LoginContext(APP_NAME, null, null, CONFIG);
lc.login();
final Subject subject=lc.getSubject();
boolean isSystem = false;
try {
for(Principal p: subject.getPrincipals()) {
if(DEBUG) System.out.println(p);
if(p.toString().equals("NTSidUserPrincipal: S-1-5-18")) {
isSystem = true;
if(DEBUG) System.out.println("\tit's SYSTEM");
}
}
}
finally { lc.logout(); }
}
As explained in this answer, SYSTEM is a set of permissions that can be attached to different accounts. The code iterates over all principals associated with the current account and tests for the well known SYSTEM.
But if you’re only interested in a printable user name, you may check for the NTUserPrincipal.
LoginContext lc = new LoginContext(APP_NAME, null, null, CONFIG);
lc.login();
final Subject subject=lc.getSubject();
try {
String name = System.getProperty("user.name"); // just a fall-back
for(Principal p: subject.getPrincipals()) {
if(p.toString().startsWith("NTUserPrincipal: ")) {
name = p.getName();
break;
}
}
System.out.println("Hello " + name);
}
finally { lc.logout(); }
If you can live with a direct dependency to the com.sun.security.auth package (or jdk.security.auth module in Java 9+), you can use the specific principal types directly
LoginContext lc = new LoginContext(APP_NAME, null, null, CONFIG);
lc.login();
final Subject subject=lc.getSubject();
try {
boolean system = false;
for(NTSidUserPrincipal p: subject.getPrincipals(NTSidUserPrincipal.class)) {
if(p.getName().equals("S-1-5-18")) {
system = true;
break;
}
}
Set<NTUserPrincipal> up = subject.getPrincipals(NTUserPrincipal.class);
String name = up.isEmpty()?
System.getProperty("user.name"): up.iterator().next().getName();
System.out.println("Hello " + name+(system? " *": ""));
}
finally { lc.logout(); }
I am working on an application which shall move some files and update some inputs in the database. If the file isn't found there will be thrown my own Exception. But after that exception the application interrupts and stops moving files. How can I change my code so that my application can continue after the exception?
It shall just print out that the file isn't existing and then it shall continue with moving the next file.
Here is my code:
import java.sql.*;
import java.nio.file.*;
import java.io.*;
public class SortMainNewFinal {
public static void main(String[] args) throws IOException, FileNotSynchronizedException {
//some not relevant code
//...
//the relevant code
if(path.contains(timestamp)) {
if(filecheck(path,filename)) {
data.writeToFile("The File " + filename + " is already in its subordinated folder.");
}
}else {
checkDir(path+timestamp,filename);
filemove(path,timestamp,filename);
data.writeToFile("File "+filename+" has been moved into " + path + timestamp + "/" +
filename);
String strUpdate = ("update cm_documents set document_path=\""+path+timestamp+"/"
+filename + "\" where document_name=\""+filename+"\"");
data.writeToFile("SQL Statement is: " + strUpdate);
update.executeUpdate(strUpdate);
}
//Catch SQLException
}
private static void filemove(String path, String timestamp, String filename)
throws IOException, FileNotSynchronizedException{
try {
Files.move(Paths.get(path+filename), Paths.get(path+timestamp+"/"+filename));
}catch(NoSuchFileException e) {
String error= "ERROR: The file " + filename + " has been moved, renamed or deleted and
these changes are not synchronized with the database.";
String file_name="C:/database/logfile.log";
WriteFile data = new WriteFile(file_name,true);
data.writeToFile(error);
throw new FileNotSynchronizedException(filename);
}
}
}
class FileNotSynchronizedException extends Exception{
FileNotSynchronizedException(String filename) throws IOException{
super("The file" + filename + "has been moved, renamed or deleted and these changes are not
synchronized with the database.");
}
}
My problem is now that the application throws my exception and then interrupts but I want the application to print out the Exception and then it shall just continue at the top of my application with the if Statement etc.
I want to say that I am not a mother tongue of English so please excuse any mistakes and I am quite new to coding so please excuse any mistakes in my code.
Remove the throws IOException, FileNotSynchronizedException from your main method, because there you want to handle the exception not throw it. If you leave you're catch block empty it will not stop the program execution:
try {
filemove(path,timestamp,filename);
}catch ( Exception e){
System.out.println("Some exception occurred -> "+e.getMessage());
}
I want to measure the time from the start of an incoming HTTP request and the application getting to a certain point. Both those points in time are located in different classes. How would I start and stop a timer from these different classes. I don't see a way to use 'named' timers from the MeterRegistry.
How would I go about this?
You can use AOP as below :
#Aspect
#Component
public class ControllerMonitor {
protected static final Logger LOGGER = LoggerFactory.getLogger(ControllerMonitor.class);
#Before("execution(public * com.demo.controller.*Controller.*(..))")
public void logBeforeAccess(JoinPoint joinPoint) {
if(joinPoint!=null){
String packageName = joinPoint.getSignature()!=null?joinPoint.getSignature().getDeclaringTypeName():"LOG-404";
LOGGER.info(". . .A request initiated from controller [" + packageName + "."+ getMethodSignature(joinPoint) + "]. . .");
}
}
#After("execution(public * com.demo.controller.*Controller.*(..))")
public void logAfterAccess(JoinPoint joinPoint) {
if(joinPoint!=null){
String packageName = joinPoint.getSignature()!=null?joinPoint.getSignature().getDeclaringTypeName():"LOG-404";
LOGGER.info(". . .Request from controller [" + packageName + "."+ getMethodSignature(joinPoint) + "] completed. . .");
}
}
#AfterThrowing(pointcut = "execution(public * com.demo.controller.*Controller.*(..))",throwing="exception")
public void logAfterThrowing(Exception exception){
LOGGER.error("Exception caught:"+ exception.getMessage());
}
private String getMethodSignature(JoinPoint joinPoint){
if(joinPoint!=null){
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
StringBuilder sb=new StringBuilder();
if(arguments!=null){
for (Object param: arguments) {
sb.append(param).append(",");
}
sb =(sb.length()>1)?sb.deleteCharAt(sb.length()-1):sb;
}
methodName = methodName+"("+new String(sb)+")";
return methodName;
}else{
return "LOG-405";
}
}
}
Use AOP …...No need to do changes on each class level. It will be one place config..
Hi I created sample jmdns serviceListner, When i run it , It should continue to list services as it finds, But with this my program, It list few services when run and after that it does not list any service. And i have dns-sd in my google chrome browser, So when i browse services in chrome, at that time my program list other services, Otherwise my program doesn't list services. I don't get why ServiceListner itself doesn't detect any subsequent events.
public static void main(String[] args) throws Exception {
String type = "_my-app._tcp.local.";
Enumeration<NetworkInterface> ifc = NetworkInterface.getNetworkInterfaces();
while (ifc.hasMoreElements()) {
NetworkInterface anInterface = ifc.nextElement();
if (anInterface.isUp()) {
Enumeration<InetAddress> addr = anInterface.getInetAddresses();
while (addr.hasMoreElements()) {
InetAddress address = addr.nextElement();
final JmDNS jmdns = JmDNS.create(address, type);
ServiceListenerClass aClass = new ServiceListenerClass();
jmdns.addServiceListener(type, aClass);
}
}
}
}
public static class ServiceListenerClass implements ServiceListener {
public void serviceAdded(ServiceEvent event) {
event.getDNS().requestServiceInfo(event.getType(), event.getName(), true);
}
public void serviceRemoved(ServiceEvent event) {
System.out.println((count--) + " " + event.getInfo().getName());
}
public void serviceResolved(ServiceEvent event) {
System.out.println((count++) + " :Res: " + event.getInfo().getName() + " " + event.getInfo().getPort() + " " + event.getInfo().getApplication()
+ " " + event.getInfo().getDomain() + " " + event.getInfo().getKey());
}
}
I had a similar problem two.
The problem might come from your firewall settings.
In my case the javaw.exe had access to all incoming calls but could not send anything to anyone as the firewall blocked it.
Try turning of the firewall to test you programm and to be shure thats not the firewall causing the problem.
Same issue here. Starting java with the following argument solved it for me:
-Djava.net.preferIPv4Stack=true
I am trying to implement JNotify. but I am getting a bit weird error messages when I compiled the program. I get the sample code from this site ttp://jnotify.sourceforge.net/sample.html
as an info, JNotify is used for directory monitoring and this is how my source code looks like.
this is the content of the class watching.java
import net.contentobjects.jnotify.JNotifyListener;
import net.contentobjects.jnotify.JNotify;
public class watching{
public void watching(String s) throws Exception {
// path to watch
String path = System.getProperty(s);
// watch mask, specify events you care about,
// or JNotify.FILE_ANY for all events.
int mask = JNotify.FILE_CREATED |
JNotify.FILE_DELETED |
JNotify.FILE_MODIFIED |
JNotify.FILE_RENAMED;
// watch subtree?
boolean watchSubtree = true;
// add actual watch
int watchID = JNotify.addWatch(path, mask, watchSubtree, new Listener());
// sleep a little, the application will exit if you
// don't (watching is asynchronous), depending on your
// application, this may not be required
Thread.sleep(1000000);
// to remove watch the watch
boolean res = JNotify.removeWatch(watchID);
if (!res) {
// invalid watch ID specified.
}
}
class Listener implements JNotifyListener {
public void fileRenamed(int wd, String rootPath, String oldName,
String newName) {
print("renamed " + rootPath + " : " + oldName + " -> " + newName);
}
public void fileModified(int wd, String rootPath, String name) {
print("modified " + rootPath + " : " + name);
}
public void fileDeleted(int wd, String rootPath, String name) {
print("deleted " + rootPath + " : " + name);
}
public void fileCreated(int wd, String rootPath, String name) {
print("created " + rootPath + " : " + name);
}
void print(String msg) {
System.err.println(msg);
}
}
}
then this is the main class that named nowwatch.java
public class nowwatch
{
public static void main(String[] args) throws Exception
{
System.out.println("Hello World!");
watching hello = new watching();
hello.watching("C:/Users/Raden/Documents/Downloads");
}
}
but why did the error went like this? I had screenshot the error so that you can see it by clicking on this link
has any of you ever experience this type of error? any help would be appreciated though.
thanks
JNotify surely uses JNI to interface with the OS-dependent notification APIs. Looks like there's a bug in JNotify. Have you tried asking on the JNotify forum on SourceForge?
We had the same problems. Because we used JNA anyways, we just used the FileMonitor example from this framework. Works like a charm.
it ask for jNotify.dll file, make sure that you have placed that file to the window or in jre/bin or jdk/bin. and then try it will start working.