DateTime compareTo not applicable to DateTime - java

The investigation and details for the accepted answer are in the comments to the question.
I have a small Java project that reads a schedule and puts Joda-Time Intervals into a sorted map (TreeMap in this case) for further processing.
This is done via a ScheduledExecutorService:
executor.scheduleWithFixedDelay(new Runnable() {
#Override
public void run() {
try {
doWork();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}, 1, 1, TimeUnit.SECONDS);
doWork() then reads a file, creates some intervals and then populates the map using this comparator (specified in the map constructor):
#Override
public int compare(Interval o1, Interval o2) {
return o1.getStart().compareTo(o2.getStart());
}
The code then breaks in the comparator when inserting the very first interval.
Usually I would think there is something wrong with the interval itself, however I have checked several possibilities and noticed multiple odd things that I got lost in:
The interval is fine, o1 and o2 are valid DateTimes with the same long timestamp.
No exception is caught. The thread just ceases work.
When I launch the app from Eclipse, everything works fine. It only breaks when launching a deployed version. By deployed I mean it was packed into a .jar and copied over to a shared directory, no containers here.
Changing
try {
doWork();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
to
try {
doWork();
} catch (Throwable e) {
e.printStackTrace();
throw new RuntimeException(e);
}
fixes it. (I.e. map gets populated fine, including the original first interval).
The last part makes me think it is a bug with JIT or JVM, rather than with the code.
I have also explored the possibility of this being a build issue, however it does not seem to be the case:
Both Eclipse and the build server use Java 7 (Eclipse 7.0.51, Build server: 7.0.25, Launched the deployed version with a 7.0.51 JRE)
Joda time library version is the same both in Eclipse and deployed lib folder (2.1)
This is NOT a new feature and the very same code works in a different branch, and has been for a couple of weeks now
I have tried stopping Eclipse from using its own cached Ivy libraries, and instead use the libraries in the deployed directory. Same stuff - works from Eclipse, doesn't work when launching jar with Java.
After a bit of remote-debugging I have reproduced something of the like: Method "compareTo" with signature "(Lorg/joda/time/ReadableInstant;)I" is not applicable on this object with the target object being class org.joda.time.DateTime when breakpointing in the comparator code.
Any help in how to debug this further would be appreciated.
EDIT:
private void doWork() {
SortedMap<Interval, String> map = new TreeMap<>(new Comparator<Interval>() {
#Override
public int compare(Interval o1, Interval o2) {
return o1.getStart().compareTo(o2.getStart());
}
});
Collection<String> col1 = new HashSet<>();
Collection<String> col2 = new HashSet<>();
String string = "";
long ts = 0;
try (FileInputStream input = new FileInputStream(fileName);
InputStreamReader isr = new InputStreamReader(input);
BufferedReader reader = new BufferedReader(isr)) {
String line = reader.readLine();
map.put(new Interval(new DateTime(), new DateTime()), "");
}
}
While this does not look like an SSCCE due to a lot of extra code, if I remove the Collection declarations or the line read, or put anything in the map before the try block (and then do the rest as is) - everything works fine. Makes me think of race conditions, however all variables involved here are local (except fileName, which is guaranteed to have been set).
Also, while trying out stuff I found that switching to Joda-time 2.3 from 2.1 apparently fixes the problem. However I do not see anything in their changelog of bugfixes that looks even remotely relevant.

Here a summarizing answer on base of my comments:
Does the remote side have a second JodaTime version? Maybe an older one before version 2.0 where the Comparable-handling changed a little bit (see generified interface ReadableInstant)? Pre 2.0 the method in question had the signature compareTo(Object) while in 2.0 and later the new signature compareTo(ReadableInstant), see also the release notes. This situation of two joda-jars and a connected classloading-issue would explain following exception message:
Method "compareTo" with signature "(Lorg/joda/time/ReadableInstant;)I" is not applicable on this object with the target object being class org.joda.time.DateTime.
(Your question was tricky and has deserved even more upvotes. Glad to hear that you found the reason in JRuby-library containing an older JodaTime-version.)

Related

Problems with SmbFile.createNewFile() behaviour

I wonder what the catch is with createNewFile() in recent versions of jCIFS and ng (SMB2 specifically). The documentation says it should fail on execution if a file already exists, but that is not the case in my code, the file is always overwritten instead of throwing a SmbException. I need to be able to rename the file so it is not overwritten, but due to server load and quantity I cannot use exists(). This snippet worked perfectly on SMB1:
for (int i = 0; !fileCreated && (i < maxCopies); i++) {
try {
smbFile.createNewFile();
fileCreated = true;
} catch (SmbException e) {
smbFile = new SmbFile(smbFilePath.concat(String.valueOf(i)), auth);
}
}
I've been searching high and low and trying out different versions of SMB2, but createNewFile() always does the opposite of what the javadoc says it should. Is there a simple way (using attributes for example) to make it work just as in SMB1?
EDIT: Solution by jcifs-ng developer on GitHub
Apparently I got the behavior wrong when implementing the SMB2
version. Create disposition should be FILE_CREATE not FILE_OPEN_IF,
then ( O_EXCL in SMB1). Let me look into making that change, and how
much havoc this will cause. You could potentially work around this by
explicitly calling openOutputStream and passing O_EXCL as open flag.

delete file after serving over HTTP in play framework - java

How do i delete a file after serving it over http,
Files.TemporaryFile file = null;
try {
file = new Files.TemporaryFile(f);
return ok().sendFile(file.file());
} catch (IllegalArgumentException e) {
return badRequest(Json.newObject().put("message", e.getMessage()));
} finally {
file.clean();
}
with this code, the file gets deleted before it is served. i receive an empty file on the client.
Play framework in version 2.8 should support onClose argument in sendFile method also in Java (so far it seems to be supported only in Scala version).
In older versions (I have tried only on 2.7.x) you may apply the same approach like in the fix for 2.8, so:
public Result doSomething() {
final File fileToReturn = ....;
final Source<ByteString, CompletionStage<IOResult>> source = FileIO.fromFile(fileToReturn);
return Results.ok().streamed(wrap(source, () -> fileToReturn.delete()), Optional.of(fileToReturn.length()), Optional.of("content type, e.g. application/zip"));
}
private Source<ByteString, CompletionStage<IOResult>> wrap(final Source<ByteString, CompletionStage<IOResult>> source, final Runnable handler) {
return source.mapMaterializedValue(
action -> action.whenCompleteAsync((ioResult, exception) -> handler.run())
);
}
From reading the JavaFileUpload documentation for 2.6.x, it sounds like you don't need that finally block to clean up the file afterwards. Since you are using a TemporaryFile, garbage collection should take care of deleting the resource:
...the idea behind TemporaryFile is that it’s only in scope at completion and should be moved out of the temporary file system as soon as possible. Any temporary files that are not moved are deleted [by the garbage collector].
The same section goes on to describe that there is the potential that the file will not get garbage collection causing Denial Of Service issues. If you find that the files are not getting removed, then you can use the TemporaryFilesReaper:
However, under certain conditions, garbage collection does not occur in a timely fashion. As such, there’s also a play.api.libs.Files.TemporaryFileReaper that can be enabled to delete temporary files on a scheduled basis using the Akka scheduler, distinct from the garbage collection method.
I am not forcing all the project, but you can use a Scala for only this controller, then you can use onClose parameter of the sendFile method. The only attention - that parameter is not workable in all versions, it looks like in 2.5 there was an issue so it was not triggered (was not work: https://github.com/playframework/playframework/issues/6351).
Another way - you can use Akka streams, like here: https://www.playframework.com/documentation/2.6.x/JavaStream#Chunked-responses.

Why sun.swing.AccessibleMethod is gone from JDK 8?

I'm wondering if someone know why sun.swing.AccessibleMethod is gone from JDK 8 and if there is some alternative to this class in JDK 8?
I can't find any information about that anywhere.
I use this class in my own implementation DropHandler. Code snippet where I use sun.swing.AccessibleMethod looks like this:
private DropLocation getDropLocation(DropTargetEvent e)
{
DropLocation dropLocation = null;
if (this.component != null)
{
try
{
Point p = e instanceof DropTargetDragEvent ? ((DropTargetDragEvent)e).getLocation() : ((DropTargetDropEvent) e).getLocation();
AccessibleMethod method = new AccessibleMethod(JComponent.class,
"dropLocationForPoint",
Point.class);
dropLocation = (DropLocation) method.invokeNoChecked(this.component, p);
}
catch (NoSuchMethodException ex)
{
LOGGER.info(ex.getMessage());
}
}
return dropLocation;
}
As explained in this official post from Oracle: Why Developers Should Not Write Programs That Call 'sun' Packages (thanks to #greg-449 for providing this info):
The sun.* packages are not part of the supported, public interface.
A Java program that directly calls into sun.* packages is not guaranteed to work on all Java-compatible platforms. In fact, such a program is not guaranteed to work even in future versions on the same platform.
So, you should not have relied on sun.swing.AccessibleMethod class in the first place.
More info:
It is a bad practice to use Sun's proprietary Java classes?
As a solution for your problem, you can do the following:
Use the source code of sun.swing.AccessibleMethod to create a custom class.
Replace the usage of AccessibleMethod by your own custom class.
What’s the point about this AccessibleMethod class?
The following uses standard Java API which exists since Java 1.2:
try {
Method method = JComponent.class
.getDeclaredMethod("dropLocationForPoint", Point.class);
method.setAccessible(true);
dropLocation = (DropLocation) method.invoke(this.component, p);
} catch(NoSuchMethodException|IllegalAccessException|InvocationTargetException ex) {
Logger.info(ex.getMessage());
}
However, don’t come back and ask why JComponent.dropLocationForPoint has been removed, if that happens in the future. If you are accessing non-standard APIs you may encounter such problems. To be exact, there were always Java implementations not having these features your code relies on...

Is there a way to get, at runtime, the version of Guava in use?

I did a quick grep of the Guava source and documentation, and neither seem to have any mention of versions. I was wondering if there was a way Guava's version information can be obtained at runtime.
This version information doesn't have to be accessible via any getter, if no such thing actually exists; if it's stashed in a field somewhere that doesn't get GC'd while Guava is loaded, that would be sufficient.
Is this version information available anywhere at runtime?
I have a very specific use for this. A big part of my work is analysing Java heap dumps to identify and fix places in the code that cause exorbitant memory usage. For this task, I use fasthat, a heavily-modified version of jhat with special features useful to my work.
One of those features is to display the contents of containers. I've already implemented this for the likes of ArrayList, HashMap, ConcurrentHashMap, etc. (I implement type printers on demand, based on what I encounter in our heap dumps.) Currently, I'm implementing a type printer for Guava's CustomConcurrentHashMap.
Since the layout of structures can change between versions, my code tweaks its unpacking behaviour based on what version is in use. For example, at work, we used to use JRuby 1.2, but recently switched to JRuby 1.6, so I have type printers for both of those versions, and it selects the version based on the version information it finds in the heap dump.
So, that's the point of the second paragraph of the question: if the version information is anywhere in the heap dump, that's all I need.
And before anyone asks: heap dump data is not "live", so you cannot simply call toString or the like. You really have to walk the data structures to extract the bits out, and you really do have to use implementation details to the nth degree. ;-)
If you want to get the version of a maven built class, you can start with the class, find the jar it comes from and read the meta information which maven adds (such as the version)
A simpler way to do this, if the version is in the path, is to look at your classpath, find guava and the version you are using from the file name.
For a heap dump, the class path is in a System property.
This is more of a workaround, but I guess you could do this if there is no simpler way of accessing the Guava version:
In most Guava releases, classes / fields / methods are added / removed. You could try to look for them in the heap dump, and, depending on their existence, determine the Guava version.
Something like:
/**
* A {#link Predicate} that checks whether a class exists in the given {#link HeapDump}
*/
public class ClassExistsPredicate implements Predicate<String> {
private final HeapDump heapDump;
public ClassExistsPredicate(HeapDump heapDump) {
this.heapDump = heapDump;
}
#Override
public boolean apply(String fullyQualifiedClassName) {
// checks whether the given class exists in the heap dump
return true;
}
}
public enum GuavaVersion {
R01,
R02 {
#Override
Set<String> getAddedClasses() {
return ImmutableSet.of("com.google.common.base.Foo");
}
},
R03 {
#Override
Set<String> getAddedClasses() {
return ImmutableSet.of("com.google.common.collect.ForwardingFooIterator");
}
},
R04 {
#Override
Set<String> getAddedClasses() {
return ImmutableSet.of("com.google.common.collect.FooFoo2");
}
};
/**
* #return a {#link Set} of added class names that uniquely identify this version from the preceding one (not
* necessarily <b>all</b> classes!)
*/
Set<String> getAddedClasses() {
return ImmutableSet.of();
}
public static GuavaVersion getGuavaVersionFor(HeapDump heapDump) {
ClassExistsPredicate classExists = new ClassExistsPredicate(heapDump);
for (GuavaVersion version : Lists.reverse(Arrays.asList(GuavaVersion.values()))) {
if (Iterables.all(version.getAddedClasses(), classExists)) {
return version;
}
}
throw new RuntimeException("Unable to determine Guava version...");
}
}
Obviously, you should cache the Guava version number, since the computation might be slow... The approach could be extended to consider added methods / fields.
This approach could work with other projects, too.
You can retrieve the version from Guava's JAR manifest.
public static String getGuavaVersion() {
try {
File file = new File(Charsets.class.getProtectionDomain().getCodeSource().getLocation().toURI());
try (JarFile jar = new JarFile(file)) {
return jar.getManifest().getMainAttributes().getValue("Bundle-Version");
}
} catch (Exception ex) {
throw new RuntimeException("Unable to get the version of Guava", ex);
}
}
Unfortunately, this works only for Guava 11+. Guava 10 and older were not OSGI bundles yet.
Another option is to retrieve the version from pom.properties. This works for old versions of Guava too: https://gist.github.com/seanizer/8de050427f3f199cf8f085b2a3a2473e

Query Windows Search from Java

I would like to get to query Windows Vista Search service directly ( or indirectly ) from Java.
I know it is possible to query using the search-ms: protocol, but I would like to consume the result within the app.
I have found good information in the Windows Search API but none related to Java.
I would mark as accepted the answer that provides useful and definitive information on how to achieve this.
Thanks in advance.
EDIT
Does anyone have a JACOB sample, before I can mark this as accepted?
:)
You may want to look at one of the Java-COM integration technologies. I have personally worked with JACOB (JAva COm Bridge):
http://danadler.com/jacob/
Which was rather cumbersome (think working exclusively with reflection), but got the job done for me (quick proof of concept, accessing MapPoint from within Java).
The only other such technology I'm aware of is Jawin, but I don't have any personal experience with it:
http://jawinproject.sourceforge.net/
Update 04/26/2009:
Just for the heck of it, I did more research into Microsoft Windows Search, and found an easy way to integrate with it using OLE DB. Here's some code I wrote as a proof of concept:
public static void main(String[] args) {
DispatchPtr connection = null;
DispatchPtr results = null;
try {
Ole32.CoInitialize();
connection = new DispatchPtr("ADODB.Connection");
connection.invoke("Open",
"Provider=Search.CollatorDSO;" +
"Extended Properties='Application=Windows';");
results = (DispatchPtr)connection.invoke("Execute",
"select System.Title, System.Comment, System.ItemName, System.ItemUrl, System.FileExtension, System.ItemDate, System.MimeType " +
"from SystemIndex " +
"where contains('Foo')");
int count = 0;
while(!((Boolean)results.get("EOF")).booleanValue()) {
++ count;
DispatchPtr fields = (DispatchPtr)results.get("Fields");
int numFields = ((Integer)fields.get("Count")).intValue();
for (int i = 0; i < numFields; ++ i) {
DispatchPtr item =
(DispatchPtr)fields.get("Item", new Integer(i));
System.out.println(
item.get("Name") + ": " + item.get("Value"));
}
System.out.println();
results.invoke("MoveNext");
}
System.out.println("\nCount:" + count);
} catch (COMException e) {
e.printStackTrace();
} finally {
try {
results.invoke("Close");
} catch (COMException e) {
e.printStackTrace();
}
try {
connection.invoke("Close");
} catch (COMException e) {
e.printStackTrace();
}
try {
Ole32.CoUninitialize();
} catch (COMException e) {
e.printStackTrace();
}
}
}
To compile this, you'll need to make sure that the JAWIN JAR is in your classpath, and that jawin.dll is in your path (or java.library.path system property). This code simply opens an ADO connection to the local Windows Desktop Search index, queries for documents with the keyword "Foo," and print out a few key properties on the resultant documents.
Let me know if you have any questions, or need me to clarify anything.
Update 04/27/2009:
I tried implementing the same thing in JACOB as well, and will be doing some benchmarks to compare performance differences between the two. I may be doing something wrong in JACOB, but it seems to consistently be using 10x more memory. I'll be working on a jcom and com4j implementation as well, if I have some time, and try to figure out some quirks that I believe are due to the lack of thread safety somewhere. I may even try a JNI based solution. I expect to be done with everything in 6-8 weeks.
Update 04/28/2009:
This is just an update for those who've been following and curious. Turns out there are no threading issues, I just needed to explicitly close my database resources, since the OLE DB connections are presumably pooled at the OS level (I probably should have closed the connections anyway...). I don't think I'll be any further updates to this. Let me know if anyone runs into any problems with this.
Update 05/01/2009:
Added JACOB example per Oscar's request. This goes through the exact same sequence of calls from a COM perspective, just using JACOB. While it's true JACOB has been much more actively worked on in recent times, I also notice that it's quite a memory hog (uses 10x as much memory as the Jawin version)
public static void main(String[] args) {
Dispatch connection = null;
Dispatch results = null;
try {
connection = new Dispatch("ADODB.Connection");
Dispatch.call(connection, "Open",
"Provider=Search.CollatorDSO;Extended Properties='Application=Windows';");
results = Dispatch.call(connection, "Execute",
"select System.Title, System.Comment, System.ItemName, System.ItemUrl, System.FileExtension, System.ItemDate, System.MimeType " +
"from SystemIndex " +
"where contains('Foo')").toDispatch();
int count = 0;
while(!Dispatch.get(results, "EOF").getBoolean()) {
++ count;
Dispatch fields = Dispatch.get(results, "Fields").toDispatch();
int numFields = Dispatch.get(fields, "Count").getInt();
for (int i = 0; i < numFields; ++ i) {
Dispatch item =
Dispatch.call(fields, "Item", new Integer(i)).
toDispatch();
System.out.println(
Dispatch.get(item, "Name") + ": " +
Dispatch.get(item, "Value"));
}
System.out.println();
Dispatch.call(results, "MoveNext");
}
} finally {
try {
Dispatch.call(results, "Close");
} catch (JacobException e) {
e.printStackTrace();
}
try {
Dispatch.call(connection, "Close");
} catch (JacobException e) {
e.printStackTrace();
}
}
}
As few posts here suggest you can bridge between Java and .NET or COM using commercial or free frameworks like JACOB, JNBridge, J-Integra etc..
Actually I had an experience with with one of these third parties (an expensive one :-) ) and I must say I will do my best to avoid repeating this mistake in the future. The reason is that it involves many "voodoo" stuff you can't really debug, it's very complicated to understand what is the problem when things go wrong.
The solution I would suggest you to implement is to create a simple .NET application that makes the actual calls to the windows search API. After doing so, you need to establish a communication channel between this component and your Java code. This can be done in various ways, for example by messaging to a small DB that your application will periodically pull. Or registering this component on the machine IIS (if exists) and expose simple WS API to communicate with it.
I know that it may sound cumbersome but the clear advantages are: a) you communicate with windows search API using the language it understands (.NET or COM) , b) you control all the application paths.
Any reason why you couldn't just use Runtime.exec() to query via search-ms and read the BufferedReader with the result of the command? For example:
public class ExecTest {
public static void main(String[] args) throws IOException {
Process result = Runtime.getRuntime().exec("search-ms:query=microsoft&");
BufferedReader output = new BufferedReader(new InputStreamReader(result.getInputStream()));
StringBuffer outputSB = new StringBuffer(40000);
String s = null;
while ((s = output.readLine()) != null) {
outputSB.append(s + "\n");
System.out.println(s);
}
String result = output.toString();
}
}
There are several libraries out there for calling COM objects from java, some are opensource (but their learning curve is higher) some are closed source and have a quicker learning curve. A closed source example is EZCom. The commercial ones tend to focus on calling java from windows as well, something I've never seen in opensource.
In your case, what I would suggest you do is front the call in your own .NET class (I guess use C# as that is closest to Java without getting into the controversial J#), and focus on making the interoperability with the .NET dll. That way the windows programming gets easier, and the interface between Windows and java is simpler.
If you are looking for how to use a java com library, the MSDN is the wrong place. But the MSDN will help you write what you need from within .NET, and then look at the com library tutorials about invoking the one or two methods you need from your .NET objects.
EDIT:
Given the discussion in the answers about using a Web Service, you could (and probably will have better luck) build a small .NET app that calls an embedded java web server rather than try to make .NET have the embedded web service, and have java be the consumer of the call. For an embedded web server, my research showed Winstone to be good. Not the smallest, but is much more flexible.
The way to get that to work is to launch the .NET app from java, and have the .NET app call the web service on a timer or a loop to see if there is a request, and if there is, process it and send the response.

Categories

Resources