Enterprise Perl

Sébastien Aperghis-Tramoni

Perl recurrent problem

  • Perl is not considered as an enterprise language

  • Reason: no big company support

Solution

  • Look at and imitate enterprise languages

  • Especially, Java

  • More precisely, Java stack traces

    • Untreated exceptions generate complete stack traces which allow a precise diagnostic of the problem

Example

  • Stack trace of an exception from BEA WebLogic

     java.lang.ThreadDeath
            at java.lang.Thread.stop(Thread.java:578)
            at weblogic.t3.srvr.T3Srvr.die(T3Srvr.java:2129)
            at weblogic.t3.srvr.T3Srvr.waitForDeath(T3Srvr.java:1983)
            at java.lang.reflect.Method.invoke(Native Method)
            at weblogic.Server.startServerDynamically(Server.java:148)
            at weblogic.Server.main(Server.java:97)
            at weblogic.Server.main(Server.java:58)
  • Trace d'une exception au sein du logiciel iFS Config d'Oracle

     java.lang.ClassCastException
            at javax.swing.plaf.basic.BasicTextUI.getInputMap(BasicTextUI.java:379)
            at javax.swing.plaf.basic.BasicTextUI.installKeyboardActions(BasicTextUI.java:360)
            at javax.swing.plaf.basic.BasicTextUI.installUI(BasicTextUI.java:697)
            at oracle.bali.ewt.olaf.OracleTextAreaUI.installUI(Unknown Source)
            at javax.swing.JComponent.setUI(JComponent.java:449)
            at javax.swing.text.JTextComponent.setUI(JTextComponent.java:287)
            at javax.swing.text.JTextComponent.updateUI(JTextComponent.java:297)
            at javax.swing.text.JTextComponent.<init>(JTextComponent.java:271)
            at javax.swing.JTextArea.<init>(JTextArea.java:186)
            at javax.swing.JTextArea.<init>(JTextArea.java:122)
            at oracle.ifs.installer.IfsConfigWizardPage.<init>(IfsConfigWizardPage.java:145)
            at oracle.ifs.installer.ActionQueueVerificationPage.<init>(IfsWizardFactory.java:595)
            at oracle.ifs.installer.ProtocolServerOptionsPage.<init>(IfsWizardFactory.java:2989)
            at oracle.ifs.installer.IfsWizardFactory.createWizard(IfsWizardFactory.java:376)
            at oracle.ifs.installer.IfsConfig2.<init>(IfsConfig2.java:324)
            at oracle.ifs.installer.IfsConfig2.main(IfsConfig2.java:203)

Analysis

  • Detailed traces precisely indicate the critical path of the exception

  • Free softwares don't lag behind commercial softwares and show the road to follow

Example

Stack trace of an exception from Jakarta Tomcat

 org.xml.sax.SAXParseException: The content of element type "servlet" must match "(icon?,servlet-name,display-name?,description?,(servlet-class|jsp-file),init-param*,load-on-startup?,run-as?,security-role-ref*)".
        at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
        at org.apache.xerces.util.ErrorHandlerWrapper.error(Unknown Source)
        at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
        at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
        at org.apache.xerces.impl.dtd.XMLDTDValidator.handleEndElement(Unknown Source)
        at org.apache.xerces.impl.dtd.XMLDTDValidator.endElement(Unknown Source)
        at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanEndElement(Unknown Source)
        at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
        at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
        at org.apache.xerces.parsers.DTDConfiguration.parse(Unknown Source)
        at org.apache.xerces.parsers.DTDConfiguration.parse(Unknown Source)
        at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
        at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
        at org.apache.commons.digester.Digester.parse(Digester.java:1543)
        at org.apache.catalina.startup.ContextConfig.applicationConfig(ContextConfig.java:282)
        at org.apache.catalina.startup.ContextConfig.start(ContextConfig.java:639)
        at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:243)
        at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:166)
        at org.apache.catalina.core.StandardContext.start(StandardContext.java:3567)
        at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1188)
        at org.apache.catalina.core.StandardHost.start(StandardHost.java:738)
        at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1188)
        at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:347)
        at org.apache.catalina.core.StandardService.start(StandardService.java:497)
        at org.apache.catalina.core.StandardServer.start(StandardServer.java:2190)
        at org.apache.catalina.startup.Catalina.start(Catalina.java:512)
        at org.apache.catalina.startup.Catalina.execute(Catalina.java:400)
        at org.apache.catalina.startup.Catalina.process(Catalina.java:180)
        at java.lang.reflect.Method.invoke(Native Method)
        at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:203)

(31 lines)

Example

Stack trace of an exception from Sun JDK print manager from inside Jakarta Tomcat

 2004-08-06 10:33:53 StandardWrapperValve[print]: "Servlet.service()" pour la servlet print a généré une exception
 javax.servlet.ServletException: Erreur durant l'impression
	at com.PROVIDER.prj.CLIENT.servlet.Print.service(Print.java:46)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:324)
	at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:284)
	at java.security.AccessController.doPrivileged(Native Method)
	at javax.security.auth.Subject.doAsPrivileged(Subject.java:499)
	at org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:306)
	at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:200)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:278)
	at org.apache.catalina.core.ApplicationFilterChain.access$000(ApplicationFilterChain.java:97)
	at org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:187)
	at java.security.AccessController.doPrivileged(Native Method)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:183)
	at com.PROVIDER.servlet.FileUploadFilter.doFilter(FileUploadFilter.java:94)
	at sun.reflect.GeneratedMethodAccessor41.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:324)
	at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:284)
	at java.security.AccessController.doPrivileged(Native Method)
	at javax.security.auth.Subject.doAsPrivileged(Subject.java:499)
	at org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:306)
	at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:256)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
	at org.apache.catalina.core.ApplicationFilterChain.access$000(ApplicationFilterChain.java:97)
	at org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:187)
	at java.security.AccessController.doPrivileged(Native Method)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:183)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:257)
	at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:151)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:564)
	at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:245)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:199)
	at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:151)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:564)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:195)
	at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:151)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:164)
	at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:149)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:564)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:156)
	at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:151)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:564)
	at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:972)
	at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:206)
	at org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:324)
	at org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:395)
	at org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:673)
	at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:615)
	at org.apache.jk.common.SocketConnection.runIt(ChannelSocket.java:786)
	at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:683)
	at java.lang.Thread.run(Thread.java:536)
 Caused by: javax.servlet.ServletException: Error while extracting
	at com.PROVIDER.prj.CLIENT.servlet.FichePrint.doGet(FichePrint.java:338)
	at com.PROVIDER.prj.CLIENT.servlet.FichePrint.doPost(FichePrint.java:38)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:763)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
	at com.PROVIDER.prj.CLIENT.servlet.Print.service(Print.java:43)
	... 53 more
 Caused by: com.PROVIDER.bean.ObjectNotFoundException: Objet non trouve : 
	at com.PROVIDER.prj.CLIENT.XBean$PrivilegedLoadAction.run(XBean.java:1289)
	at java.security.AccessController.doPrivileged(Native Method)
	at com.PROVIDER.prj.CLIENT.XBean.load(XBean.java:1249)
	at com.PROVIDER.prj.CLIENT.XBean.load(XBean.java:1238)
	at com.PROVIDER.prj.CLIENT.servlet.FichePrint.doGet(FichePrint.java:319)
	... 57 more

Example

 java.io.FileNotFoundException: /home/prttest/tomcat/logs/portal.log (Permission denied)
	at java.io.FileOutputStream.openAppend(Native Method)
	at java.io.FileOutputStream.<init>(FileOutputStream.java:177)
	at java.io.FileOutputStream.<init>(FileOutputStream.java:102)
	at org.apache.log4j.FileAppender.setFile(FileAppender.java:272)
	at org.apache.log4j.RollingFileAppender.setFile(RollingFileAppender.java:156)
	at org.apache.log4j.FileAppender.activateOptions(FileAppender.java:151)
	at org.apache.log4j.config.PropertySetter.activate(PropertySetter.java:247)
	at org.apache.log4j.config.PropertySetter.setProperties(PropertySetter.java:123)
	at org.apache.log4j.config.PropertySetter.setProperties(PropertySetter.java:87)
	at org.apache.log4j.PropertyConfigurator.parseAppender(PropertyConfigurator.java:645)
	at org.apache.log4j.PropertyConfigurator.parseCategory(PropertyConfigurator.java:603)
	at org.apache.log4j.PropertyConfigurator.configureRootCategory(PropertyConfigurator.java:500)
	at org.apache.log4j.PropertyConfigurator.doConfigure(PropertyConfigurator.java:406)
	at org.apache.log4j.PropertyConfigurator.doConfigure(PropertyConfigurator.java:432)
	at org.apache.log4j.helpers.OptionConverter.selectAndConfigure(OptionConverter.java:460)
	at org.apache.log4j.LogManager.<clinit>(LogManager.java:113)
	at org.apache.log4j.Logger.getLogger(Logger.java:85)
	at org.apache.commons.logging.impl.Log4JLogger.<init>(Log4JLogger.java:102)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:274)
	at org.apache.commons.logging.impl.LogFactoryImpl.newInstance(LogFactoryImpl.java:529)
	at org.apache.commons.logging.impl.LogFactoryImpl.getInstance(LogFactoryImpl.java:235)
	at org.apache.commons.logging.impl.LogFactoryImpl.getInstance(LogFactoryImpl.java:209)
	at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:351)
	at org.apache.commons.beanutils.ConvertUtilsBean.<init>(ConvertUtilsBean.java:130)
	at org.apache.commons.beanutils.BeanUtilsBean.<init>(BeanUtilsBean.java:110)
	at org.apache.commons.beanutils.BeanUtilsBean$1.initialValue(BeanUtilsBean.java:68)
	at org.apache.commons.beanutils.ContextClassLoaderLocal.get(ContextClassLoaderLocal.java:80)
	at org.apache.commons.beanutils.BeanUtilsBean.getInstance(BeanUtilsBean.java:78)
	at org.apache.commons.beanutils.ConvertUtilsBean.getInstance(ConvertUtilsBean.java:115)
	at org.apache.commons.beanutils.ConvertUtils.convert(ConvertUtils.java:217)
	at org.apache.commons.digester.CallMethodRule.end(CallMethodRule.java:457)
	at org.apache.commons.digester.Rule.end(Rule.java:276)
	at org.apache.commons.digester.Digester.endElement(Digester.java:1058)
	at org.apache.xerces.parsers.AbstractSAXParser.endElement(Unknown Source)
	at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanEndElement(Unknown Source)
	at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
	at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
	at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
	at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
	at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
	at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
	at org.apache.commons.digester.Digester.parse(Digester.java:1548)
	at org.apache.catalina.startup.ContextConfig.defaultConfig(ContextConfig.java:515)
	at org.apache.catalina.startup.ContextConfig.start(ContextConfig.java:623)
	at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:216)
	at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
	at org.apache.catalina.core.StandardContext.start(StandardContext.java:4290)
	at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:823)
	at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:807)
	at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:595)
	at org.apache.catalina.core.StandardHostDeployer.install(StandardHostDeployer.java:277)
	at org.apache.catalina.core.StandardHost.install(StandardHost.java:832)
	at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:701)
	at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:432)
	at org.apache.catalina.startup.HostConfig.check(HostConfig.java:1083)
	at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:327)
	at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
	at org.apache.catalina.core.StandardHost.backgroundProcess(StandardHost.java:800)
	at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1619)
	at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1628)
	at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1608)
	at java.lang.Thread.run(Thread.java:534)

(66 lines)

What about Perl?

  • Acme::JavaTrace module, available on the CPAN

  • Overloads the functions warn() and die()

    • Acme::JavaTrace augments the paradigm of these widely used functions while keeping their semantic untouched

  • Use is extremely simplified: use Acme::JavaTrace

Example

Stack trace of warnings generated by a test script of HTTP::Proxy

 getsockname() on closed socket Symbol::GEN1
        at IO::Socket::sockname(/System/Library/Perl/darwin/IO/Socket.pm:186)
        at IO::Socket::INET::sockport(/System/Library/Perl/IO/Socket/INET.pm:231)
        at HTTP::Daemon::url(/Library/Perl/HTTP/Daemon.pm:52)
        at HTTP::Daemon::ClientConn::get_request(/Library/Perl/HTTP/Daemon.pm:139)
        at HTTP::Proxy::serve_connections(lib/HTTP/Proxy.pm:287)
        at HTTP::Proxy::start(lib/HTTP/Proxy.pm:179)
        at t::Utils::fork_proxy(t/Utils.pm:72)
        at main::(t/20keepalive.t:70)
 Use of uninitialized value in numeric ne (!=)
        at HTTP::Daemon::url(/Library/Perl/HTTP/Daemon.pm:53)
        at HTTP::Daemon::ClientConn::get_request(/Library/Perl/HTTP/Daemon.pm:139)
        at HTTP::Proxy::serve_connections(lib/HTTP/Proxy.pm:287)
        at HTTP::Proxy::start(lib/HTTP/Proxy.pm:179)
        at t::Utils::fork_proxy(t/Utils.pm:72)
        at main::(t/20keepalive.t:70)
 Use of uninitialized value in concatenation (.)
        at HTTP::Daemon::url(/Library/Perl/HTTP/Daemon.pm:53)
        at HTTP::Daemon::ClientConn::get_request(/Library/Perl/HTTP/Daemon.pm:139)
        at HTTP::Proxy::serve_connections(lib/HTTP/Proxy.pm:287)
        at HTTP::Proxy::start(lib/HTTP/Proxy.pm:179)
        at t::Utils::fork_proxy(t/Utils.pm:72)
        at main::(t/20keepalive.t:70)

Example

Stack trace of warnings generated by a test script of NetworkInfo::Discovery::Rendezvous

 Use of uninitialized value in split
        at Net::Rendezvous::Entry::fetch(/Library/Perl/Net/Rendezvous/Entry.pm:172)
        at Net::Rendezvous::discover(/Library/Perl/Net/Rendezvous.pm:320)
        at NetworkInfo::Discovery::Rendezvous::discover_service(lib/NetworkInfo/Discovery/Rendezvous.pm:140)
        at NetworkInfo::Discovery::Rendezvous::do_it(lib/NetworkInfo/Discovery/Rendezvous.pm:117)
        at <eval>(t/20rendezvous.t:48)
        at main::(t/20rendezvous.t:48)
 Use of uninitialized value in sprintf
        at Net::Rendezvous::Entry::type(/Library/Perl/Net/Rendezvous/Entry.pm:247)
        at Net::Rendezvous::Entry::fetch(/Library/Perl/Net/Rendezvous/Entry.pm:175)
        at Net::Rendezvous::discover(/Library/Perl/Net/Rendezvous.pm:320)
        at NetworkInfo::Discovery::Rendezvous::discover_service(lib/NetworkInfo/Discovery/Rendezvous.pm:140)
        at NetworkInfo::Discovery::Rendezvous::do_it(lib/NetworkInfo/Discovery/Rendezvous.pm:117)
        at <eval>(t/20rendezvous.t:48)
        at main::(t/20rendezvous.t:48)
 Use of uninitialized value in sprintf
        at Net::Rendezvous::Entry::type(/Library/Perl/Net/Rendezvous/Entry.pm:247)
        at Net::Rendezvous::Entry::fetch(/Library/Perl/Net/Rendezvous/Entry.pm:175)
        at Net::Rendezvous::discover(/Library/Perl/Net/Rendezvous.pm:320)
        at NetworkInfo::Discovery::Rendezvous::discover_service(lib/NetworkInfo/Discovery/Rendezvous.pm:140)
        at NetworkInfo::Discovery::Rendezvous::do_it(lib/NetworkInfo/Discovery/Rendezvous.pm:117)
        at <eval>(t/20rendezvous.t:48)
        at main::(t/20rendezvous.t:48)

New problem

Thanks

  • Thanks to Sun and Tomcat for offering such guarantees of unlimited work to the systems administrators