NoClassDefFoundError accessing jackrabbit jar from servlet - spring-mvc

I'm getting the above mentioned error when trying to access a repository
using jackrabbit-standalone-2.4.2.jar from a servlet. I didn't use the
jackrabbit war because I already have a thick client app working and I want
to reuse as much code as possible. I just assumed doing this was possible.
To test I created a small web application. Since I cannot attach a zip file
I will just copy the doPost() method below:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Repository repository = new TransientRepository(
"repository.xml", //embedded within the war
"path/to/home/dir");
Session session = null;
try {
session = repository.login();
System.out.println("root node identifier: " +
session.getRootNode().getIdentifier());
} catch (Exception e) {
e.printStackTrace();
} finally {
session.logout();
}
}
When I post to this servlet from an html form the exception has 2 parts:
java.lang.NoClassDefFoundError: javax/jcr/Repository
java.lang.ClassNotFoundException: javax.jcr.Repository
when I add jcr-2.0.jar in it then I get a different error:
java.lang.NoClassDefFoundError: org/apache/jackrabbit/core/TransientRepository

You originally got the ClassNotFoundException because that class wasn't in the classpath. You have fixed that. The NoClassDefFoundError means the class is in the classpath, but there was an problem initializing it. For details about this distinction, see also this question.
So the class TransientRepository is there, but most likely a class referenced by the TransientRepository isn't. That means most likely you didn't include other required jar files in the classpath. For a complete list of dependencies (required jar files), see the jackrabbit-standalone-2.4.2.jar, or see the Jackrabbit docs. It could also mean you have all jar files, but at least one of the jar files is the wrong version.

You originally got the ClassNotFoundException because that class wasn't in the classpath. You have fixed that.
The NoClassDefFoundError means the class is in the classpath, but there was an problem initializing it.

Related

How to do logging in servlets deployed to jboss 7.1

I am writing a simple web app with one servlet and my System.out.println statements (in my servlet) do not show up in the server.log file which for me is located at
C:\jboss-as-7.1.1.Final\jboss-as-7.1.1.Final\standalone\log
So, I'm thinking that maybe I need to set up some kind of logging or something. I am completely clueless on this.
I have tried to research log4j as an option but the more I research the more confused I get.
I need a step by step approach on this. If anyone could please help I would be so thankful.
The simplest to start is IMHO using java.util.logging framework. You don't need any special application dependency. It just works.
Example usage in a servlet:
import java.util.logging.Logger;
private final Logger LOGGER = Logger.getLogger(getClass().getName());
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/plain");
final PrintWriter writer = resp.getWriter();
writer.println("Logging message with SEVERE importance level");
LOGGER.severe("Test log message with level SEVERE");
writer.close();
}
Look on GitHub for a full example servlet.
To enable all log-levels for your application, you can use JBoss CLI (jboss-cli.sh / jboss-cli.bat). Here is example, assuming your application is under org.jboss.test package:
connect
/subsystem=logging/console-handler=CONSOLE:write-attribute(name=level,value=ALL)
/subsystem=logging/logger=org.jboss.test:add(level=ALL)
quit

how to call a sling servlet through osgi bundle inside CQ5

I just created a Sling servlet through maven.packaging as - "bundle", then I installed it inside system console of CQ5.
My bundle shows me Active state and all the required packages ..exported successfully.
but I when I call this bundle to use the servlet... nothing happened.
It doesn't give me response.
Is there a better way..to create a sling servlet and create a OSGI bundle,so that I can install it as a bundle in CQ5 to call the servlet from the component.
You can create SlingSerlvet like this.
#SlingServlet(
paths={"/services/myapp/LoginController/validateUser","/services/myapp/LoginController/logout"})
#Properties({
#Property(name="service.pid", value="com.xxx.xxx.controller.LoginController",propertyPrivate=false),
#Property(name="service.description",value="Validates the user", propertyPrivate=false),
#Property(name="service.vendor",value="xxx Tech", propertyPrivate=false)
})
public class LoginController extends SlingAllMethodsServlet{
private static final long serialVersionUID = 1L;
#Override
protected void doPost(SlingHttpServletRequest request,
SlingHttpServletResponse response) throws ServletException,
IOException {
}
#Override
protected void doGet(SlingHttpServletRequest request,
SlingHttpServletResponse response) throws ServletException,
IOException {
}
}
To Call this servlet in browser just type the URLS "/services/myapp/LoginController/validateUser"
And "/services/myapp/LoginController/logout" As you may already know that a serlvet can have multiple URLS.
This is a working piece of Code.
Make sure that your URL Mappings i.e paths(in Sling/CQ5) starts with /services
also you can also create bundle using a dedicated Eclipse for CQ5 CRXDE Eclipse instead of Maven bundle.
It's much easier to use but it is a bit slow. Download Here
Bingo.. finally I am able to call a sling sevlet bundled as OSGI bundle and deployed in CQ's system console.
later I called this OSGI bundle fire a post request and this time able to get the response.
here is a very nice and very explanatory tutorial from Scott that explain every and each steps of my problem.
http://scottsdigitalcommunity.blogspot.in/2013/06/posting-form-data-to-adobe-cq-using.html
and the sample code or sample application link can be found from here -
http://helpx.adobe.com/experience-manager/using/custom-sling-servlets.html
follow the above link step by step and you end up with the victory.
I followed each steps and successfully called OSGI bundle's servlet through component inside CRXDE.
and finally not to forget to thanks Scott.... thanks Scott for the explanation !!!

Could you explain spring-boot thread's classloader principals in servlet init() vs servlet request?

We have a working spring-boot powered app using embedded Tomcat, and one of the servlets is a legacy Struts 1.3.10 one (don't ask). And this is working perfectly fine!
Or it was until we added BIRT viewer servlet, which init() code changes the thread's classloader.
To summarise in #Confuguration both Struts Servlet and BIRT Servlet are normal ServletRegistrationBeans.
BIRT Servlet in init() is doing the following:
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
Once the app is running, on each request to Struts Servlet, it tries to resolve the needed property from a prepopulated HashMap, where the key is the CLassLoader, and it fails to find a match:
ClassLoader cl = Thread.currentThread().getContextClassLoader();
This is the outcome:
2014-06-10 08:33:28.971 ERROR 16572 --- [nio-9087-exec-4] o.a.c.c.C.[.[.[/].[ActionServlet] : Servlet.service() for servlet [ActionServlet] in context with path [] threw exception [Cannot find catalog 'struts'] with root cause
The way I solved it out of no other ideas, is to revert the classloader just before init() is done, by extending BIRT servlet:
public class BirtEngineServletWorkaround extends BirtEngineServlet {
#Override
public void init(ServletConfig config) throws ServletException {
ClassLoader savedClassLoader = Thread.currentThread().getContextClassLoader();
super.init(config);
//return classloader to this thread o_O!
Thread.currentThread().setContextClassLoader(savedClassLoader);
}
}
QUESTION: Why changing the thread's classloader is allowed? Is this setting or getting the classloader in this particular case wrong? Would classloaders be fine if it wasn't in embedded container? Should thread's classloader be mutable? Could somebody be so kind and lecture me a bit about this?

jboss deployment issue - can not visit servlet

I am trying to write a simple web application and deploy on jboss EAP 6. The application is named "webapp" and I was able to build and deploy it to jboss. The context root is /webapp.
I was able to then visit localhost:8080/webapp and it returns a "Hello World" printed from the defaulted index.jsp that was generated by eclipse at /src/main/webapp.
However, when I tried to actually visit the servlet at localhost:8080/webapp/sessionsetup I got the following error:
JBWEB000065: HTTP Status 404 - /webapp/sessionsetup
JBWEB000309: type JBWEB000067: Status report
JBWEB000068: message /webapp/sessionsetup
JBWEB000069: description JBWEB000124: The requested resource is not available.
Below is my simple code for the servlet:
#WebServlet("/sessionsetup")
public class SessionSetup extends HttpServlet{
private static final Logger log = LoggerFactory.getLogger(SessionSetup.class);
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
log.info(this.toString());
log.info("Do get method is called");
response.setContentType("text/xml");
PrintWriter printer = response.getWriter();
printer.println("<html>");
printer.println("<head>" + "</head>");
printer.println("<body>");
printer.println("<h1>" + "Welcome! You are in session setup" + "</h1>");
printer.println("</body>");
printer.println("</html>");
printer.close();
}
}
Could anyone comment on where I might miss something? Is there a way to find some log information no this error? I tried to look for server.log at /standalone/log but couldn't find anything.
There can be 2 reasons
(1) you can configure your standalone.xml in jboss server
virtual-server name="default-host" enable-welcome-root="false">
use false instead of true in enable-welcome-root
(2)
you have not done mapping of controller properly
Problem resolved. It appears to be an issue with the web.xml - once this is removed, the servlet is available.
The actual problem should be the way how it was deployed(Run time name) in the jboss.
So if you try to access the application on that it should works.
Runtime Name: Name by which the deployment should be known within a server's runtime. This would be equivalent to the file name of a deployment file, and would form the basis for such things as default Java Enterprise Edition application and module names. This would typically be the same as 'name', but in some cases users may wish to have two deployments with the same 'runtime-name' (e.g. two versions of "foo.war") both available in the deployment content repository, in which case the deployments would need to have distinct 'name' values but would have the same 'runtime-name'.
This is just my experience about how this problem might happen and the way I have solved issue.
This problems happens in the absence of war file. When I deployed
hawtio
to monitoring jboss which it needs
jolokia
so I just download and deployed manually the .war file into my jboss then problem has been solved.
I think you have to add WEB-INF/jboss-web.xml file in which you have set the context root
<jboss-web>
<context-root>contextroot</context-root>
</jboss-web>
Clean Server to solve this problem in many cases work..

Controller/Routing Errors with js, img files using a CommonServiceLocator ControllerFactory

I've set up an ASP.NET MVC RC2 application to use a custom controller factory backed by a CommonServiceLocator (using StructureMap). Routing to and instantiating controllers works fine, but for some reason I'm getting exceptions when trying to access .js, .jpg, or any other static file.
Here's the ControllerFactory code:
public class CommonServiceLocatorControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(Type controllerType)
{
return (controllerType == null) ?
base.GetControllerInstance(controllerType) :
ServiceLocator.Current.GetInstance(controllerType) as IController;
}
}
And the exception is:
The controller for path '/someimage.jpg' could not be found or it does not implement IController.
How can I get the factory or routing engine to bypass the controller factory?
Note: I'll be using IIS7/Integrated Mode, but the error occurs with the built in web server for VS2K8.
The problem was actually due to 404 errors- the path I was requesting for the static content didn't exist, and the base controller factory couldn't handle the request because there was nothing to deliver.
I very much doubt this has anything to do with the ControllerFactory. I've just looked at the source code for DefaultControllerFactory.GetControllerInstance, and I can see no means by which this override could cause the error that you are describing. It is probably due to the way you have configured your routes. Take a look at your routing configuration, write unit tests for it, and if you still can't solve the problem, post your routes here.

Resources