在同一Java VM上使用不同的DocumentBuilder实现

时间:2014-01-30 15:41:19

标签: xml multithreading java-ee global-variables default-implementation

我知道这个问题已经被问到了,但是有一种不同的味道,所以我再次向我的POV询问。

在我们的应用程序服务器中有几个EJB驻留(因此,AFAIK,几个线程,每个EJB调用一个)。一些EJB,为了正常运行,需要DocumentBuilder工厂生成xerces实例,一些EJB需要crimson实例。

目前,选择强制xerces作为默认值,因此xerces类被注入适当的System.property,这是全局的。

据我所知,DocumentBuilder类首先查找System.property,然后查找属性文件到JRE文件夹,然后再查找属性文件到JAR / Services。

为了隔离需要深红色工作的库,我编写了一个自定义类加载器,所以他们的jar不在类路径中,我可以确定“套件”的其他部分听起来很安全,不受干扰。

但即使我将这些罐子隔离开来,他们也会利用DocumentBuilder,它会像前面所说的那样寻找实施方案。如果我将System.property更改为调用库所需的严格时间,那么我冒着其他EJB崩溃的风险,因为它们没有得到正确的实现。

我还尝试编写一个伪造的DocumentBuilder类来根据调用线程切换newInstance结果,但这不起作用(太糟糕了,被调用的库通过捕获原始异常并通过仅获取新异常来抛出异常来掩盖异常原始消息,这不足以得到重点)

我正在寻找一种在线程级别隔离属性更改的方法,但无法弄明白。

有什么想法?谢谢!

1 个答案:

答案 0 :(得分:0)

好的,我想出了如何解决这个问题。

我实际上写了一个假的DocumentBuilder,它接受一个静态字段,需要得到crimson实现的Thread。所以,只有这个线程会变得绯红,所有其他线程都会得到xerces。然后,我只是在javax.xml.parsers.DocumentBuilderFactory System属性中设置此类,并在完成时重置为原始值。我猜这个解决方案可以推广到一个永久类来处理来自vaiour线程的请求。

这里是伪造的DocumentBuilder的来源:

public class   DocumentBuilderFactoryTweak
       extends DocumentBuilderFactory
{
  private static Thread tweakingTH = null;    

  private DocumentBuilderFactory impl = null;

  public DocumentBuilderFactoryTweak() {
    super();
    try {
      this.impl =
          Thread.currentThread() == tweakingTH
        ? (DocumentBuilderFactory)tweakingTH.getContextClassLoader().loadClass( "org.apache.crimson.jaxp.DocumentBuilderFactoryImpl" ).newInstance()
        : (DocumentBuilderFactory)Class.forName( "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl"  ).newInstance();
    }
    catch( Throwable exc ) { exc.printStackTrace(); }
  }

  public synchronized static void setTweakingThread( Thread th ) { tweakingTH = th; }

  public boolean isCoalescing                                ()                                     { return this.impl.isCoalescing                      ();       }
  public boolean isExpandEntityReferences                    ()                                     { return this.impl.isExpandEntityReferences          ();       }
  public boolean isIgnoringComments                          ()                                     { return this.impl.isIgnoringComments                ();       }
  public boolean isIgnoringElementContentWhitespace          ()                                     { return this.impl.isIgnoringElementContentWhitespace();       }
  public boolean isNamespaceAware                            ()                                     { return this.impl.isNamespaceAware                  ();       }
  public boolean isValidating                                ()                                     { return this.impl.isValidating                      ();       }
  public void    setCoalescing                               ( boolean v )                          { this.impl.setCoalescing                            ( v );    }
  public void    setExpandEntityReferences                   ( boolean v )                          { this.impl.setExpandEntityReferences                ( v );    }
  public void    setIgnoringComments                         ( boolean v )                          { this.impl.setIgnoringComments                      ( v );    }
  public void    setIgnoringElementContentWhitespace         ( boolean v )                          { this.impl.setIgnoringElementContentWhitespace      ( v );    }
  public void    setNamespaceAware                           ( boolean v )                          { this.impl.setNamespaceAware                        ( v );    }
  public void    setValidating                               ( boolean v )                          { this.impl.setValidating                            ( v );    }
  public javax.xml.parsers.DocumentBuilder newDocumentBuilder() throws ParserConfigurationException { return this.impl.newDocumentBuilder                ();       }
  public Object  getAttribute                                ( String k )                           { return this.impl.getAttribute                      ( k );    }
  public void    setAttribute                                ( String k, Object v )                 { this.impl.setAttribute                             ( k, v ); }    
}