Why can't I instantiate DataImportHandler in Solr on JBoss? - java

I'm trying to set up Solr 3.5.0 on JBoss 5.1. Everything works quite fine. I copied war into deploy dir, all the dependencies from dist and contrib directories into the lib (or earlier deploy) directory.
I can start a server, everything works fine, but whenever I want to activate the DataImportHandler to index data in my DB, I get an error.
Basically what I do is I copy is I copy a core from example/example-DIH/solr/db (Or whole example, that doesn't matter), I register the core in solr.xml and at startup I get an error:
15:17:10,707 SEVERE [RequestHandlers] org.apache.solr.common.SolrException: Error Instantiating Request Handler, org.apache.solr.handler.dataimport.DataImportHandler is not a org.apache.solr.request.SolrRequestHandler
at org.apache.solr.core.SolrCore.createInstance(SolrCore.java:427)
at org.apache.solr.core.SolrCore.createRequestHandler(SolrCore.java:461)
at org.apache.solr.core.RequestHandlers.initHandlersFromConfig(RequestHandlers.java:157)
I'm pretty sure my request handler definition is correct, but just to be sure:
<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
<lst name="defaults">
<str name="config">dataimport.xml</str>
</lst>
As far as I can find, this error may be caused by DataImportHandler and SolrRequestHandler supposedly being hold different class loaders.
Whenever I start a Solr from the start.jar app in example (I think it starts a Jetty server) it works fine.
My question is: is this really because of the class loader issue, or some other thing? And, more importantly: how do I fix it?

This is a class loader issue and according to this post on the Lucene Developer Mailing List you need to do the following:
make sure that the dataimport jars are NOT in the classpath and not loaded by other classloaders but from the path specified in solrconfig.xml. This will ensure that the dataimport classes are loaded by the same classloader.
Please see the thread for more details.

Paige Cook's answer is correct, but I'd like to add some details. I think you put the dataimporthandler jar into the common lib directory of your application server, while all solr jars are inside the WEB-INF/lib of solr.war. This means you're loading the dataimporthandler jar from a different classloader. You can solve it by putting your solr libraries in a different lib (external) directory. Then in your solr.xml you should refer to that lib folder through the sharedLib attribute. Something like this:
<?xml version="1.0" encoding="UTF-8" ?>
<solr persistent="false" sharedLib="lib">
<cores adminPath="/admin/cores">
<core name="core1" instanceDir="core1" />
</cores>
</solr>
This way the Solr web application will load jars from that external location through its specific classloader.

As said by Paige Cook this is a class loader issue, you should add dataimport jars into a path used by Solr class loader. In order to define such lib path there are many options.
Old versions of Solr (4.x and older) accepts an attribute sharedLib in the tag :
<solr persistent="false" sharedLib="lib"></solr>
sharedLib - Path to a directory containing .jar files that are added to the classpath of every core. The path is relative to solr.home (where solr.xml sits).
Newer versions of Solr (5.x and newer) use sharedLib as a child node of solr element.
<?xml version='1.0' encoding='UTF-8'?>
<solr>
<str name='sharedLib'>lib</str>
</solr>
Even in this case the lib path is relative to solr.home (where solr.xml sits).
Another alternative is define a lib directive directly into the solrconfig.xml,

Related

Someone used solr5.5? In which directory should I put Mysql package?

My mysql-data-input.xml looks like:
<dataSource type="JdbcDataSource" driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost/dbname" user="db_username" password="db_password"/>
obviously, it need mysql jar, but I don't know in which directory should I put mysql.jar.
The solr config directory is /aparts/solr-5.5.0/server/solr/configsets/basic_configs/conf, also mysql-data-input.xml is there.
Technically, you can put the dependencies files/Jars any where. As long as you make sure in solrconfig.xml, you added the dependencies to the lib tag so Solr knows where it is.
Here is the solrconfig.xml from techproducts which is one of the built in example project.
Here is a screenshot where I dump mysql connector into the dist folder of solr home and how my solrconfig looks like:
It should be added in the application server's lib folder.
I have been using apache-tomcat and added the same in tomcat's lib folder.
apache-tomcat-5.5.26/common/lib

How to force jboss to load classes from jars in webapp's lib

I am trying to deploy my web application on jboss-6.0.0Final, which is currently deployed on apache tomcat.
I have two jars one that contains same package which is org.apache.axis. I am putting one jar in <Jboss-home>/server/default/lib & another jar in <my-app-war>WEB-INF/lib.
It is required to put both jars in the class path. No way to remove one of the jar. So I need to keep both jars. & It is giving me following error
java.lang.ClassCastException: org.apache.axis.attachments.AttachmentsImpl cannot be cast to org.apache.axis.attachments.Attachments
at org.apache.axis.AxisFault.makeFault(AxisFault.java:101)
at org.apache.axis.client.Call.invoke(Call.java:1828)
I think it is due to conflict of same classes in two different jars.
Now, I want to know the way by which I can force jboss to load classes of this particular package from axis.jar exist in /WEB-INF/lib.
How can I do that?
This helped me:
http://www.mastertheboss.com/jboss-configuration/solving-jboss-5-classloading-issues
Explode your war,
In your Exploded WAR web-inf directory add this xml file: jboss-classloading.xml
with content:
(domain is your war name)
<classloading xmlns="urn:jboss:classloading:1.0"
name="mywar.war"
domain="mywar_domain" <!-- (domain is your war name) -->
parent-domain="Ignored"
export-all="NON_EMPTY"
import-all="true">
</classloading>
I'll share quite simple and straight forward process which I had followed when I came across same situation.
1> Create a jboss-web.xml file.
<class-loading java2classloadingcompliance="false">
<loader-repository>
com.rts:archive=DTH_PROD.war
<loader-repository-config>
java2ParentDelegation=false
</loader-repository-config>
</loader-repository>
</class-loading>
</jboss-web>
Points:,
Begin the xml with tag which is not visible in the code I'm posting
Check 3rd line of above code,
com.rts - This is your package name.
DTH_PROD.war - Name of bundle you wish to keep
2> Now place this xml file into WEB-INF directory of your project and voilla!!
Further more you may wish to refer this article for detailed info. Also comment below if you face any difficulty solving this.

Load persistence.xml from aar in tomcat

I have a openJPA based project that I need to deploy it in format of aar into the following folder under Tomcat.
tomcat\webapps\axis2\WEB-INF\services
But it seems that the service cannot load the persistence.xml file in the META-INF folder within the aar file. I found a solution to rename the aar file into jar, like DummySerivce.aar -> DummySerivce.jar and then put the DummySerivce.jar into the lib folder, to be exactly
tomcat\webapps\axis2\WEB-INF\lib
This time, the persistence.xml could be loaded and the service worked well. But this unnecessarily imported a jar file which was not included in the specification.
So my question is, is there any way to load the persistence.xml from a aar file? is it possible to overload the path of persistence.xml file in code?
btw, only entity information are left in the persistence.xml, database connection parameters are already define in code, and I'm using Axis2.
Thanks!
I have found a solution.
By adding the following line into the services.xml, persistence.xml packed in aar file could be successfully loaded.
<parameter name="ServiceTCCL">composite</parameter>
for detailed info. please refer to http://wso2.org/node/1131
Now checking if there's any side effect.
TCCL - Thread context class loader
default - Status quo, normal behavior
composite - TCCL contains all
jars from environment (say webapp) and those specified in the
service
archive (aar) file under /lib service - TCCL contains all jars from
service archive (aar)

How do I tell JBoss 4.2.3.GA to load jars in my war file lib directory first?

I deploy a web archive and that war references a jar file that conflicts with those in $JBOSS_HOME/server/default/lib. I can go and remove the offending jars manually, but I'd prefer a solution that allows me to specify my jars over JBoss's. I would even like to just tell JBoss to exclude specific jars, if that's even possible.
The closest I've come was to add something in jboss-web.xml in my war's META-INF directory, but I'm clearly not doing something right there. This is what I have so far:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
<class-loading java2ClassLoadingCompliance="false">
<loader-repository>com.amce:archive=WHATEVER</loader-repository>
<loader-repository-config>java2ParentDelegation=false</loader-repository-config>
</class-loading>
</jboss-web>
This fails spectacularly with errors like this:
ERROR [13]] Exception sending context initialized event to listener instance of class org.jboss.web.jsf.integration.config.JBossJSFConfigureListener
java.lang.ClassCastException: org.apache.xerces.jaxp.SAXParserFactoryImpl cannot be cast to javax.xml.parsers.SAXParserFactory
at javax.xml.parsers.SAXParserFactory.newInstance(SAXParserFactory.java:128)
at com.sun.faces.config.ConfigureListener$WebXmlProcessor.getConfiguredFactory(ConfigureListener.java:697)
at com.sun.faces.config.ConfigureListener$WebXmlProcessor.scanForFacesServlet(ConfigureListener.java:669)
...
That error leads me to believe I'm just specifying the jboss-web syntax incorrectly (is there an xml schema somewhere)? However I'm not even sure I'm heading down the right path. Is there anyway I can do this without modifying JBoss in anyway?
java2ParentDelegation=false. Read here for more details.
Java EE class loading details: Java EE class loading standard
jboss-web.xml belongs in your app's WEB-INF directory, not META-INF. your xml file looks right, I compared it to WAR i have deploye to Jboss-4.x

What's the purpose of META-INF?

In Java, you often see a META-INF folder containing some meta files. What is the purpose of this folder and what can I put there?
From the official JAR File Specification (link goes to the Java 7 version, but the text hasn't changed since at least v1.3):
The META-INF directory
The following files/directories in the META-INF directory are recognized and interpreted by the Java 2 Platform to configure applications, extensions, class loaders and services:
MANIFEST.MF
The manifest file that is used to define extension and package related data.
INDEX.LIST
This file is generated by the new "-i" option of the jar tool, which contains location information for packages defined in an application or extension. It is part of the JarIndex implementation and used by class loaders to speed up their class loading process.
x.SF
The signature file for the JAR file. 'x' stands for the base file name.
x.DSA
The signature block file associated with the signature file with the same base file name. This file stores the digital signature of the corresponding signature file.
services/
This directory stores all the service provider configuration files.
New since Java 9 implementing JEP 238 are multi-release JARs. One will see a sub folder versions. This is a feature which allows to package classes which are meant for different Java version in one jar.
Generally speaking, you should not put anything into META-INF yourself. Instead, you should rely upon whatever you use to package up your JAR. This is one of the areas where I think Ant really excels: specifying JAR file manifest attributes. It's very easy to say something like:
<jar ...>
<manifest>
<attribute name="Main-Class" value="MyApplication"/>
</manifest>
</jar>
At least, I think that's easy... :-)
The point is that META-INF should be considered an internal Java meta directory. Don't mess with it! Any files you want to include with your JAR should be placed in some other sub-directory or at the root of the JAR itself.
I've noticed that some Java libraries have started using META-INF as a directory in which to include configuration files that should be packaged and included in the CLASSPATH along with JARs. For example, Spring allows you to import XML Files that are on the classpath using:
<import resource="classpath:/META-INF/cxf/cxf.xml" />
<import resource="classpath:/META-INF/cxf/cxf-extensions-*.xml" />
In this example, I'm quoting straight out of the Apache CXF User Guide. On a project I worked on in which we had to allow multiple levels of configuration via Spring, we followed this convention and put our configuration files in META-INF.
When I reflect on this decision, I don't know what exactly would be wrong with simply including the configuration files in a specific Java package, rather than in META-INF. But it seems to be an emerging de facto standard; either that, or an emerging anti-pattern :-)
The META-INF folder is the home for the MANIFEST.MF file. This file contains meta data about the contents of the JAR. For example, there is an entry called Main-Class that specifies the name of the Java class with the static main() for executable JAR files.
META-INF in Maven
In Maven the META-INF folder is understood because of the Standard Directory Layout, which by name convention package your project resources within JARs: any directories or files placed within the ${basedir}/src/main/resources directory are packaged into your JAR with the exact same structure starting at the base of the JAR.
The Folder ${basedir}/src/main/resources/META-INF usually contains .properties files while in the jar contains a generated MANIFEST.MF, pom.properties, the pom.xml, among other files. Also frameworks like Spring use classpath:/META-INF/resources/ to serve web resources.
For more information see How do I add resources to my Maven Project.
You can also place static resources in there.
In example:
META-INF/resources/button.jpg
and get them in web3.0-container via
http://localhost/myapp/button.jpg
> Read more
The /META-INF/MANIFEST.MF has a special meaning:
If you run a jar using java -jar myjar.jar org.myserver.MyMainClass you can move the main class definition into the jar so you can shrink the call into java -jar myjar.jar.
You can define Metainformations to packages if you use java.lang.Package.getPackage("org.myserver").getImplementationTitle().
You can reference digital certificates you like to use in Applet/Webstart mode.
Adding to the information here, the META-INF is a special folder which the ClassLoader treats differently from other folders in the jar.
Elements nested inside the META-INF folder are not mixed with the elements outside of it.
Think of it like another root. From the Enumerator<URL> ClassLoader#getSystemResources(String path) method et al perspective:
When the given path starts with "META-INF", the method searches for resources that are nested inside the META-INF folders of all the jars in the class path.
When the given path doesn't start with "META-INF", the method searches for resources in all the other folders (outside the META-INF) of all the jars and directories in the class path.
If you know about another folder name that the getSystemResources method treats specially, please comment about it.
Just to add to the information here, in case of a WAR file, the META-INF/MANIFEST.MF file provides the developer a facility to initiate a deploy time check by the container which ensures that the container can find all the classes your application depends on. This ensures that in case you missed a JAR, you don't have to wait till your application blows at runtime to realize that it's missing.
I have been thinking about this issue recently. There really doesn't seem to be any restriction on use of META-INF. There are certain strictures, of course, about the necessity of putting the manifest there, but there don't appear to be any prohibitions about putting other stuff there.
Why is this the case?
The cxf case may be legit. Here's another place where this non-standard is recommended to get around a nasty bug in JBoss-ws that prevents server-side validation against the schema of a wsdl.
http://community.jboss.org/message/570377#570377
But there really don't seem to be any standards, any thou-shalt-nots. Usually these things are very rigorously defined, but for some reason, it seems there are no standards here. Odd. It seems like META-INF has become a catchall place for any needed configuration that can't easily be handled some other way.
If you're using JPA1, you might have to drop a persistence.xml file in there which specifies the name of a persistence-unit you might want to use. A persistence-unit provides a convenient way of specifying a set of metadata files, and classes, and jars that contain all classes to be persisted in a grouping.
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
// ...
EntityManagerFactory emf =
Persistence.createEntityManagerFactory(persistenceUnitName);
See more here:
http://www.datanucleus.org/products/datanucleus/jpa/emf.html
All answers are correct. Meta-inf has many purposes. In addition, here is an example about using tomcat container.
Go to
Tomcat Doc and check
" Standard Implementation > copyXML " attribute.
Description is below.
Set to true if you want a context XML descriptor embedded inside the application (located at /META-INF/context.xml) to be copied to the owning Host's xmlBase when the application is deployed. On subsequent starts, the copied context XML descriptor will be used in preference to any context XML descriptor embedded inside the application even if the descriptor embedded inside the application is more recent. The flag's value defaults to false. Note if the deployXML attribute of the owning Host is false or if the copyXML attribute of the owning Host is true, this attribute will have no effect.
You have MANIFEST.MF file inside your META-INF folder. You can define optional or external dependencies that you must have access to.
Example:
Consider you have deployed your app and your container(at run time) found out that your app requires a newer version of a library which is not inside lib folder, in that case if you have defined the optional newer version in MANIFEST.MF then your app will refer to dependency from there (and will not crash).
Source: Head First Jsp & Servlet
As an addition the META-INF folder is now also used for multi-release jars. This is a feature which allows to package classes which are meant for different Java version in one jar, e.g. include a class for Java 11 with new features offered by Java 11 in a jar also working for Java 8, where a different class for Java 8 with less features in contained. E.g this can be useful if a newer Java version is offering enhanced, different or new API methods which would not work in earlier version due to API violations. One will see a sub folder versions then.

Categories

Resources