I have a Servlet/JSP application.
I'm trying to display a customised URL for each Servlet:
Example, i have a servlet "First_step" that does some work, the URL diplayed is
http://localhost:8080/App/Fisrt_step
How can i change it to display http://localhost:8080/App/home
Depends on your web configuration. Are you on servlets 2.5 or 3.1 ? If you are still using 2.5, then you can change your servlet url mapping in your web.xml file located inside WEB-INF:
Your current mapping would look something like this *assuing your servlet class name is also "FisrtStepServlet" (FisrtStepServlet.class):
<servlet>
<display-name>FisrtStepServlet</display-name>
<servlet-name>FisrtStepServlet</servlet-name>
<servlet-class>yourpackage.FisrtStepServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FisrtStepServlet</servlet-name>
<url-pattern>/Fisrt_step </url-pattern>
<url-pattern>/alternativeURL</url-pattern>
</servlet-mapping>
if you are using 3.1, you can change the url mapping of your servlet with annotations.
#WebServlet("/Fisrt_step ") //here you change the servlet URL
public class FisrtStepServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public FisrtStepServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//whatever here
}
}
Related
Is there any other way to configure a context parameter excluding the one which uses web.xml as in the below example?
<context-param>
<param-name>com.sun.faces.numberOfLogicalViews</param-name>
<param-value>10</param-value>
</context-param>
Since Servlet 3.0, you can programmatically set them via ServletContext#setInitParameter().
Just put below ServletContextListener anywhere in your web project. The #WebListener annotation will make the container to automatically pickup and run it during webapp startup.
#WebListener
public class Config implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent event) {
ServletContext servletContext = event.getServletContext();
servletContext.setInitParameter("com.sun.faces.numberOfLogicalViews", "10");
}
#Override
public void contextDestroyed(ServletContextEvent event) {
// NOOP.
}
}
If you're using embedded Tomcat, it is like this:
Context.getServletContext()
.getServletRegistrations()
.get("webdavservlet")
.setInitParameter("listings", "true");
I do have a problem with ServletFiltering and EJB Injection. I've configured a ServletFilter and included it to my web.xml.
Filter-Class:
package at.dot.web.rest.common.utils;
public class AuthRequestFilter implements Filter {
#EJB
private RequestValidator rv;
#Override
public void doFilter(ServletRequest servletRequest,
ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
AuthRequestWrapper wr = new AuthRequestWrapper((HttpServletRequest) servletRequest);
if (rv.isRequestAccepted(wr)) {
filterChain.doFilter(wr, servletResponse);
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void destroy() {
}
}
web.xml:
<filter>
<filter-name>AuthRequestFilter</filter-name>
<filter-class>at.dot.web.rest.common.utils.AuthRequestFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AuthRequestFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Everthing looks great and works without any problem. I now do wanted to make the whole thing a little much more flexible and came to this article:
How to add filters to servlet without modifying web.xml
I added that GodFilter including the FilterChain and the Pattern as suggested in the answere. Thats working pretty well. Filter is called as defined. What my problem is: The EJB (rv) is not injected. It's always null for me.
I'm pretty sure I'm missing any (simple) issue - but nevertheless I do not find the mistake.
Any ideas?
Thanks in advance
So i fixed the issue by myself:
#Stateless
#LocalBean
#RequestScoped
public class AuthRequestFilter implements Filter { .. }
#RequestScoped
public class MasterFilter implements Filter {
#EJB(beanName = "AuthRequestFilter")
private AuthRequestFilter arf;
..
}
Of course new AuthRequestFilter() does not inject the EJB - I do have to inject the filter.
I'm using the servlet which redirects me with the help of
dispatcher.forward(request, response);
in the end. But after this I want to get the page(path) from which I was redirected to use it in next servlet command(to go to previous page). How could I get it?
Or previous URL is not contained in request parameters and I should add it myself?
Will be very grateful for your help.
String referer = request.getHeader("Referer");
response.sendRedirect(referer);
SEE:
Link to forum answer
Try using
request.getAttribute("javax.servlet.forward.request_uri")
See
https://tomcat.apache.org/tomcat-9.0-doc/servletapi/constant-values.html
and
How to get the url of the client
Any method will return source URL when you do forward(..) so my solution is to define a filter to store the requestURL() in a request attribute to check later. To do this in your web.xml write:
...
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>my.package.CustomFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>
...
Then in CustomFilter class:
public class CustomFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {}
#Override
public void destroy() {}
#Override
public void doFilter(ServletRequest req, ServletResponse rsp,
FilterChain chain) throws IOException, ServletException {
req.setAttribute("OriginURL", req.getRequestURL().toString());
chain.doFilter(req, rsp);
}
}
Then you can get it everywhere in your code with ServletRequest object with:
request.getAttribute("OriginURL").toString();
you can store that url in HttpSession and retrieve it in next servlet when you need.
I have the following servlet:
public class MyServlet extends HttpServlet {
private static final long serialVersionUID = 16252534;
private static int ping = 3000;
private Thread t;
private static boolean shouldStop = false;
#Override
public void init() throws ServletException {
super.init();
t = new Thread(new Runnable() {
#Override
public void run() {
while(!shouldStop) {
System.out.println("Now:" + System.currentTimeMillis());
try {
Thread.sleep(ping);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
t.start();
}
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
super.doGet(req, resp);
System.out.println("doGet");
PrintWriter out = resp.getWriter();
out.println("<html><h1>It works!!</h1></html>");
}
#Override
public void service(ServletRequest req, ServletResponse resp) throws ServletException, IOException {
super.service(req, resp);
System.out.println("service");
}
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
System.out.println("doPost");
}
#Override
public void destroy() {
super.destroy();
System.out.println("Destroy servlet");
shouldStop = true;
}
}
Which is mapped as follows in my web.xml:
<display-name>MyServer</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>com.myserver.MyServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/MyServlet</url-pattern>
</servlet-mapping>
When I open my browser (Chrome) on http://localhost:8080/MyServer/MyServlet, then I see "service" from doService() being logged on console and my thread works correctly, however I don't see "It Works" from doGet() being logged and I get the following error in the browser:
HTTP method GET is not supported by this URL
How is this caused and how can I solve it?
This is the default response of the default implementation of HttpServlet#doXxx() method (doGet(), doPost(), doHead(), doPut(), etc). This means that when the doXxx() method is not properly being #Overriden in your servlet class, or when it is explicitly being called via super, then you will face a HTTP 405 "Method not allowed" error.
So, you need to make sure that you have the doXxx() method properly declared conform the API, including the #Override annotation just to ensure that you didn't make any typos. E.g.
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// ...
}
And you also need to make sure that you don't ever call super.doXxx() in your servlet method:
super.doGet(request, response);
Your servlet has this. Just get rid of this line and your problem shall disappear.
The HttpServlet basically follows the template method pattern where all non-overridden HTTP methods returns this HTTP 405 error "Method not supported". When you override such a method, you should not call super method, because you would otherwise still get the HTTP 405 error. The same story goes on for your doPost() method.
This also applies on service() by the way, but that does technically not harm in this construct since you need it to let the default implementation execute the proper methods. Actually, the whole service() method is unnecessary for you, you can just remove the entire method from your servlet.
The super.init(); is also unnecessary. It's is only necessary when you override the init(ServletConfig), because otherwise the ServletConfig wouldn't be set. This is also explicitly mentioned in the javadoc. It's the only method which requires a super call.
Unrelated to the concrete problem, spawning a thread in a servlet like that is a bad idea. For the correct approach, head to How to run a background task in a servlet based web application?
you have overridden the service method which is responsible to delegate the call to doGet or doPost. see this for more details
Also get rid of super.doxxx(..) calls from each method.
Don't override the service method and you should see, "It Works" from doGet.
I am using Spring 3 with sitemesh. I would like to refer to spring context bean in decorator page defined in sitemesh.
The problem is that SiteMesh filter is working outside the Spring context, so request object on sitemesh decorator jsp page is native HttpServletRequest and not wrapper with useful functions to access context and etc.
Is there a way to somehow configure both spring and sitemesh to have access to Spring context in decorator page?
I had the same issue and solved my problem by using a filter. I created an environment filter that I could use for setting environment data for all requests. Autowire the bean you need to have access too in the filter.
#Component
public class EnvironmentFilter extends OncePerRequestFilter {
#Autowired
Object bean;
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
request.setAttribute("bean", bean); // add bean or just specific properties of bean.
filterChain.doFilter(request, response);
}
}
Configure the filter in web.xml, be sure to use the same pattern for the filter mapping as you have for Sitemesh filter.
<filter>
<filter-name>environmentFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>environmentFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
The attributes set from your filter are now available from your decorator page.
Start by creating a singleton for whatever you fancy, I am just setting a String, but any Class will work:
public class MySiteEnvironment {
private String someConfigurationParameter;
public String getSomeConfigurationParameter() {
return someConfigurationParameter;
}
public void setSomeConfigurationParameter(String someConfigurationParameter) {
this.someConfigurationParameter = someConfigurationParameter;
}
/* SINGLETON */
private static final MySiteEnvironment INSTANCE = new MySiteEnvironment();
private MySiteEnvironment() {
}
public static MySiteEnvironment getInstance() {
return INSTANCE;
}
}
Next you need to inject the value:
<bean id="mySiteEnvironment" class="MySiteEnvironment" factory-method="getInstance">
<property name="someConfigurationParameter" value="myValueOrBean"/>
</bean>
Finally you access it by:
<%# page import="MySiteEnvironment" %>
<% pageContext.setAttribute("env", MySiteEnvironment.getInstance()); %>
Now you can use expression language to access the environment
I'm not aware of a way to do what you're asking, but there's another alternative as well. You can declare the HttpServletRequest in your controller method parameters. Just put the model objects on the request if they need to be available to Sitemesh. The JSP code looks exacty the same whether the backing context is the servlet request or the Spring MVC model.
I resolved this problem reimplementing the sitemesh filter:
#Component
class SitemeshSpringFilter extends PageFilter implements ApplicationContextAware {
ApplicationContext applicationContext;
#Override
public void doFilter(ServletRequest rq, ServletResponse rs,
FilterChain chain) throws IOException, ServletException {
def newRq = new ContextExposingHttpServletRequest(
rq, getApplicationContext(), null);
super.doFilter(newRq, rs, chain);
}
#Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
}
In the web.xml, declare this filter:
<filter>
<filter-name>sitemeshSpringFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>sitemeshSpringFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Now, the sitemesh filter will use ContextExposingHttpServletRequest instead normal request.