cq5 can't create servlet resource - java

I create a servlet in my CQ5 application:
import java.io.IOException;
import javax.servlet.ServletException;
import org.apache.felix.scr.annotations.sling.SlingServlet;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
#SlingServlet(
label = "Example Servlet",
paths = {"/bin/project/signin"},
methods = {"GET"},
extensions = {"html"},
metatype = false
)
public class SignInServlet extends SlingAllMethodsServlet {
private static final long serialVersionUID = 796802690004962223L;
#Override
protected void doGet(SlingHttpServletRequest request,
SlingHttpServletResponse response) throws ServletException,
IOException {
doPost(request, response);
}
#Override
protected void doPost(SlingHttpServletRequest request,
SlingHttpServletResponse response) throws ServletException,
IOException {
response.setContentType("text/plain");
response.getOutputStream().print("Sigin Servlet");
}
}
i try to call it via rest-client but it return:
No resource found for url: http://localhost:4502/bin/project/signin
I also open Sling Resource Resolver at Felix side to test if it available. But i received:
NonExistingResource, path=/bin/project/signin
/bin/ already config in Apache Sling Servlet/Script Resolver and Error Handler at Fellix

In the #SlingServlet annotation you've declared that this servlet supports only requests with .html extension, so you should hit following URL:
http://localhost:4502/bin/project/signin.html
If you don't want to use the extension, remove appropriate parameter from the servlet annotation.

Two ways to help debug this type of situation —
The ServletResolver will allow you to check which Servlet a given GET or POST request will resolve against.
If you find the request you made that generated the 404 in the Recent Requests tab, it should tell you exactly what properties it has found by Sling when trying to resolve it.
E.g. in your case, I presume the 404 is giving something like:
LOG Resource Path Info: SlingRequestPathInfo: \
path='/bin/project/signin', \
selectorString='null', \
extension='null', \
suffix='null'
Comparing this against the settings in your annotation, there's an extension='null' here that wouldn't match against your servlet — which is binding only against a 'html' extension, as Tomek rightly says above.

Related

Servlet error HTTP Status 404 – Not Found Java Tomcat

I know that there were similar problems already, but non of the solutions worked for me. I checked the directories and I edited my `web.xml file a couple of times but it still does not work.
I am writing a simple servlet in Java running on Tomcat and I am getting the error:
HTTP Status 404 – Not Found
Type Status Report
Message /WorkshopForm/MainWorkshopForm
Description The origin server did not find a current representation
for the target resource or is not willing to disclose that one exists.
My servlet class is:
package workshop;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
#WebServlet(description = "This registration form", urlPatterns = {
"/WorkshopForm" })
public class WorkshopForm {
public class MyServlet extends HttpServlet implements Servlet {
private static final long serialVersionUID = 13425L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String participantName = request.getParameter("participantName");
String participantSurname = request.getParameter("participantSurname");
String participantEmail = request.getParameter("participantEmail");
PrintWriter writer = response.getWriter();
writer.println("Welcome" + participantName + " " + participantSurname + " " + participantEmail);
}
}
}
My web.xml:
Tree in Eclipse:
Is it a problem with the web.xml file? I am thinking that maybe I have some mismatch with names or paths but I tried to solved it already and no idea why it is not working.
The URL pattern /WorkshopForm matches only the exact URL path /WorkshopForm. If you want the servlet to also handle longer paths like /WorkshopForm/MainWorkshopForm, you need to change the URL pattern to /WorkshopForm/*. Then you can call request.getPathInfo() in your servlet code to obtain the variable part of the path.
Another alternative is to use some JAX-RS framework to handle the mapping from URL paths to Java methods that handle individual paths.

JAX-RS Multipart with com.sun.jersey

I have a REST service hosted inside Karaf, which is working fine with all requests except for multipart requests. I'm using the com.sun.jersey packages, as I have only succeeded in hosting these inside of Karaf to be accessed over HTTP.
When I try to receive the HttpServletRequest inside the POST and call the getParts() method on it, I get the error:
IllegalStateException: No multipart config for servlet
I have found that I am missing the #MultipartConfig annotation on my servlet, so I added this to the servlet implementation I am using. I extend com.sun.jersey.spi.container.servlet.ServletContainer and add the annotation to that class. But this does not work.
I've also tried using my own extension of the HttpServlet class, that reproduces the error:
#MultipartConfig
public class MultipartServlet extends HttpServlet {
#Override
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
try {
final HttpServletRequest httpRequest = (HttpServletRequest)request;
final Collection<Part> parts = httpRequest.getParts();
System.out.println("There are " + parts.size() + " parts");
}
catch (Exception exception) {
System.out.println("MEGA FAIL");
System.out.println(exception.getMessage());
}
super.service(request, response);
}
}
I've seen the approach using org.glassfish.jersey packages that makes registers the MultiPartFeature class with the ResourceConfig, but I haven't been able to get these packages accessible over HTTP inside of Karaf (the services appear to register without error, but all requests return 404 responses).
Instead of trying to use the Servlet multipart, you just use Jersey's multipart support. In the example in the link, it uses named parts. If you want to be able to process all unknown parts, you can just use FormDataMultiPart as the method parameter. This way you can access all the parts with getFields()
#POST
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response post(FormDataMultiPart multiPart) {
final Map<String, List<FormDataBodyPart>> = multiPart.getFields();
}

Error 404: The requested resource is not available using HelloWorld servlet [duplicate]

This question already has answers here:
Servlet returns "HTTP Status 404 The requested resource (/servlet) is not available"
(19 answers)
Closed 1 year ago.
I am writing a Java Servlet, and I am struggling to get a simple HelloWorld example to work properly.
The HelloWorld.java class is:
package crunch;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class HelloWorld extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
out.println("Hello World");
}
}
I am running Tomcat v7.0, and have already read similar questions, with responses referring to changing the invoker servlet-mapping section in web.xml. This section actually doesn't exist in mine, and when I added it the same problem still occurred.
Try this (if the Java EE V6)
package crunch;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
#WebServlet(name="hello",urlPatterns={"/hello"}) // added this line
public class HelloWorld extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
out.println("Hello World");
}
}
now reach the servlet by http://127.0.0.1:8080/yourapp/hello
where 8080 is default Tomcat port, and yourapp is the context name of your applciation
You definitely need to map your servlet onto some URL. If you use Java EE 6 (that means at least Servlet API 3.0) then you can annotate your servlet like
#WebServlet(name="helloServlet", urlPatterns={"/hello"})
public class HelloWorld extends HttpServlet {
//rest of the class
Then you can just go to the localhost:8080/yourApp/hello and the value should be displayed. In case you can't use Servlet 3.0 API than you need to register this servlet into web.xml file like
<servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>crunch.HelloWorld</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
Writing Java servlets is easy if you use Java EE 7
#WebServlet("/hello-world")
public class HelloWorld extends HttpServlet {
#Override
public void doGet(HttpServletRequest request,
HttpServletResponse response) {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("Hello World");
out.flush();
}
}
Since servlet 3.0
The good news is the deployment descriptor is no longer required!
Read the tutorial for Java Servlets.
this is may be due to the thing that you have created your .jsp or the .html file in the WEB-INF instead of the WebContent folder.
Solution: Just replace the files that are there in the WEB-INF folder to the Webcontent folder and try executing the same - You will get the appropriate output
For those stuck with "The requested resource is not available" in Java EE 7 and dynamic web module 3.x, maybe this could help: the "Create Servlet" wizard in Eclipse (tested in Mars) doesn't create the #Path annotation for the servlet class, but I had to include it to access successfuly to the public methods exposed.
You have to user ../../projectName/Filename.jsp in your action attr. or href
../ = contains current folder simple(demo.project.filename.jsp)
Servlet can only be called with 1 slash forward to your project name..
My problem was in web.xml file. In one <servlet-mapping> there was an error inside <url-pattern>: I forgot to add / before url.

How to define default welcome page in an equinox OSGI server?

We are using OSGI Equinox "org.eclipse.equinox.http.registry.resources" extension to define resources accessible in our different JAR in our OSGI Equinox server. Most of them are just to point to static HTML content so there's no Servlet implementation. I was wondering what was the easiest way to define the default page for a sub folder (defining the "Welcome" file usually defined in a web.xml in standard Servlet packaging). Basically, I define a resource at /mynewresource and would link the user to be directed to index.html when he enters instead of getting a server error.
If you just want to have a default behavior of going to index.html on your resource, you can create that simple filter:
public class WelcomFilter implements javax.servlet.Filter {
/** {#inheritDoc} */
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
/** {#inheritDoc} */
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (request instanceof HttpServletRequest) {
HttpServletRequest r = (HttpServletRequest) request;
if ("/".equals(r.getPathInfo())) {
r.getRequestDispatcher("index.html").forward(request, response);
} else {
chain.doFilter(request, response);
}
} else {
chain.doFilter(request, response);
}
}
/** {#inheritDoc} */
#Override
public void destroy() {
}
}
You have two choices: you can register this filter once at the root (/) but keep in mind that any request with no path info will get redirected to index.html or you can register it for the sub-domain where you want it. In any case, you need to use the equinox http filter extension.
<extension
point="org.eclipse.equinox.http.registry.filters">
<filter
alias="/mydomain"
class="com.abc.filters.WelcomeFilter">
</filter>
</extension>
There is no standardised way yet to define a default (or welcome) page in an OSGi server.
Coincidentally, I faced the same and decided to add this functionality to the Amdatu-Web project. Aside allowing non-Java resources to be served through the web, it now also allows you to define a default page like:
X-Web-Resource-Default-Page: index.html
or a default page for a specific directory:
X-Web-Resource-Default-Page: /path=index.html
The default page(s) will be served in case no file is requested.
It is not entirely done yet, as it needs some reviewing and I need to update the documentation and examples a bit on the Amdatu website. But, you can already take a look at the code (especially the demo project in the BitBucket project) to get an idea of how it should work.
Filters didn't work for me (using Kura/Equinox) however, using a custom HttpContext implementation I was able to add the required logic in getResources.

Does RequestDispatcher work over multiple webapps in one servlet container?

Does RequestDispatcher work over multiple webapps ?
I'm asking because I had a single webapp working fine that uses RequestDispatcher rather than redirects so state isnt lost when displaying error and feedback messages.
However I now need to split some functionality between two webapps, so initial call is made from a webpage hosted on webapp1, calls webapp2 which eventually returns user to a page hosted on webapp1.
Clearly if webapps and webapp2 were on different websites using RequestDispatcher would not be possible but is it if both webapps are deployed within the same instance of a servlet container (tomcat 7)
Update
Got the request dispatcher part to work as explained in answer but am unable to retrieve data put in my webapp2 which iss why Im using it
i.e
webapp2 called , does some processing and then dispatches to a jsp on webapp1
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
HttpSession userSession = request.getSession(true);
String emailAddress = ......
String nextPage = /finish.jsp
userSession.setAttribute("DATA", emailAddress);
ServletContext otherContext = getServletContext().getContext("/webapp1");
otherContext.getRequestDispatcher(nextPage).forward(request, response);
}
webapp2 jsp file contains
...
<p>Email(<%=((String)session.getAttribute("DATA"))%>)</p>
...
but always displays null
Update 2 **
Im wondering if Im misunderstanding what crossContext="true" actually does . Does it make the same HttpSession availble in different webapps, or does it just make the ServletContext from one webap availble to another and hence allow one webapp to see the HttpSessions of another webapp ?
Im starting to think what Im doing is a bad idea as Ive always been keen to use vanilla servlet setups and never want to tie myself to a particular implementation. I think it might help if I explain why I flet the need to split the webapps in the first place.
I had a one webapp (webapp1), that was a website about a product I develop and code for purchasing that product using Google Checkout (now Google Wallet).
I then added created a new webapp for a new product (webapp2).
I then tried to add Google Checkout for new product into webapp2, but realised I couldnt do this easily because Google Checkout requires me to provide it with a url which it can call by application once it has processed payment so that I can then send
user a license. The url was already set to a servlet in webapp1, but
it wouldn't make sense for webapp1 to process payment s for product 2.
One option was to merge webpp1 and webapp2 into one webapp, but this goes against my general view of keeping things modular, it
would also mean evey time I would want to make chnages for one
product Id have to redeploy everything. It also meant big
modifications to webapp1 which I really didnt want to modify as it
was working and stable.
The alternative was to create webapp3 and then google url can point to this, and use this for processing purchases of product 1
and product 2 which is what Ive done. But the problem is when
purchasing product 1 the starting page is in webapp1 , and once
purchase has taken place I want to go back to a page in webapp1, but
only webapp3 has the details of the user who has just made the
purchase which I wanted to display on on the page in webapp1.
This is due to security reasons by default not possible. You need to configure Tomcat first to enable exposing the ServletContext of the current webapp to other webapps. This is to be done by setting the crossContext attribute of context.xml to true.
<Context ... crossContext="true">
Once done that, then you can use ServletContext#getContext() to obtain the other servlet context by its context path and finally use the RequestDispatcher as obtained by ServletContext#getRequestDispatcher() the usual way.
E.g.
ServletContext otherContext = getServletContext().getContext("/otherContext");
otherContext.getRequestDispatcher("/WEB-INF/some.jsp").forward(request, response);
Yes.
The first thing you need to do is get hold of a ServletContext for the other webapp. You do that with ServletContext::getContext on your own ServletContext, passing the context path of the other webapp.
Then, you simply do ServletContext::getRequestDispatcher as normal on the foreign context.
I haven't actually tried this, but i 100% guarantee that it will work.
I am not sure about different servlet container. But it works for same container by using
getServletContext().getContext() method.
First you need to make changes in below file
(Windows) C:\Program Files\Apache Software Foundation\Tomcat 7.0\conf\context.xml
Set value of crossContext to true.
context.xml
<Context crossContext="true">
<!-- Default set of monitored resources -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<!-- Uncomment this to disable session persistence across Tomcat restarts -->
<!--
<Manager pathname="" />
-->
<!-- Uncomment this to enable Comet connection tacking (provides events
on session expiration as well as webapp lifecycle) -->
<!--
<Valve className="org.apache.catalina.valves.CometConnectionManagerValve" />
-->
</Context>
Please note that crossContext="true".
Suppose you have two web applications with name InterServletComm1 and InterServletComm2
having servlets Servlet1 and Servlet1 in each web application respectively. Then the code in each servlets goes as follows:
Servlet1.java
package interServletComm1;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class Servlet1
*/
#WebServlet("/Servlet1")
public class Servlet1 extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* #see HttpServlet#HttpServlet()
*/
public Servlet1() {
super();
// TODO Auto-generated constructor stub
}
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
response.setContentType("text/html");
PrintWriter pw = response.getWriter();
request.setAttribute("name", "WebApp1");
ServletContext context = getServletContext().getContext("/InterServletComm2");
RequestDispatcher rd = context.getRequestDispatcher("/Servlet2");
rd.forward(request, response);
}
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}
}
Servlet2.java
package interServletComm2;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class Servlet2
*/
#WebServlet("/Servlet2")
public class Servlet2 extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* #see HttpServlet#HttpServlet()
*/
public Servlet2() {
super();
// TODO Auto-generated constructor stub
}
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
response.setContentType("text/html");
PrintWriter pw = response.getWriter();
String name = (String) request.getAttribute("name");
pw.println("This is web application 2.");
pw.println("<br>The value received from web application one is: " + name);
}
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}
}
Above code sends attribute name from InterServletComm1 and it is received in InterServletComm2.
Please let me know if this answer is not clear.

Categories

Resources