4 Replies Latest reply on Aug 7, 2002 8:21 PM by far

    Jboss & xml resources

    far Newbie

      Jboss doesn't seem be able to get access or let Tomcat/Jetty get access to XML files in WEB-INF. I' ve tried to deploy the same web application on Jboss-tomcat and Jboss-Jetty. This is what I get as an error:

      15:03:42,857 ERROR [STDERR] 4 URLMappingsXmlDAO error: java.net.MalformedURLException:
      no protocol: java.io.ByteArrayInputStream@143753
      15:03:42,857 ERROR [STDERR] java.net.MalformedURLException: no protocol: java.io.ByteArr
      ayInputStream@143753

      15:03:42,867 ERROR [STDERR] at java.net.URL.(URL.java:579)
      15:03:42,867 ERROR [STDERR] at java.net.URL.(URL.java:476)
      15:03:42,867 ERROR [STDERR] at java.net.URL.(URL.java:425)
      15:03:42,867 ERROR [STDERR] at com.sun.j2ee.blueprints.waf.controller.web.URLMapping
      sXmlDAO.loadDocument(Unknown Source)

      I 've tried to configure this in Jboss-service.xml or Tomcat-service.xml
      Is this due to a loader problem or the UrldeployerScanner Mbean?.
      I haven't got a clue
      Any suggestion or clue please!

      Faisal

        • 1. Re: Jboss & xml resources
          Julian Gosnell Expert

          I could help with the Jetty side of things if I could understand what you were trying to do - browse files in WEB-INF ? - You are not allowed to.

          SRV.9.5

          "A special directory exists within the application hierarchy named WEB-INF . This directory contains all things related to the application that aren t in the document root of the application. The WEB-INF node is not part of the public document tree of the application. No file contained in the WEB-INF directory may be served directly to a client by the container. However, the contents of the WEB- INF directory are visible to servlet code using the getResource and getResourceAsStream method calls on the ServletContext, and may be exposed using the RequestDispatcher calls. Hence, if the Application Developer needs access, from servlet code, to application specific configuration information that he does not wish to be exposed directly to the web client, he may place it under this directory. Since requests are matched to resource mappings case-sensitively, client requests for /WEB-INF/foo , /WEb-iNf/foo , for example, should not result in contents of the web application located under /WEB-INF being returned, nor any form of directory listing thereof."


          Jules

          • 2. Re: Jboss & xml resources
            far Newbie

            Thanks for the reply
            Here is what I am trying to do exactly:
            I got a servlet - a template servlet that needs to get access to two xml files: screendefintions.xml and requestmappings.xml to load the screens when initiated. When I first deploy the ear file I get the error that those two file don't event exist in WEB-INF dir and that
            they are an "unknown source".Tomcat an Jetty are too mature engines to get me this error. This a the important part of the TemplateServlet where I got the error:

            private void initScreens(ServletContext context, String language) {
            URL screenDefinitionURL = null;
            try {
            screenDefinitionURL = context.getResource("/WEB-INF/screendefinitions_" + language + ".xml");
            } catch (Exception ex) {
            ex.printStackTrace();
            }
            if (screenDefinitionURL != null) {
            Screens screenDefinitions = ScreenDefinitionDAO.loadScreenDefinitions(screenDefinitionURL);
            if (screenDefinitions != null) {
            allScreens.put(language, screenDefinitions);
            } else {
            System.err.println("bla bla bla");
            any idea !
            thanks for any suggestion
            Brummy Faisal
            Birmingham UK

            • 3. Re: Jboss & xml resources
              Julian Gosnell Expert


              1. you are doing a getResource() on on "screendefinitions_.xml which will NEVER match "screendefinitions.xml".

              2. even if it did match, I would be suspicious of the URL - since the servlet spec makes no guarantee that your app will be unpacked. You should be using getResourceAsStream() and passing the resultant InputStream on to your template parser.

              Of course, I could be talking nonsense... :-)


              Jules

              • 4. Jboss & loading  xml resources form war archive
                far Newbie

                Finally I managed to solve this mystery
                Instead of using context.getResource("/WEB-INF/")i used
                Thread.currentThread().getContextClassLoader().getResource("screendefinitions_"+language+".xml");
                and
                Instead of

                String requestMappingsURL = context.getResource("/WEB-INF/mappings.xml").toString();

                U used requestMappingsURL =Thread.currentThread().getContextClassLoader().getResource("mappings.xml").toString();

                Also I think it is important for Java/Jboss users to read this:


                ---------------------------------------------------

                Accessing Resources in a Location-Independent Manner
                Code written for the Java 1.0 platform uses two mechanisms to access resources.

                Applets use Applet.getCodeBase() to get a URL to the base of the code for the applet. This base can be extended with a "relative path" to point to the desired resource, which can then be loaded (for example using Applet.getAudioClip(url)).
                Applications use "well known locations" (such as System.getProperty("user.home") or System.getProperty("java.home")). They add "/lib/" to the location and then open that file.
                The Java 1.0 platform lacks a mechanism to locate resources that are independent of the code. That is, there is no way locate resources for an applet loaded from the net using multiple http connects, or for an applet loaded using JAR files, or for a Bean loaded or a Bean installed in the CLASSPATH, or for a "library" installed in the CLASSPATH, and so on. The APIs described here provide such a mechanism.

                The I18N APIs use this API as a primitive operation to locate ResourceBundles. See the latest I18N documentation for details.

                Resources, names, and contexts
                A resource is identified by a String. This String, while possibly empty, is a /-separated sequence of substrings, each a valid Java programming lanaugage identifier, followed by a name of the form "" or ".". Both "shortName" and "extension" are composed of valid Java Letters and Numbers (section 3.8 in JLS). If the optional sequence exists, it is separated from the "shortName" by a /.

                The name of a resource is independent of the Java implementation; in particular, the / is always used as a separator. However, the Java implementation controls the details of how the contents of the resource are mapped into a file, database, or other object containing the actual resource.

                The interpretation of a resource name is relative to a ClassLoader instance. Methods implemented by the ClassLoader do this interpretation.

                System Resources
                A system resource is similar to a system class (section 20.14.5 of the JLS). A system resource is a resource that is either built-in to the system, or it is kept by the host implementation in, for example, a local file system. System resources are accessed through special methods (getSystemResource and getSystemResourceAsStream) that consult the base host implementation.

                For example, in a particular implementation, locating a system resource may involve searching the entries in the CLASSPATH. Each directory, zip file, or jar file entry in the CLASSPATH is searched for the resource file, and, if found, either an InputStream, or its name, is returned. If not found, null is returned. Note that a resource may be found in a different entry in the CLASSPATH than where the class file was loaded.

                Non-System Resources
                The implementation of getResource on a given ClassLoader will depend on the details of the ClassLoader. For example AppletClassLoader will:
                First try to locate the resource as a system resource; then, if not found,
                Search through the resources in ARCHIVES (JAR files) already loaded in this CODEBASE; then, if not found,
                Use CODEBASE and attempt to locate the resource (which may involve contacting a remote site).
                All ClassLoaders will search for a resource first as a system resource, in a manner analogous to searcing for class files. This search rule permits overwriting locally any resource. Clients should choose a resource name that will be unique (using the company or package name as a prefix, for instance).

                Resource Names
                A common convention for the name of a resource used by a class is to use the fully qualified name of the package of the class, convert all "." to "/", and add a resource name of the form ".". To support this, and to simplify handling the details of system classes (for which getClassLoader returns null), the class Class provides two convenience methods that call the appropriate methods in ClassLoader.

                The resource name given to a Class method may have an initial starting "/" that identifies it as an "absolute" name. Resource names that do not start with a "/" are "relative".

                Absolute names are stripped of their starting "/" and are passed, without any further modification, to the appropriate ClassLoader method to locate the resource. Relative names are modified according to the convention described previously and then are passed to a ClassLoader method.

                Manipulating Resources
                The method getResource() returns a URL for the resource. The URL (and its representation) is implementation and JVM*-instance specific (the URL obtained in one runtime instance may not work in another) and may vary depending on the implementation details Its protocol is (usually) specific to the ClassLoader loading the resource. If the resource does not exist, a null will be returned; if the resource is not visible due to security considerations, a null will also be returned.

                If the client code wants to read the contents of the resource as an InputStream, it can apply the openStream() method on the url. This is common enough to justify adding getResourceAsStream() to Class and ClassLoader. getResourceAsStream() is semantically identical to getResource().openStream(), except that IO exceptions are caught and returned as a null InputStream.

                The client code code can also request the contents of the resource as an object by applying the getContent() method on the url. This is useful when the resource contains the data for an image, for instance. Note that in this case, the result is an awt.image.ImageProducer object, not an Image object.

                API Additions to Class
                Specifically, the class Class methods are of the following form:


                class Class {

                /**
                * Find a resource with a given name. Will return null if no
                * resource with this name is found. The rules for searching a
                * resources associated with a given class are implemented by the
                * ClassLoader of the class.
                *
                * The Class methods delegate to ClassLoader methods, after applying
                * a naming convention: if the resource name starts with "/", it is used
                * as is. Otherwise, the name of the package is prepended, after
                * converting "." to "/".
                *
                * @see java.lang.ClassLoader
                */
                public InputStream getResourceAsStream(String name) {
                name = resolveName(name);
                ClassLoader cl = getClassLoader();
                if (cl==null) {
                // A system class.
                return ClassLoader.getSystemResourceAsStream(name);
                }
                return cl.getResourceAsStream(name);
                }

                public java.net.URL getResource(String name) {
                name = resolveName(name);
                ClassLoader cl = getClassLoader();
                if (cl==null) {
                // A system class.
                return ClassLoader.getSystemResource(name);
                }
                return cl.getResource(name);
                }

                /**
                * Add a package name prefix if the name is not absolute
                * Remove leading "/" if name is absolute
                */
                private String resolveName(String name) {
                if (name == null) {
                return name;
                }
                if (!name.startsWith("/")) {
                Class c = this;
                while (c.isArray()) {
                c = c.getComponentType();
                }
                String baseName = c.getName();
                int index = baseName.lastIndexOf('.');
                if (index != -1) {
                name = baseName.substring(0, index).replace('.', '/')
                +"/"+name;
                }
                } else {
                name = name.substring(1);
                }
                return name;
                }




                Note that it is possible, albeit somewhat uncommon, to have two classes in two diffent packages sharing the same resource.

                API Additions to ClassLoader
                We provide two sets of methods to access a resource. One set returns an InputStream on the resource. The other set returns a URL. The methods that return an InputStream are somewhat easier to use and will satisfy many needs, while the methods that return URLs provide access to more complex information, such as an Image and an AudioClip.

                Resources are managed through ClassLoaders in a manner analogous to classes. A ClassLoader controls how to map the name of a resource to its content. ClassLoader also provides methods for accessing system resources, analogous to the system classes. Class Class provides some convenience methods that delegate functionality to the appropriate ClassLoader methods.

                Many Java programs will access these methods indirectly through the I18N APIs. Others will access it through methods in class Class. A few will directly invoke the ClassLoader methods.

                The methods in ClassLoader use the given String as the name of the resource without applying any absolute/relative transformation (cf. the methods in Class). The name should not have a leading "/".


                class ClassLoader {

                /**
                * A resource is some data (images, audio, text, etc) that wants to be
                * accessed by some class code in a way that is independent of the
                * location of the code. Resources are found with cooperation of the
                * class loaders, since they are the only ones who know where the class
                * actually came from.
                *
                * System resources are those that are handled by the host implemenation
                * directly. For example, they may be located in the CLASSPATH.
                *
                * The name of a resource is a "/"-separated sequence of identifiers.
                * The class Class provides convenience methods for accessing resources;
                * the methods implement a convention where the package name is prefixed
                * to the short name of the resource.
                *
                * Resources can be accessed as an InputStream, or as a URL.
                *
                * @see Class
                */

                /**
                * Get an InputStream on a given resource.. Will return null if no
                * resource with this name is found.
                *
                * The resource name may be any system resource (e.g. follows CLASSPATH order)
                * @param name the name of the resource, to be used as is.
                * @return an InputStream on the resource, or null if not found.
                */

                public static final InputStream getSystemResourceAsStream(String name) {
                ... this is equivalent to getSystemResource() call plus a openStream()
                }

                /**
                * Find a resource with a given name. The return is a URL to the resource
                * Doing a getContent() on the URL may return an ImageProducer, an AudioClip, or
                * an InputStream.
                *
                * The resource name may be any system resource (e.g. follows CLASSPATH order)
                * @param name the name of the resource, to be used as is.
                * @return the URL on the resource, or null if not found.
                */
                public static final java.net.URL getSystemResource(String name) {
                ...
                }

                /**
                */

                /**
                * Get an InputStream on a given resource. Will return null if no
                * resource with this name is found.
                *
                * The class loader can choose what to do to locate the resource.
                * @param name the name of the resource, to be used as is.
                * @return an InputStream on the resource, or null if not found.
                */
                public InputStream getResourceAsStream(String name) {
                return null;
                }

                /**
                * Find a resource with a given name. The return is a URL to the resource.
                * Doing a getContent() on the URL may return an ImageProducer, an AudioClip,
                * or an InputStream.
                *
                * The class loader can choose what to do to locate the resource.
                * @param name the name of the resource, to be used as is.
                * @return an InputStream on the resource, or null if not found.
                */
                public java.net.URL getResource(String name) {
                return null;
                }

                }


                Client code
                Below are two examples of client code. The first example uses "absolute resource" names and traditional mechanisms to get a class Class object:


                package pkg;

                import java.io.IOException;
                import java.io.InputStream;
                import java.io.PrintStream;

                class Test {

                private static final String absName = "/pkg/mumble.baf";

                public static void test1() {
                Class c=null;
                try {
                c = Class.forName("pkg.Test");
                } catch (Exception ex) {
                // This should not happen.
                }
                InputStream s = c.getResourceAsStream(absName);
                // do something with it.
                }

                public void test2() {
                InputStream s = this.getClass().getResourceAsStream(absName);
                // do something with it.
                }



                The second example uses "relative resource" names and the new mechanism, available from the compiler through the -experimental flag, to get a class Class object:


                package pkg;

                import java.io.IOException;
                import java.io.InputStream;
                import java.io.PrintStream;

                class Test {

                private static final String relName = "mumble.baf";

                public static void test1() {
                InputStream s = Test.class.getResourceAsStream(relName);
                // do something with it.
                }

                public void test2() {
                InputStream s = Test.class.getResourceAsStream(relName);
                // do something with it.
                }



                Security Details
                Since getResource() provides access to information, it must have well defined and well founded security rules that at the same time support the intended use of this mechanism. Below we describe the exact details, as specified and implemented in releases starting at version 1.1.5 of the Java Development Kit. The semantics are described only for ClassLoader.getResource and ClassLoader.getSystemResource() and extend to the AsStream methods as defined in the previous section.
                If security considerations do not allow a resource to be visible in some security context, the getResource() method will fail (will return null) as if the resource was not present at all, this addresses existence attacks.

                All classloaders will not provide access to the contents of a .class file. This is for both security and performance issues. Whether it is possible to obtain a URL into a .class file depends on the specifics, as shown below.

                There are no specified security issues or restrictions regarding resources that are found by a non-system class loader. AppletClassLoader provides access to information that is loaded from some source location, either individually, or in a group through a JAR file; thus AppletClassLoader should apply the same checkConnect() rules when dealing with URLs through getResource().

                The system Class Loader provides access to information in the CLASSPATH. A CLASSPATH may have directories and/or JAR files. Since a JAR file is created intentionally, we ascribe a different significance to it than in a directory where things may end up in a more casual manner. In particular, we are more strict on getting information out of a directory than out from a JAR file.

                If the resource is in a Directory:

                getResource() invocations will use File.exists() to determine whether to make the corresponding file visible to the user. Recall that File.exists() uses the checkRead() method in the security manager.
                the same applies to getResourceAsStream().
                If the resource is in a JAR file:

                getResource() invocations will succeed for all files, regardless of whether the invocation is done from within a System or a non-System class.
                getResourceAsStream() invocations will succeed for non .class resources, and so will for getContent() on corresponding URLs.
                Related Topics & Known Bugs
                The getResource interface does not provide specific support for locating localized resources. Localized resources are supported by the internationalization facilities.

                *As used on this web site, the terms "Java Virtual Machine" or "JVM" mean a virtual machine for the Java platform.

                -----------------------------------------------------
                thank u Jules for your help
                Faisal