之前在碰到一个bug,email service的smtp服务由于没有设置timeout,当和服务器连接失败时,会永远hang在那里。然后就在代码里加上了下面的红色字体(在smtp服务首次被调用时,下面的代码会被调用到)。
<span style="color:#ff0000;">private static final int MAIL_SMTP_TIMEOUT = 300000;</span>
Properties props = System.getProperties();
props.put( "mail.smtp.host", smtpHost);
<span style="color:#ff0000;">props.put("mail.smtp.timeout", MAIL_SMTP_TIMEOUT);</span>
m_session = Session. getDefaultInstance(props, null);
但是却发现,这样修改后jsp会随机的出现无法compile的情况,报错如下:
org.apache.jasper.JasperException: Unable to compile class for JSP
org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:520)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:295)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:292)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:236)
javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
root cause: java.lang.NullPointerException
java.util.Hashtable.put(Hashtable.java:396)
org.apache.tools.ant.PropertyHelper.setProperty(PropertyHelper.java:335)
org.apache.tools.ant.Project.setPropertyInternal(Project.java:460)
org.apache.tools.ant.Project.setSystemProperties(Project.java:800)
org.apache.tools.ant.Project.init(Project.java:261)
org.apache.jasper.compiler.Compiler.getProject(Compiler.java:116)
org.apache.jasper.compiler.Compiler.generateClass(Compiler.java:320)
org.apache.jasper.compiler.Compiler.compile(Compiler.java:472)
org.apache.jasper.compiler.Compiler.compile(Compiler.java:439)
org.apache.jasper.compiler.Compiler.compile(Compiler.java:451)
org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:511)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:295)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:292)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:236)
javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
具体就是由于ant在set properties的时候出现了null pointer, 导致jsp的编译失败。
起初并没有怀疑是代码的问题(真莫有一点怀疑啊...),因为这次修改只是加了这个属性以及升级了mail的jar包,而没有可能引入任何null值。
于是有了两种猜测,一种是新的jar包造成的,一种是有人动了server的环境。
对环境进行了仔细的检查,甚至对prod环境进行了jdb调试,折腾一天无果。
后来经过不断的重启service,发现一个规律:
如果在服务起来后,如果首先访问jsp页面,那jsp就可以编译出来;如果在反问jsp前先访问了某些其他服务,则会nullpointer。然后自然就想到,这个某些其他服务应该就是这个smtp服务。
由于email service是很多年前写的,所以用的tomcat版本比较老(5.0的), ant jar包的版本是1.6.4
于是去看了源码,发现如下:
1.6.4
1.7.1
原来在ant的1.7.1之前,一直没有做nullpointer的检测,就直接赋值到一个hashtable里面,之后的版本已经改了这个bug。
但是Properties本身就是个hashtable,放进去的指不可能有null值,为什么拿出来的时候怎么可能有null值,我第一反应是,添加进去的时候是好的,后来由于调用了某些服务,使其中的某个或某些值变为null。后来看了下Properties的源码,也是醉了.............
Properties
class is considered to be one of the "mistakes" of java.