ServiceManager.getServiceNames() returns null. Why? - java

I had a little app which was able to save and load files. Then I decided to try Java Web Start, so that I needed to rewrite JFileChooser usage to jnlp stuff.
Looking at http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle.com/javase/tutorial/uiswing/examples/components/JWSFileChooserDemoProject/src/components/JWSFileChooserDemo.java I've tried to rewrite my code.
Here what I came with
FileSaveService fss = null;
FileContents fileContents = null;
ByteArrayInputStream is = new ByteArrayInputStream(
(new String("Saved by JWSFileChooserDemo").getBytes()));
try {
String[] services = ServiceManager.getServiceNames();
fss = (FileSaveService)ServiceManager.
lookup("javax.jnlp.FileSaveService");
}
catch (UnavailableServiceException exc) { }
if (fss != null) {
try {
fileContents = fss.saveFileDialog(null, null, is, null);
}
and so on.
At first there were no ServiceManager.getServiceNames call, and my the ServiceManager.lookup returned null. So I decided to get the service list, and getServiceNames returns null also.
How can I make it to find FileSaveService? Where does the method looks for this service, and shouldn't I write some extra stuff somewhere to declare that I need that service?
UPD: I've tried to run JWSFileChooserDemo from the oracle's link above, and it doesn't work. Same thing with ServiceManager.lookup that returns null.

Related

No NullPointerException on the logs

I have a strange behaviour in my java code I would like to ask some advice.
In a multithreading application I wrote this code:
scratchDir.resolve(directoryTree).toFile().mkdirs();
For a bug the Object scratchDir is null, I was expecting a stack trace on the logs but there's nothing about the error.
I have checked the code and I never try to catch the NullPointerException.
Here is the complete method code:
#Override
public void write(JsonObject jsonObject) throws FileSystemException {
Path directoryTree = getRelativePath();
scratchDir.resolve(directoryTree).toFile().mkdirs();
String newFileName = getHashFileName(jsonObject);
Path filePath = scratchDir.resolve(directoryTree).resolve(newFileName);
logger.debug("Write new file Json {} to persistent storage dir {}", newFileName, scratchDir);
File outputFile = filePath.toFile();
if (outputFile.exists()) {
throw new FileAlreadyExistsException(filePath.toString());
}
try (FileWriter fileWriter = new FileWriter(outputFile)) {
fileWriter.write(jsonObject.toString());
fileWriter.flush();
} catch (Exception e) {
logger.error(e);
}
}
Why I don't have the exception in my logs?
Why are you doing this?
The proper way to do this is:
Files.createDirectories(scratchDir.resolve(directoryTree));
don't mix old and new API. The old mkdirs() api DEMANDS that you check the return value; if it is false, the operation failed, and you do not get the benefit of an exception to tell you why. This is the primary reason for why there is a new API in the first place.
Are you sure you aren't confused - and that is the actual problem? The line as you have it will happily do absolutely nothing whatsoever (no directories, and no logs or exceptions). The line above will throw if it can't make the directories, so start there.
Then, if that line IS being run and nothing is logged, then you've caught the NPE and discarded it, someplace you didn't paste.

Domino app - how to access the source document in java during custom file attachment routine

This is a non-xpages application.
I have inherited some code that I need to tweak....this code is used in a drag&drop file attachment subform. Normally, this will create a document in a separate dedicated .nsf that stores only attachments, and uses the main document's universalid as a reference to link the two....I need to change what the reference is to the value in a field already on the main document (where the subform is).
Java is challenging to me, but all I need to do is GET the value of the field from the main document (which has not necessarily been saved yet) and write that string value onto the attachment doc in that storage database, so I think I am just needing help with one line of code.
I will paste the relevant function here and hopefully someone can tell me how I get that value, or what else they need to see what is going on here.
You can see my commented-out attempt to write the field 'parentRef' in this code
...
private void storeUploadedFile( UploadedFile uploadedFile, Database dbTarget) {
File correctedFile = null;
RichTextItem rtFiles = null;
Document doc = null;
String ITEM_NAME_FILES = "file";
try {
if (uploadedFile==null) {
return;
}
doc = dbTarget.createDocument();
doc.replaceItemValue("form", "frmFileUpload");
doc.replaceItemValue("uploadedBy", dbTarget.getParent().getEffectiveUserName() );
Utils.setDate(doc, "uploadedAt", new Date() );
doc.replaceItemValue("parentUnid", parentUnid);
//doc.replaceItemValue("parentRef", ((Document) dbTarget.getParent()).getItemValue("attachmentDocKey"));
//get uploaded file and attach it to the document
fileName = uploadedFile.getClientFileName();
File tempFile = uploadedFile.getServerFile(); //the uploaded file with a cryptic name
fileSize = tempFile.length();
targetUnid = doc.getUniversalID();
correctedFile = new java.io.File( tempFile.getParentFile().getAbsolutePath() + java.io.File.separator + fileName );
//rename the file on the OS so we can embed it with the correct (original) name
boolean success = tempFile.renameTo(correctedFile);
if (success) {
//embed original file in target document
rtFiles = doc.createRichTextItem(ITEM_NAME_FILES);
rtFiles.embedObject(lotus.domino.EmbeddedObject.EMBED_ATTACHMENT, "", correctedFile.getAbsolutePath(), null);
success = doc.save();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
com.gadjj.Utils.recycle(rtFiles, doc);
try {
if (correctedFile != null) {
//rename the temporary file back to its original name so it's automatically
//removed from the os' file system.
correctedFile.renameTo(uploadedFile.getServerFile());
}
} catch(Exception ee) { ee.printStackTrace(); }
}
}
}
...
dbTarget.getParent does not do what you think it does. It returns a Session object that is the parent session containing all your objects. Casting it to (Document) won't give you your main document.
I don't see the declaration for it, but you appear to have a variable available called parentUNID. You can use it to get a handle on the main document.
You need to use the parentUNID value in a call to getDocumentByUNID() in order to retrieve the Document object representing your main document. But in order to do that, you need the Database object for the nsf file containing the main document, and if I understand you correctly, that is a different database than targetDb.
I'm going to have to assume that you already have that Database object in a variable called parentDb, or that you know the path to the NSF and can open it. In either case, your code would look like this (without error handling):
Document parentDoc = parentDb.getDocumentByUNID(parentUNID);
doc.replaceItemvalue("parentRef", parentDoc.getItemValue("attachmentDocKey"));

Change in file after creating FileOutputStream object even without writing anything into file

EDIT (for the sake of confusion): null has been written into the files "abc" and "efg".
After running the following code, the contents of file "abc" change which were initially null , and I get EOFException in every next execution :
ObjIStream = new ObjectInputStream(new FileInputStream("abc"));
M[][] objs = (M[][]) ObjIStream.readObject();
FS.objs = objs;
ObjIStream.close();
Here, FS.objs is a static member of class FS of type M[][] type.
On the other hand, this one has no effect on the file and I don't get any Exceptions after any number of executions:
ObjIStream = new ObjectInputStream(new FileInputStream("abc"));
M[][] objs = (M[][]) ObjIStream.readObject();
ObjIStream.close();
EDIT: I just found the trouble that exists in class FS in this form:
static{
try {
ObjOStream = new ObjectOutputStream(new FileOutputStream("abc"));
ObjOStream.close();
ObjOStream = new java.io.ObjectOutputStream(new java.io.FileOutputStream("efg"));
ObjOStream.close();
}
catch (IOException ex) { }
}
How is it troubling anyways?
The problem is new FileOutputStream("abc") itself, which means new FileOutputStream("abc", false). It cleans up all the data in file because you are not going to append anything. It calls FileOutputStream.open(String name, boolean append) which is a private native function. It erases everything in file in overwrite mode.

How to get the opened document using UNO?

I'm writing an add-on that opens a dialog and I need to access the currently opened text document but I don't know how get it.
I'm using the OpenOffice plug-in in NetBeans and I started from an Add-on project. It created a class that gives me a XComponentContext instance but I don't know how to use it to get a OfficeDocument instance of the current document.
I've been googling for some time and I can't find any example that uses an existing, opened, document. They all start from a new document or a document that is loaded first so they have an URL for it.
I gave it a try based on the OpenOffice wiki (https://wiki.openoffice.org/wiki/API/Samples/Java/Office/DocumentHandling) and this is what I came up with:
private OfficeDocument getDocument() {
if (this.officeDocument == null) {
try {
// this causes the error
XMultiComponentFactory xMultiComponentFactory = this.xComponentContext.getServiceManager();
Object oDesktop = xMultiComponentFactory.createInstanceWithContext("com.sun.star.frame.Desktop", this.xComponentContext);
XComponentLoader xComponentLoader = UnoRuntime.queryInterface(XComponentLoader.class, oDesktop);
String url = "private:factory/swriter";
String targetFrameName = "_self";
int searchFlags = FrameSearchFlag.SELF;
PropertyValue[] propertyValues = new PropertyValue[1];
propertyValues[0] = new PropertyValue();
propertyValues[0].Name = "Hidden";
propertyValues[0].Value = Boolean.TRUE;
XComponent xComponent = xComponentLoader.loadComponentFromURL(url, targetFrameName, searchFlags, propertyValues);
XModel xModel = UnoRuntime.queryInterface(XModel.class, xComponent);
this.officeDocument = new OfficeDocument(xModel);
} catch (com.sun.star.uno.Exception ex) {
throw new RuntimeException(ex);
}
}
return this.officeDocument;
}
But there is something strange going on. Just having this method in my class, even if it's never been called anywhere, causes an error when adding the add-on.
(com.sun.star.depoyment.DeploymentDescription){{ Message = "Error during activation of: VaphAddOn.jar", Context = (com.sun.star.uno.XInterface) #6ce03e0 }, Cause = (any) {(com.sun.star.registry.CannotRegisterImplementationException){{ Message = "", Context = (com.sun.star.uno.XInterface) #0 }}}}
It seems this line causes the error:
XMultiComponentFactory xMultiComponentFactory = this.xComponentContext.getServiceManager();
I have no idea how to preceed.
I posted this question on the OpenOffice forum but I haven't got a response there. I'm trying my luck here now.
Use this in your code to get the current document:
import com.sun.star.frame.XDesktop;
...
XDesktop xDesktop = (XDesktop) UnoRuntime.queryInterface(XDesktop.class, oDesktop);
XComponent xComponent = xDesktop.getCurrentComponent();
I opened the BookmarkInsertion sample in NetBeans and added this code to use the current document instead of loading a new document.
As far as the error, there may be a problem with how it is getting built. A couple of things to check:
Does the Office SDK version match the Office version? Check version number and whether it's 32- or 64-bit.
Make sure that 4 .jar files (juh.jar, jurt.jar, unoil.jar, ridl.jar) are shown under Libraries in NetBeans, because they need to be included along with the add-on.
If you get frustrated with trying to get the build set up correctly, then you might find it easier to use python, since it doesn't need to be compiled. Also python does not require queryInterface().

How can I use an assertion to test this java code?

My homework assignment is to read a URL and print all hyperlinks at that URL to a file. I also need to submit a junit test case with at least one assertion. I have looked at the different forms of Assert but I just can't come up with any use of them that applies to my code. Any help steering me in the right direction would be great.
(I'm not looking for anyone to write the test case for me, just a little guidance on what direction I should be looking in)
public void saveHyperLinkToFile(String url, String fileName)
throws IOException
{
URL pageLocation = new URL(url);
Scanner in = new Scanner(pageLocation.openStream());
PrintWriter out = new PrintWriter(fileName);
while (in.hasNext())
{
String line = in.next();
if (line.contains("href=\"http://"))
{
int from = line.indexOf("\"");
int to = line.lastIndexOf("\"");
out.println(line.substring(from + 1, to));
}
}
in.close();
out.close();
}
}
Try to decompose your method into simpler ones:
List<URL> readHyperlinksFromUrl(URL url);
void writeUrlsToFile(List<URL> urls, String fileName);
You could already test your first method by saving a sample document as a resource and running it against that resource, comparing the result with the known list of URLs.
You can also test the second method by re-reading that file.
But you can decompose things further on:
void writeUrlsToWriter(List<URL> urls, Writer writer);
Writer createFileWriter(String fileName);
Now you can test your first method by writing to a StringWriter and checking, what was written there by asserting the equality of writer.toString() with the sample value. Not that methods are becoming simpler and simpler.
It would be actually a very good excercise to write the whole thing test-first or even play ping-pong with yourself.
Good luck and happy coding.

Categories