tada / pljava

PL/Java is a free add-on module that brings Java™ Stored Procedures, Triggers, Functions, Aggregates, Operators, Types, etc., to the PostgreSQL™ backend.
http://tada.github.io/pljava/
Other
238 stars 77 forks source link

Unknown dbf protocol #400

Closed gjevardat closed 2 years ago

gjevardat commented 2 years ago

Hello

I have an issue similar to #266 though it looks sligthly different since I'am using pl Java 1.6.3 REL1_6_STABLE. I'am on JDK 17+ Here is the detailed description of the issue after some debugging.

Problem is triggered by the loading of XSD schema.

SchemaFactory sf = SchemaFactory.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI);
URL schemaFile = MyClass.class.getClassLoader().getResource("schema.xsd");
Schema schema = sf.newSchema(schemaFile);

I get the URL of the schema. It works and returns an URL : dbf://localhost/1101215. The jar_entry is here and its id matches exactly the schema.xsd file that is wrapped into the jar.

Problem happens in the next step when I want to instantiate the Schema ( 3rd line of the snipped above) After initialising many Jaxb and Xml stuff we arrive at the actual URL reading.

It happens like that in the java.net.URL class :

static URLStreamHandler getURLStreamHandler(String protocol) {

URLStreamHandler handler = handlers.get(protocol);  URLStreamHandler handler = handlers.get(protocol);
...

where protocol = "dbf" Here the main point in that in handlers Hashtable only "sqlj protocol is registered" by pljava and all fallback strategies to get the handler are returning null.

I see pljava has 2 classes that override URLStreamHandler. One override for the sqlj protocol that is registered in the URL handlers. The other one which looks the most important is the EntryStreamHandler that performs the actual query to load the serialized image of the classes and ressources. But this one is not registered in the URL handlers ( at least in the scenario I'am reproducing here)

I'am wondering why the EntryStreamHandler does register the dbf protocol as it would allow to directly load dbf URLs ?

Thanks for any help.

PS: Reading issue #266 I see there is option to load ressources as file system resources on database host machine, but I would prefer to avoid this approach as it adds more steps in the deployement of the pljava code and ressources. To be clear, I tried but I could not figure out where to put the file. I tried with URL like "file:///schema.xsd" but was unsure were to put the file exactly

gjevardat commented 2 years ago

Just a quick update to inform that reading directly from a file worked, so in a sense I'am unblocked. I still think it should work smoothly from dbf protocol. Let me know if I can help. I could try to test and implement solution of registering the dbf protocol in the URL class by overriding the method createURLStreamHandler in the class EntryStreamHandler. This is the solution I have in mind, but I have only a very limited understanding of pljava as it was first time I debugged it. Meanwhile I'll advance with file loading...

jcflack commented 2 years ago

Yes, this is the #266 issue. I am sorry not to have improved that in a 1.6.x release.

I am reluctant to further implement the dbf scheme, because I would prefer to deprecate and replace it. It has a few problems; one is that dbf is a pretty arbitrary scheme name, and one is that the path portion is an arbitrary integer instead of a meaningful name, and one is that it directly identifies a component of a jar and not the jar itself (so it wasn't usable in 1.6 for granting codebase permissions in pljava.policy because those are granted to a jar as a whole, so the sqlj scheme had to be created for that anyway).

I have some code in the works to provide a usable scheme that works at the jar level (so then your individual resource URL would just be a jar: URL based on that, as you would normally expect), but that isn't near to release yet. There is also code in the works to implement the XML Catalog API that was added in Java 9. With that, you could just register your schema with the catalog and the rest would Just Work.

As a workaround until then, if you want to build a locally patched PL/Java with the dbf scheme registered and see if that works, that's one option.

Another workaround would be to use the newSchema(Source) overload, and supply your own StreamSource over the byte array you could retrieve from

SELECT entryimage
 FROM
  sqlj.jar_repository
  JOIN sqlj.jar_entry USING (jarId)
  WHERE jarname = 'myjar' and entryname = 'schema.xsd';

Admittedly, that's pretty much like repeating by hand what the dbf URL handler does, but saves you building a patched PL/Java.

Either workaround would have a limited lifespan, as when the PL/Java version with a working alternative is released, you would want to use that (and such a release will probably have changes in the sqlj schema that would break the above query).

You could sort of future-proof it by coding it to just try the straightforward URL way and try the fallback in an exception handler (or vice versa); that way you would not have to synchronize a new version with a new PL/Java release.

gjevardat commented 2 years ago

Many tanks for the detailed answer and for explaining a bit more on the gloomy future of dbf protocol :) As a consequence of future deprecation of dbf, I won't invest more time in patching it as I already spent quite some (interesting) time on debugging and will rely on loading my schema as a file. Indeed It's a bit more work for deployement, on the other hand this schema is quite stable so all in all I can wait for this next protocol !