Skip to content

Instantly share code, notes, and snippets.

@BruceZu
Last active June 7, 2018 06:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BruceZu/3952e52edecfd3ce4b224b897641ea32 to your computer and use it in GitHub Desktop.
Save BruceZu/3952e52edecfd3ce4b224b897641ea32 to your computer and use it in GitHub Desktop.
Tomcat

Tomcat 8

https://tomcat.apache.org/tomcat-8.5-doc/host-manager-howto.html https://tomcat.apache.org/tomcat-8.5-doc/config/host.html

Automatic Application Deployment

https://tomcat.apache.org/tomcat-5.5-doc/config/host.html#Automatic Application Deployment

Tips

http://www.onjava.com/pub/a/onjava/2003/06/25/tomcat_tips.html

Apache Tomcat wiki

Removing the unpackWARs feature https://wiki.apache.org/tomcat/RemoveUnpackWARs

   // unpackWARs="false" the 
   SevletContext.getRealPath();//  method always returns null

https://docs.oracle.com/javaee/6/api/javax/servlet/ServletContext.html#getRealPath(java.lang.String)

getServletContext().getRealPath("/") 

// returns '\' at the end when I run my project in Tomcat 7 whereas it is not 
// working as such in Tomcat 8. 

// For example, 
// In Tomcat 7 it returns as "D:\Tomcat\webapps\project\" 
// In Tomcat 8 it returns as "D:\Tomcat\webapps\project" 

//At present the project is in production so, I am unable to change the code 
//in every part(where i use getRealPath("/")). Is there a way/setting in 
//tomcat level configuration to make it resolved. 

//Additional information, Tomcat version : 8.0.14 
 

tomcat implementation

https://bz.apache.org/bugzilla/show_bug.cgi?id=57556

 
 // the servlet-2_3-fcs-docs for ServletContext.getRealPath():
 // "This method returns null if the servlet container cannot translate the virtual path to a real path for any reason 
 // (such as when the content is being made available from a .war archive)."
   config.getServletContext().getRealPath("/" + storageLocation);
   getServletContext().getResource("files");
 // Read the javadoc for ServletContext.getResource:

//"Returns a URL to the resource that is mapped to a specified path. The
//path must begin with a "/" and is interpreted as relative to the current
//context root."
ServletContext#getRealPath() 
// may return null in case that the cms.war is running without being unpacked.

// So, I think it's better to use a default storage directory instead in this
// case under the current working directory (e.g, "./repository_storage").
@BruceZu
Copy link
Author

BruceZu commented Mar 29, 2018

Runtime configuration

where to save the configured file

/var/webapp/fpc/runtime-configuration/ 

add its path to the classpath of the appserver.

assume to use Tomcat, shared.loader property of Tomcat/conf/catalina.properties.

$ java -XshowSettings
 ...
 java.io.tmpdir = /tmp
 ...
System.getProperty("catalina.base")
System.getProperty("java.class.path")
System.getProperty("user.dir")

https://docs.oracle.com/javase/tutorial/essential/environment/sysprop.html

how about other OS

If you adhere the *nix filesystem path rules (i.e. you use exclusively forward slashes as in /path/to/files), then it will work on Windows as well without the need to fiddle around with ugly File.separator string-concatenations. It would however only be scanned on the same working disk as from where this command is been invoked. So if Tomcat is for example installed on C: then the /path/to/files would actually point to C:\path\to\files.
        File file = new File("/path/to/files", filename);
        file.toPath() ;

how to get it

1. put it in classpath

  • foo.properties is supposed to be placed in one of the roots which are covered by the default classpath of a webapp, e.g.

    • webapp's /WEB-INF/lib and /WEB-INF/classes,

    • server's /lib,

    • JDK/JRE's /lib.

If the propertiesfile is webapp-specific, best is to place it in /WEB-INF/classes.

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("foo.properties");
// ...
Properties properties = new Properties();
properties.load(input);
  • If you have placed the foo.properties it in a Java package structure like com.example, then you need to load it as below

    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    InputStream input = classLoader.getResourceAsStream("com/example/foo.properties");
    

    Note that this path of a context class loader should not start with a /. Only when you're using a "relative" class loader such as SomeClass.class.getClassLoader(), then you indeed need to start it with a /.

    ClassLoader classLoader = SomeClass.class.getClassLoader();
    InputStream input = classLoader.getResourceAsStream("/com/example/foo.properties");
    

    the visibility of the properties file depends then on the class loader in question. It's only visible to the same class loader as the one which loaded the class. So, if the class is loaded by e.g. server common classloader instead of webapp classloader, and the properties file is inside webapp itself, then it's invisible.

    The context class loader is your safest bet so you can place the properties file "everywhere" in the classpath and/or you intend to be able to override a server-provided one from the webapp on.

    2. put it in webcontent

    load it by ServletContext#getResourceAsStream() with a webcontent-relative path:

    InputStream input = getServletContext().getResourceAsStream("/WEB-INF/foo.properties");
    // ...

http://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/ServletContext.html#getResource(java.lang.String)

@Service
public class PropertiesUtils {
    private ServletContext context;
    private Properties properties;
    @Autowired 
    public PropertiesUtils(ServletContext context) {
        this.context = context;
        this.properties = new Properties();
        try {
            this.properties.load(new FileInputStream(this.context.getRealPath("/WEB-INF/context.properties"))); 
        InputStream input = servletContext.getResourceAsStream("/index.jsp"); 
             // Right! system's file separator
             //Tomcat requires / at the begining 
                 
                 
// when it is unpacked war, it still works.
           
//obtain a list of all available web resource paths, use 
Set<String> resourcePaths = servletContext.getResourcePaths("/");//system's file separator

//obtain an individual resource as URL via 
ServletContext#getResource(). 
//This will return null when the resource does not exist.
URL resource = servletContext.getResource(path);

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
   ...
String absolutePathToIndexJSP = servletContext.getRealPath("/index.jsp");

3. Put it in local disk file system

So that you can load it the usual java.io way with an absolute local disk file system path:

InputStream input = new FileInputStream("/absolute/path/to/foo.properties");
// ...

Note the importance of using an absolute path.

Relative local disk file system paths are an absolute no-go in a Java EE web application. See also the first "See also" link below.

Which to choose?

If you prefer being able to edit properties files from outside the web application without the need to rebuild and redeploy the WAR every time, then put it in the classpath outside the project (if necessary add the directory to the classpath).

If you prefer being able to edit properties files programmatically from inside the web application using Properties#store() method, put it outside the web application. As the Properties#store() requires a Writer, you can't go around using a disk file system path. That path can in turn be passed to the web application as a VM argument or system property. As a precaution, never use getRealPath(). All changes in deploy folder will get lost on a redeploy for the simple reason that the changes are not reflected back in original WAR file.

3 class loader difference: context class loader; server common classloader and webapp classloader???

Get resouce

java.io.File

The java.io.File and consorts acts on the local disk file system.

Relative paths in java.io are dependent on the current working directory.

I.e.

  • the directory from which the JVM is started. This may for example be C:\Tomcat\bin or something entirely different.

  • In a normal Eclipse project, that would be C:\Eclipse\workspace\projectname.

  • but thus not C:\Tomcat\webapps\contextname or whatever you'd expect it to be.

  • You can learn about the current working directory the following way:

    System.out.println(new File(".").getAbsolutePath());

cons: The working directory is in no way programmatically controllable. You should really prefer using absolute paths in the File API instead of relative paths. E.g. C:\full\path\to\file.ext.

cons: You don't want to hardcode or guess the absolute path in Java (web)applications. That's only portability trouble (i.e. it runs in system X, but not in system Y).

put them in classpath

place those kind of resources in the classpath, or to add its full path to the classpath (in an IDE like Eclipse that's the src folder and the "build path" respectively).

// ClassLoader#getResource() 
// ClassLoader#getResourceAsStream()

locate files relative to the "root" of the classpath

  • how to select class loader?

In web applications (or any other application which uses multiple classloaders) it's recommend to use the

for this so you can look "outside" the webapp context as well.

alternative in webapps is the

// ServletContext#getResource()
// ServletContext#getResourceAsStream()

It is able to access files located in the public webfolder of the webapp project, including the /WEB-INF folder.

ServletContext#getResource() and its counterpart ServletContext#getResourceAsStream(). It is able to access files located in the public webfolder of the webapp project, including the /WEB-INF folder. The ServletContext is available in servlets by the inherited getServletContext() method, you can call it as-is.

Different ??

Thread.currentThread().getContextClassLoader().getResource();
Thread.currentThread().getContextClassLoader().getResourceAsStream();
// and
// ServletContext#getResource()
// ServletContext#getResourceAsStream()
// add in webapp and local. what is the domain?  ProtectionDomain
// MyClass.getClass().getProtectionDomain().getCodeSource().getLocation().getPath();

Save or Update at runtime

The public web content folder will all get lost whenever the webapp get redeployed or even when the server get restarted with a cleanup.

location outside the webapp deploy folder as a more permanent storage, so that it will remain intact across multiple deployments/restarts. prepare a fixed local disk file system folder

String uploadsFolder = getItFromConfigurationFileSomehow(); 
// "/var/webapp/uploads" or Catalina base/conf/cutomized/my_config.xml
File file = new File(uploadsFolder, "imagetosave.jpg");
// Check Java 8 new features

https://stackoverflow.com/questions/2161054/where-to-place-and-how-to-read-configuration-resource-files-in-servlet-based-app

@BruceZu
Copy link
Author

BruceZu commented Apr 9, 2018

URL mainURL = Main.class.getResource("Main.class");
if (!"file".equalsIgnoreCase(mainURL.getProtocol()))
   // Note that most class files are assembled into JAR files so this won't work in every case (hence the IllegalStateException). 
  // However, you can locate the JAR that contains the class with this technique, 
  // and you can get the content of the class file by substituting a call to getResourceAsStream() in place of getResource(), and that will work whether the class is on the file system or in a JAR.
File path = new File(mainURL.getPath());
final File f = new File(Main.class.getProtectionDomain().getCodeSource().getLocation().getPath());
// getCodeSource() returns null in my jvm (jetty) 

@BruceZu
Copy link
Author

BruceZu commented Apr 9, 2018

get the current working directory, i.e. directory where your program started.

 new File(".").getAbsolutePath();

@BruceZu
Copy link
Author

BruceZu commented Apr 9, 2018

what the main class is.

Thread.getAllStackTraces(). 
public static Class<?> getMainClass() {
  if (mainClass != null)
    return mainClass;

  Collection<StackTraceElement[]> stacks = Thread.getAllStackTraces().values();
  for (StackTraceElement[] currStack : stacks) {
    if (currStack.length==0)
      continue;
    StackTraceElement lastElem = currStack[currStack.length - 1];
    if (lastElem.getMethodName().equals("main")) {
      try {
        String mainClassName = lastElem.getClassName();
        mainClass = Class.forName(mainClassName);
        return mainClass;
      } catch (ClassNotFoundException e) {
        // bad class name in line containing main?! 
        // shouldn't happen
        e.printStackTrace();
      }
    }
  }
  return null;
}

// From this you can search all the stack traces for the main Thread to determine what the main class is.
// This will work even if your class is not running in the main thread.

jps -l 

@BruceZu
Copy link
Author

BruceZu commented Apr 9, 2018

got a file in my war/WEB-INF folder of my app engine project how to form the path to the resource though:

/war/WEB-INF/test/foo.txt

As long as the WAR file is expanded (a set of files instead of one .war file), you can use this API:

ServletContext context = getContext();
String fullPath = context.getRealPath("/WEB-INF/test/foo.txt");

http://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/ServletContext.html#getRealPath(java.lang.String)

That will get you the full system path to the resource you are looking for.

However, that won't work if the Servlet Container never expands the WAR file (like Tomcat).
What will work is using the ServletContext's getResource() methods.

ServletContext context = getContext();
URL resourceUrl = context.getResource("/WEB-INF/test/foo.txt");

or alternatively if you just want the input stream:

InputStream resourceContent = context.getResourceAsStream("/WEB-INF/test/foo.txt");

http://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/ServletContext.html#getResource(java.lang.String)

The latter approach will work no matter what Servlet Container you use and where the application is installed.
The former approach will only work if the WAR file is unzipped before deployment.

@BruceZu
Copy link
Author

BruceZu commented Apr 9, 2018

the question is
They will all get lost whenever the webapp get redeployed or even when the server get restarted with a cleanup. The simple reason is that the uploaded images are not contained in the to-be-deployed WAR file at all.

you
cannot rely on your web application being able to write in whatever directory
(if any) is its "current" directory (even supposing that this exists at all). This "current
directory" is whatever directory the JVM happens to be running in, which you
have no way to know in advance.
(Some day, your application may even be running inside a JVM and a Tomcat that
are entirely in some non-writeable kind of memory.)

have that application write something somewhere, and to
do this in a portable way, is to choose a place outside of the Tomcat directories, some
place that is guaranteed to be

  • writeable (by the JVM which runs Tomcat and your webapp) because you
    created it that way (and you include this in your application's installation
    instructions).
  • And to make this portable, your application has to be able to find out
    that location (on each system where it may be used), via some configurable
    parameter that it can read.

And finally, there is another reason for not writing inside your web
application's
directory, even if this was possible : security.
If you allow Tomcat to write to your application directory, then possibly someone can take advantage of this via some
misconfiguration, and overwrite your code with malicious code that would do something else which you do not want to happen at all.

not be using /WEB-INF/classes/ to store static resources. Use /WEB-INF/resources/

@BruceZu
Copy link
Author

BruceZu commented Apr 9, 2018

Finding the Directory Where Your Java .class File is Loaded From
I needed to find the directory that was used to load a specific Java .class file (the location in the file system of given .class file)

URL url = getClass().getResource(".");
// This works well in a console application but in a servlet container (e.g. in Tomcat or in GWT shell) it runs differently.
URL classesRootDir = getClass().getProtectionDomain().getCodeSource().getLocation();
// returns the base directory used when loading your .class files. It does not contain the package. It contains the classpath directory only
//  in a console application the above returns someting like this:
//   file:/C:/Documents%20and%20Settings/Administrator/workspace/TestPrj/bin/

// In a Web application it returns someting like this:
// file:/C:/Tomcat/webapps/MyApp/WEB-INF/classes/
// It also works well for GWT applications running in hosted mode in GWT shell and in a compiled mode in JBoss. This was the real solution.
// But, as soon as your class is deployed through a jar, war or EAR, the above does not work. getProtectionDomain().getCodeSource().getLocation().getFile() would then return the path to the embedding package as running on the runtime.
      URI uri = MetaDataGenerator.class.getProtectionDomain().getCodeSource().getLocation().toURI();
      File file = new File(uri);
      if (file.isDirectory()) {
        //  unpacked war
        PREFIX = file.getAbsolutePath();
      } else {
        PREFIX = file.getParentFile().getAbsolutePath();
      }

@BruceZu
Copy link
Author

BruceZu commented Apr 9, 2018

spring get environment variable

 

@Autowired
private Environment environment;
// in your @Component, @Bean, etc., and then access the properties through the Environment class:

environment.getProperty("myProp");

@BruceZu
Copy link
Author

BruceZu commented Apr 9, 2018

How to find absolute path of class deployed in Tomcat?

  getClass().getClassLoader().getResource(".").getPath();
  Thread.currentThread().getContextClassLoader().getResource(".").getPath();
//  /D:/ProgramFiles/Tomcat-7.0.26/lib/ 

  getClass().getClassLoader().getResource("/").getPath();
  Thread.currentThread().getContextClassLoader().getResource("/").getPath();
//  /D:/ProgramFiles/Tomcat-7.0.26/webapps/catalog-web/WEB-INF/classes/

That's because getResource(".") returns the "current" folder where the calling class is. In your case the calling class is the classloader of your webapp which is declared in the tomcat lib, which should be located at tomcat/lib folder.

The getResource("/") returns the root folder of your classpath, which is pointing by the webapp classloader to WEB-INF/classes.
https://docs.oracle.com/javase/7/docs/api/java/lang/ClassLoader.html#getResource(java.lang.String)

// The jar is included in war file.  read resource which lies in a jar which again found in WEB-INF/lib of root application. ROOT.war
// my.jar
//   com
//     test
//       myservlet.class
//   META-INF
//     test.property
// Put it in root of the JAR and get it by context classloader instead of servletcontext.

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("test.properties");
 
// If need a separate JAR folder which is to be part of the classpath, use /META-INF instead.

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("META-INF/test.properties");

@BruceZu
Copy link
Author

BruceZu commented Apr 9, 2018

C:\Program Files\Apache Software Foundation\Tomcat 7.0\webapps\ProcurementWS1\WEB-INF\classes\procwsconfig.properties
ProcurmentWS1 is the name of the WAR file

this is how am trying to access it from my code:

            Properties properties = new Properties();
            InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("/procwsconfig.properties");
            properties.load(is);

@BruceZu
Copy link
Author

BruceZu commented Apr 9, 2018

    ResourceBundle bundle1 =   ResourceBundle.getBundle("com.witness.web.license.l10n.VersionsFileName");
    String fileName = bundle1.getString("11.1");  
// com.witness.web.license.l10n being your package

@BruceZu
Copy link
Author

BruceZu commented Apr 9, 2018

build directory
The build directory differs based on the type of the application.
In stand-alone applications, the default build directory is bin which resides under the root path of the project,
however, for web applications, the default build directory is WEB-INF/classes.

check and customize the build directory of your project through:
Right Click project -> properties -> Java Build Path -> Source tab -> Default output folder

@BruceZu
Copy link
Author

BruceZu commented Apr 9, 2018

 package com.programmer.gate;
 
import java.io.File;
import java.net.URL;
 
/**
 * This class reads a resource file from classpath.
 * 
 * @author Hussein
 *
 */
public class ClasspathFileReader {
 
    private static final String CONFIG_FILE = "/example.xml";
    
    public File readFileFromClasspath()
    {
        URL fileUrl = getClass().getResource(CONFIG_FILE);
        return new File(fileUrl.getFile());
    }
}

In the above example we use getClass().getResource() , this method tries to read the resource file from the root path of the build folder (i.e. /bin, /build, /WEB-INF/classes) in case the file name starts with forward slash “/”, otherwise it tries to read the file from the same package of the class itself (i.e. com.programmer.gate).

P.S: When defining the file name in the java class, make sure to take the full path of the generated file under build directory including all subfolders, so if example.xml is generated under /bin/xml/example.xml then the file name should be defined as /xml/example.xml.

@BruceZu
Copy link
Author

BruceZu commented Apr 9, 2018

@BruceZu
Copy link
Author

BruceZu commented Apr 9, 2018

@BruceZu
Copy link
Author

BruceZu commented Apr 9, 2018

Need configure the location to save the sso configuration
Development and producetion environment
Window and Ubuntu and Mac

        Properties  configProp = new Properties();
        configProp.load( CommonUtils.class.getClassLoader().getResourceAsStream("application.properties"));
@ConfigurationProperties(prefix="my.properties.prefix")
public class MyProperties {
  // value from my.properties.prefix.myProperty will be bound to this variable
  String myProperty;

  // and this will even throw a startup exception if the property is not found
  @javax.validation.constraints.NotNull
  String myRequiredProperty;

  //getters
}

@Component
public class MyOtherBean {
  @Autowired
  MyProperties myProperties;
}
// Note: Just remember to restart eclipse after setting a new environment variable

https://docs.spring.io/spring-framework/docs/4.3.10.RELEASE/spring-framework-reference/htmlsingle/#beans-environment
https://docs.spring.io/spring-framework/docs/4.3.10.RELEASE/spring-framework-reference/htmlsingle/#beans-property-source-abstraction
https://www.logicbig.com/tutorials/spring-framework/spring-core/spring-env-properties.html

@BruceZu
Copy link
Author

BruceZu commented Apr 10, 2018

      String systempath = System.getProperty("java.class.path");
     String[] classpathEntries = systempath.split(File.pathSeparator);
  // /usr/lib/jvm/zulu8.23.0.3-jdk8.0.144-linux_x64/jre/lib/resources.jar:
  // /usr/lib/jvm/zulu8.23.0.3-jdk8.0.144-linux_x64/jre/lib/rt.jar:
  // /usr/lib/jvm/zulu8.23.0.3-jdk8.0.144-linux_x64/jre/lib/jsse.jar:
  // /usr/lib/jvm/zulu8.23.0.3-jdk8.0.144-linux_x64/jre/lib/jce.jar:
  // /usr/lib/jvm/zulu8.23.0.3-jdk8.0.144-linux_x64/jre/lib/charsets.jar:
  // /home/bzu/tool/apache-tomcat-9.0.0.M21/bin/bootstrap.jar:
  // /home/bzu/tool/apache-tomcat-9.0.0.M21/bin/tomcat-juli.jar:
  // /usr/lib/jvm/zulu8.23.0.3-jdk8.0.144-linux_x64/lib/tools.jar:
  // /home/bzu/eclipse-workspace-fogo-wrong-decision/.metadata/.plugins/com.zeroturnaround.xrebel.plugin/xrebel.jar
   String checktheab = new File(".").getAbsolutePath();
  // /home/bzu/project/new/FortiPortal/fortipmc/. (standlone )
  // /home/bzu/. (local eclipse + tomcat)

The java.io.File acts on the local disk file system. relative paths in java.io are dependent on the current working directory. "user.dir"

in the classpath use ClassLoader#getResource() or ClassLoader#getResourceAsStream() instead. It is able to locate files relative to the "root" of the classpath, In webapplications (or any other application which uses multiple classloaders) it's recommend to use the ClassLoader as returned by Thread.currentThread().getContextClassLoader() for this.

Another alternative in webapps is the ServletContext#getResource() and its counterpart ServletContext#getResourceAsStream(). It is able to access files located in the public web folder of the webapp project, including the /WEB-INF folder.

  URL url = this.getClass().getResource(File.separator);

// also need classloader
// local eclipse+tomcat:
// file:/home/bzu/eclipse-workspace-fogo-wrong-decision/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/fpc/WEB-INF/classes/
// a safer way is to use class name itself for this solution, for example,
// MyClass.getResourceAsStream(), as often this.getClass() won't work in subclassing or autoproxying scenarios.

CATALINA_BASE=/var/tomcat
export CATALINA_BASE
sh-3.1# grep env  /usr/local/tomcat/bin/catalina.sh
if [ -r "$CATALINA_BASE/bin/setenv.sh" ]; then
  . "$CATALINA_BASE/bin/setenv.sh"
elif [ -r "$CATALINA_HOME/bin/setenv.sh" ]; then
  . "$CATALINA_HOME/bin/setenv.sh"
# Get standard Java environment variables
sh-3.1# find / -type f -name setenv.sh             
/usr/local/tomcat/bin/setenv.sh
sh-3.1# grep database.properties /usr/local/tomcat/bin/setenv.sh
TOMCAT_DB_PROPERTIES=/usr/local/tomcat/util/fpc/database.properties
TOMCAT_DB_PROPERTIES_OUT=/usr/local/tomcat/util/fpc/database.propertiesout
sh-3.1# find / -type f -name database.properties                
/var/tomcat/util/fpc/database.properties
 @Autowired ServletContext servletContext;
  @Autowired Environment env;

  private void test() {
    try {
     url = this.getClass().getResource("/spring/metadata/idp.xml");                
 //file:/home/bzu/eclipse-workspace-fogo-wrong-decision/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/fpc/WEB-INF/classes/spring/metadata/idp.xml
      url = this.getClass().getResource("spring/metadata/idp.xml"); // null
      idp = this.getClass().getResourceAsStream("/spring/metadata/idp.xml"); // okay
      idp = this.getClass().getResourceAsStream("spring/metadata/idp.xml"); // null
    // 从此类所在的包下取资源,以’/'开头则是从ClassPath根下获取??
      url = this.getClass().getClassLoader().getResource("/spring/metadata/idp.xml");
//file:/home/bzu/eclipse-workspace-fogo-wrong-decision/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/fpc/WEB-INF/classes/spring/metadata/idp.xml
      url = this.getClass().getClassLoader().getResource("spring/metadata/idp.xml");
// file:/home/bzu/eclipse-workspace-fogo-wrong-decision/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/fpc/WEB-INF/classes/spring/metadata/idp.xml

      String absoluteDiskPath = servletContext.getRealPath(File.separator);
      // home/bzu/eclipse-workspace-fogo-wrong-decision/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/fpc/
      URI uri = servletContext.getResource("WEB-INF/classes/spring/metadata/idp.xml").toURI();
      // file:/home/bzu/eclipse-workspace-fogo-wrong-decision/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/fpc/WEB-INF/classes/spring/metadata/idp.xml
      InputStream idp =
          servletContext.getResourceAsStream("WEB-INF/classes/spring/metadata/idp.xml");
      env.getProperty("user.dir");
      //  /home/bzu
     URL url = Thread.currentThread().getContextClassLoader().getResource("/spring/metadata/idp.xml");
      // file:/home/bzu/eclipse-workspace-fogo-wrong-decision/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/fpc/WEB-INF/classes/spring/metadata/idp.xml

    } catch (Exception e) {
      e.printStackTrace();
    }
    log.error("");
  }

@BruceZu
Copy link
Author

BruceZu commented Apr 10, 2018

4799 root 2564 S {catalina.sh} /bin/sh /usr/local/tomcat/bin/catalina.sh start
// VM

@BruceZu
Copy link
Author

BruceZu commented Apr 11, 2018

ResourceResolver myResolver = new ResourceResolver() {
     public InputStream getResourceAsStream(String resourceName) {
         ClassLoader loader = Thread.currentThread().getContextClassLoader();
         if (loader == null) { // there may not be a context class loader
             loader = MyClazz.class.getClassLoader();
         }
         return loader.getResourceAsStream(resourceName);
     }
 };

@BruceZu
Copy link
Author

BruceZu commented Apr 11, 2018

Code:
myclass:

this.getClass().getClassLoader().getResourceAsStream("config.xml")

to get a configuration out of the classpath.

It worked really well, but now I found something weird:

I load the class with the above function in a jsp,
the class residing in a jar in the tomcat/common/lib dir and
the config.xml in the webroot/WEB-INF/classes
Suddenly the config.xml cannt be loaded any more... at least not by myclass.

Thread.currentThread().getContextClassLoader().getResourceAsStream("config.xml")

Tomcat sets the context class loader to the class loader of the webapp (which can of course load stuff from WEB_INF/classes).
The original line this.getClass().getClassLoader().getResourceAsStream("config.xml") does not work when the class that contains the line lives in common/lib or shared/lib, because its class loader is then the 'common' or 'shared' class loader, which cannot see into individual webapps.
Class Loader HOW-TO http://tomcat.apache.org/tomcat-5.5-doc/class-loader-howto.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment