1 2 Previous Next 25 Replies Latest reply on Apr 12, 2012 1:01 PM by skoure

    URL-Protocol Handler doesn't work

    dastraub

      We register some protocol handler via the system property "java.protocol.handler.pkgs".

      This works very well with JBoss 4.x and 5, but now in JBoss 7 the URL can't find our handler class (in java.net.URL.

      getURLStreamHandler). Here the URL will load the handler with Class.forName, but the result is always null.

      If we try to load the handler class in a EJB, it's work.

        • 1. Re: URL-Protocol Handler doesn't work
          alesj

          You need to use this mechanism for your custom URL protocol handler:

          * https://github.com/jbossas/jboss-modules/blob/master/src/main/java/org/jboss/modules/ModularURLStreamHandlerFactory.java

          --> register it as a service-loader pattern service / extension

          • 2. Re: URL-Protocol Handler doesn't work
            dastraub

            That is a solution, thanks for the fast response !

            But at the moment the protocol handlers are part of our application.

            In your solution the handler classes (with all dependencies) have to move to the server installation, in a module with a service extension.

            A hotdeploy or dynamic registration of handlers is impossible.

            Or can we register the handler as a service extension in our jar files ? I guess not, because the ModulearURLStreamHandlerFactory resolve this in a static initializer.

             

            The "java.protocol.handler.pkgs" - mechanism is a standard java way (more or less) what we use since a long time.

            It's hard to accept that this is impossible with the new AS7 and to change a long running, tested application.

            What's the reason for this ClassNotFoundException ?

            • 3. Re: URL-Protocol Handler doesn't work
              alesj

              A hotdeploy or dynamic registration of handlers is impossible.

              What about if you added a static handler impl, which would be capable of looking up a dynamic one?

              e.g. via TCCL + service-pattern lookup

              • 4. Re: URL-Protocol Handler doesn't work
                dastraub

                I thought about that, to deploy a small module what is registered by the ModulearURLStreamHandlerFactory and looks for other handlers.

                So we bring back the dynamic again

                • 5. Re: URL-Protocol Handler doesn't work
                  dmlloyd

                  Here's the problem.  URL stream handlers aren't, in fact, dynamic.  If you did in fact add a handler from a deployment (even if you did it indirectly via a static delegate), and then redeployed that deployment, the handler would still be served by the old deployment (it would leak, causing duplicate classes to be loaded).  That's why we don't support URL handlers from deployments.  The only correct way to do this currently is to use a static module.

                   

                  I've been working on a framework for dynamic URL handlers via deployments but it's been rather lower on the priority list.  Maybe this week though I can find a minute to get what I have up on github and I'll open a community JIRA so that this feature can be contributed.

                  • 6. Re: URL-Protocol Handler doesn't work
                    dastraub

                    Your right, the URL caches resolved handlers in a map.

                    What I mean with 'dynamic' is more that we ship the handler as part of the application and haven't to change the server installation.

                    Normaly, in a production enviroment we don't do hotdeployments and it's easy to deploy only one artifact instead of pdating the modules, configuration xml etc.

                    • 7. Re: URL-Protocol Handler doesn't work
                      thomas.diesler

                      OSGi supports the notion of dynamic URL handlers. See URLStreamHandlerService

                      • 8. Re: URL-Protocol Handler doesn't work
                        dastraub

                        Hi David

                        now I came back to this thread (because we're porting a large application to AS 7), and I use the following solution :

                        In a self developed extension we do some stuff during the deployment, and here also we add our URLStreamHandlerFactory :

                         

                         

                        @Override
                        public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
                            final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
                            final Module module = deploymentUnit.getAttachment(Attachments.MODULE);
                            URL url = module.getExportedResource("META-INF/services/java.net.URLStreamHandlerFactory");
                            if (url != null) {
                                log.info("registerURLStreamHandlerFactoryModule " + module.getIdentifier());
                                Module.registerURLStreamHandlerFactoryModule(module);
                            }
                        }
                        

                         

                        Ok, thar solves the half part.

                        Unfortunatly,  there is no method for unregister this module during undeploy.
                        Is it possible to add this method to the Module ?

                         

                        At the moment, the undeploy looks like this :

                         

                        @Override
                        public void undeploy(DeploymentUnit context) {
                            final Module module = context.getAttachment(Attachments.MODULE);
                            URL url = module.getExportedResource("META-INF/services/java.net.URLStreamHandlerFactory");
                            if (url == null) {
                                return;
                            }
                            try {
                                Class clazz = Class.forName("org.jboss.modules.ModularURLStreamHandlerFactory");
                                Field field = clazz.getDeclaredField("modules");
                                field.setAccessible(true);
                                List<Module> modules = (List<Module>) field.get(null);
                                if (modules.remove(module)) {
                                    log.info("unregisterURLStreamHandlerFactoryModule " + module.getIdentifier());
                                }
                            } catch (Exception x) {
                                //x.printStackTrace();
                            }
                        }
                        

                         

                         

                        Ugly

                        • 9. Re: URL-Protocol Handler doesn't work
                          skoure

                          David,

                           

                          Can you please comment a little more on how to correctly register a URLStreamHandler on AS 7.1 via a static module.

                          I have an ear that uses the smb protocol from jcifs and I am having dificulty getting this to work on AS 7.1
                          Whenever my application tries to access a smb URL I get a MalformedURLException unknown protocol: smb

                          In the Manifest of the ear I have added a dependency to jcifs.

                          I have created the following directory structure under modules:
                          modules
                          |- jcifs
                               |- main
                                   |- module.xml
                                   |- jcifs.jar
                                   |- service-loader-resources
                                       |- META-INF
                                           |- services
                                               |- java.net.URLStreamHandler

                          java.net.URLStreamHandler is a text file containing the class name of the Handler (jcifs.smb.Handler).
                          module.xml contains a resource-root for both service-loader-resources as well as jcifs.jar

                          I modified standalone.conf.bat to include:
                          set JAVA_OPTS=%JAVA_OPTS% -Djboss.protocol.handler.modules=jcifs
                          I have also tried:
                          set JAVA_OPTS=%JAVA_OPTS% -Djava.protocol.handler.pkgs=jcifs

                          • 10. Re: URL-Protocol Handler doesn't work
                            dmlloyd

                            I'll field this one.

                             

                            If you have a static module which you want considered as a URL stream handler provider for a standalone AS server instance, you must add your custom module to the org.jboss.as.standalone module import list like this:

                             

                                <dependencies>
                                    <module name="javax.api"/>
                                    <module name="org.jboss.logmanager" services="import"/>
                                    <module name="org.jboss.as.jmx" services="import"/>
                                    <module name="org.jboss.as.server" export="true"/>
                                    <module name="jcifs" services="import"/>
                                </dependencies>
                            
                            

                             

                            This should cause your URL handler to be recognized.

                            • 11. Re: URL-Protocol Handler doesn't work
                              skoure

                              David,

                               

                              Thanks for your quick reply.

                               

                              I added the dependency in org.jboss.as.standalone module import list as you suggested, however, I am still receiving a MalformedURLException unknown protocol: smb within my application. 

                               

                              The good news is that I now see the .index files being created without requiring a dependency to jcifs in the .ear Manifest.

                              Before this change the .index files were only created if the .ear had a dependency on jcifs, and I can see that the list of modules in the ModularURLStreamHandlerFactory is final.

                              Hence I assumed loading the jcifs module as a dependency on the .ear was too late.  I thought that defining -Djboss.protocol.handler.modules=jcifs would have resolved that, but I guess not.

                               

                              I tried adding export="true" on the jcifs dependency, but still the same Exception.

                               

                              I also tried to place the jcifs dependency before the org.jboss.as.server dependency to see if that would help, since it appears that is where the Main and Bootstrap classes reside, but still no luck.

                              Is the order of the dependencies important?

                              Am I missing something?

                              • 12. Re: URL-Protocol Handler doesn't work
                                dmlloyd

                                No, order doesn't matter; the export switch is not necessary.  Are you running in standalone mode or domain mode?

                                • 13. Re: URL-Protocol Handler doesn't work
                                  skoure

                                  I'm running in standalone mode.

                                  • 14. Re: URL-Protocol Handler doesn't work
                                    dmlloyd

                                    Okay I re-read the code and it is not exactly as I remembered it.  Here are the rules:

                                     

                                    • All modules listed in the jboss.protocol.handler.modules system property are loaded, one by one, to search for java.net.URLStreamHandlerFactory service implementations.  Note that the module list is delimited by vertical bar characters ("|"); this was motivated by consistency with the java.protocol.handler.pkgs system property.
                                    • The first such implementation that returns a URLStreamHandler for the given protocol name is used (and cached by the JVM).
                                    • Otherwise null is returned and the search is retried next time.
                                    1 2 Previous Next