how to call a sling servlet through osgi bundle inside CQ5 - servlets

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 !!!

Related

Spring MVC Java WebMvcConfigurerAdapter.addResourceHandlers

I'm looking at a project with the following Java Configuration file:
#Configuration
#EnableWebMvc
#ComponentScan("spittr.web")
public class WebConfig extends WebMvcConfigurerAdapter {
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
super.addResourceHandlers(registry);
}
}
The project has some static resources in the webapps/resources directory that are being served up. My question is I'm not sure why. It seems for this to work, the above call to addResourceHandlers(...) should be
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources");
}
I tried to look for something in the Spring documentation possibly indicating default values but could not, so I'm not sure why the project works.
The project can serve static resources thanks to DefaultServletHandlerConfigurer:
Configures a request handler for serving static resources by forwarding the request to the Servlet container's "default" Servlet.
I use Jetty in the following example, but other servlet containers (e.g. Tomcat) should behave similarly. Download the Jetty 9 distribution, then inside webapps, create these files:
example/
hello.txt
Start the Jetty server. We have deployed the simplest application imaginable. You should be able to access the file at:
http://localhost:8080/example/hello.txt
The servlet container can serve static resources without any extra configurations. This behavior is suppressed as soon as Spring MVC comes into play. Spring MVC will create a front controller, DispatcherServlet, and park it at "/". Every incoming request will go through this single servlet, and the servlet will find the appropriate component in the app to actually process the request (e.g. a #RequestMapping method in a #Controller class). If no handlers for the request can be found, we have 404s.
The handler DefaultServletHandlerConfigurer has the lowest precedence. If enabled, it allows the front controller to handle the request first. When that fails, it forwards the request to the servlet container, where the request is treated as a static resource read.
This is a quick and dirty way of serving static files. In practice, you don't want anything off the beaten path to be available via a GET. You want to allow only specific files and folders, and you would use WebMvcConfigurerAdapter.addResourceHandlers().

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

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..

NoClassDefFoundError accessing jackrabbit jar from servlet

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.

Resources