tag:blogger.com,1999:blog-68273632805925329572024-02-08T08:24:51.703+02:00cat **/* | grep яAkshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.comBlogger1125tag:blogger.com,1999:blog-6827363280592532957.post-19271257375220412982006-10-17T01:24:00.001+03:002009-02-22T16:24:44.289+02:00JCAДопустим мы пишем JCA RA который поддерживает исходящие соединения к EIS. Все написали. Верифицировали. Продеплоили в GlassFish. Все OK. Теперь продеплоили какое-то приложение, чтобы протестировать соединение к EIS. Запускаем. А оно нам @#%!: "Exception in NamingManagerImpl copyMutableObject() ... java.io.NotSerializableException".<ad></ad><br />Покопавшись мы выясняем, что падение происходит при копировании нашей имплементации java.resource.cci.ConnectionFactory интерфейса. А имеено в нашем классе ConnectionFactoryImpl есть не Serealizable поле, например ManagedConnectionFactory (содержащая сокет например). Убив N часов времени на поиски в гугле, выясняем, что GlassFish в JNDI помещает копии объектов! Наматерившись и решив, что разработчикам JNDI реализации виднее, мы делаем неугодное в ConnectionFactoryImpl поле transient'ым. А вдруг этот объект будет использоваться, только чтобы getReference вызвать? Хрен там. Повозившись еще, оказывается, что dependency injection отдает нам именно копию из JNDI у которой наше transient поле установленно в NULL!<br /><br />Даём GlassFish'у последний шанс. Читаем его исходники и оказывается, что не все объекты помещаются в JNDI в сереализованном виде. Так например Connector'ы должны помещаться не сереализованными! Хм, а как же оно определяет, что этот объект коннектор? А вот как:<br /><pre><br /> private boolean isConnector(String logicalJndiName){<br /> return (logicalJndiName.indexOf(EIS_STRING)!=-1);<br /> }<br />где EIS_STRING = "/eis/".<br /></pre><br />Короче, чтобы не иметь лишний геморрой: ConnectionFactory экземпляры должны помещаться в субконтексте /eis/ ! Если теперь поискать в гугле по словам "eis subcontext" то находятся <i>рекомендации</i>, а не <i>требования</i>!.<br /><br />Вообще, это частая ошибка, проявляется в виде NPE (null pointer exception) при вызове transient полей (activemq этим страдает). Мне кажется, в ConnectionFactoryImpl разумно вставить:<br /><pre><br /> /**<br /> * Ensure that managedConnectionFactory is not null.<br /> * @throws ResourceException if managedConnectionFactory is null.<br /> */<br /> protected void ensureManagedConnectionFactory () throws ResourceException {<br /> if (this.managedConnectionFactory == null) {<br /> throw new ResourceException (<br /> "No reference to managed connection factory exists."<br /> + " Either it is a bug of the RA or your JNDI resource"<br /> + " is not in the /eis/ subcontext");<br /> }<br /></pre><br />и вызывать этот метод перед использованием this.managedConnectionFactory внутри ConnectionFactoryImpl.<ad2></ad2>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0