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 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