Redirect the servlet request to another servlet - java

In our app for all the notification we trigger through mail.
All the templates have non sso link
>/Userlogin?param1=param2value&param2=param2value">Link to access app
I need to modify this link in all templates to
>/Userloginsso?param1=param2value&param2=param2value">Link to access app
Since there are many templates and takes lot of manual effort, is there any way we can redirect the request of Userlogin to Userloginsso. Any configuration that we can do in web.xml ?

Considering you have a mapping for Userlogin in web.xml as below:
<web-app>
<servlet>
<servlet-name>Userlogin</servlet-name>
<servlet-path>com.something.Userlogin</servlet-path>
</servlet>
<servlet-mapping>
<servlet-name>Userlogin</servlet-name>
<url-pattern>/Userlogin</url-pattern>
</servlet-mapping>
</web-app>
Modify existing mapping to :
<web-app>
<servlet>
<servlet-name>Userloginsso</servlet-name>
<servlet-path>com.something.Userloginsso</servlet-path>
</servlet>
<servlet-mapping>
<servlet-name>Userloginsso</servlet-name>
<url-pattern>/Userlogin</url-pattern>
</servlet-mapping>
</web-app>
Now all calls to Userlogin will be redirected to Userloginsso servlet.

You could do a simple redirect in your UserLogin servlet with the following:
public void doGet (HttpServletRequest request, HttpServletResponse response) throws IOException {
String param1 = request.getParameter ("param1");
String param2 = request.getParameter ("param2");
// other parameters
// Build the new url: if too much parameters, prefer using a StringBuilder over String concatenation for better performances
String baseUrl = request.getContextPath () + "/Userloginsso?param1=" + param1 + "&param2=" + param2;
String encodedUrl = response.encodeRedirectURL (baseUrl);
response.sendRedirect (encodedUrl);
}

If I understand your question correctly you could use a filter example here get the url and foward it somplace else in your app. Or and url rewrite library such us this one
If you still want a servlet you could use a ProxyServlet. There are already many good implementations.
Examples:
Complex proxy servlet with all features
Simple proxy servlet, limited features

Related

About Welcome Page and Accessing Web Service Methods

I have a problem with configuration ( or basic understanding how things work at background). I create a JAVAEE project by checking Web application and ReSt api checkbox ( in intellij with glassfish 5.0). I have sample code below which web methods work but welcome page does not work. My web.xml and sample web service methods are below.
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>test</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
**<url-pattern>/ *</url-pattern>**
</servlet-mapping>
#Path("/RestTest")
public class TestString {
#Context
ServletContext context;
#GET
#Path("insertdb/{param1}/{param2}")
#Produces(MediaType.APPLICATION_JSON)
public Object writeToDb( #PathParam("param1") String param1
,#PathParam("param2") String param2){
try{
String password= context.getInitParameter("DbPassword");
Class.forName("org.mariadb.jdbc.Driver");
Connection dbCon = DriverManager.getConnection(
"jdbc:mariadb://xxx/testdb", "root", password);
PreparedStatement stmt=dbCon.prepareStatement(
"INSERT INTO TestTable VALUES(?,?)");
stmt.setString(1,param1);
stmt.setString(2,param2);
stmt.executeUpdate();
dbCon.close();
return "Success";
}catch(SQLException | ClassNotFoundException ex){
return ex.toString();
}
}
#GET
#Path("sum/{sum1}/{sum2}")
#Produces(MediaType.TEXT_HTML)
public String calculateSum(#PathParam("sum1") int param1
,#PathParam("sum2") int param2){
return ""+(param1 + param2);
}
If i change this line url-pattern "/*" to "/"
then welcome page is accessible but not methods.
Thus what i want is, having a welcome page which i will use for documentation for my web services(i dont want SOAP) and web methods must work by adding / to base url. How can i achieve that and what is difference between /* and /
See here for explanation of differences:
What is url-pattern in web.xml and how to configure servlet
Generally for a rest api it is best to use a path specific to all rest calls, for instance http://localhost/mywebapp/rest/...
Something like:
<servlet-mapping>
<servlet-name>jersey-servlet/servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
You only want jersey serving particular URLs when it is bundled in a WAR that also includes html pages.
To answer your question, difference between "/" and "/*"
A mapping that contains the pattern "/" matches a request if no other pattern matches. This is the default mapping. The servlet mapped to this pattern is called the default servlet. The default mapping is often directed to the first page of an application. Example :
Both requests will display same contents from index.jsp
http://myhost.com/index.jsp
and
http://myhost.com/
Now, a mapping that contains "/*" overrides all other servlets, including all servlets provided by the servlet container such as the default servlet and the JSP servlet. Whatever request you fire, it will end up in that servlet. This is thus a bad URL pattern for servlets.
Possible solution for your issue
Change the URL pattern to specific instead of default pattern.
<servlet>
<servlet-name>webservice</servlet-name> //servlet name
<servlet-class>com.rest.MyRestServlet</servlet-class> //servlet class
</servlet>
<servlet-mapping>
<servlet-name>webservice</servlet-name> //servlet name
<url-pattern>/RestTest/*</url-pattern> //all webservice request
</servlet-mapping>
All the web service request are accessible through
http://myhost.com/RestTest/
You may also be interested to look
What is URL-pattern in web.xml and how to configure servlet
Basics of Java Servlet
Servlet configuration and url-pattern
As you highlighted, your problem revolves around those four lines:
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
As Jim Weaver mentioned, it's a matter of url-pattern.
Solution(s)
You may consider three solutions (from the most-preferred to least-preferred):
dedicated REST URL: the easiest way is to have a dedicated url-pattern such as /rest/* for your web services. You can benefit some assets such as url hierarchy or you can easily implement a security framework over it.
URL rewriting may be an option and this answer suggests some library. I haven't tested those libraries myself
Page redirection can be an option to go around REST filtering but in the specific case of having the url-pattern at /*, I have to say I'm not sure if it's working for the reason I'll explain in next section
now a bit of explanation of what happened
Why setting the url-pattern at /* prevent from accessing the welcome page?
Actually, it's not only the welcome page that is not accessible: it's all the resources under the defined url-pattern. Whatever get in touch with REST stays with REST... Here is the schema taken from JSR 339 Appendix C:
With a GlassFish 5.0, I guess you're using JAX-RS 2.1 (JSR 370) but the sections I'm quoting have the same content
Without entering into detail, it is visible that only ContainerRequest Filters are executed in the process. Especially, it's worthy to notice that after Request Matching, requests are not forwarded to any servlet in a sense that standard resources are not reachable, unless specified by the REST method.
It's also worthy to highlight the fact the servlet filters are executed beforehand (leveraging this point is absolutely vital for managing security for example). I did not find back the source proving this point but I know it's somewhere on the web ^^.
Request matching is defined at section 3.7.2. In a nutshell, it is in three steps where the first one is the most important for your question, especially at step D:
Identify a set of candidate root resource classes matching the request
c. ...
d. If [the set of classes whose path matches the request URL] is empty then no matching resource can be found, the algorithm terminates and an implementation MUST generate a NotFoundException (404 status) and no entity
e. ...
highlights are mine.
The two last steps are
Obtain a set of candidate resource methods for the request
Identify the method that will handle the request
TL;DR
What happened when you set <url-pattern>/*<url-pattern> and tries to access to your welcome page (or any page actually):
Your server receives the GET request
If there are filters (such those from a security framework), there are executed
REST enters the scene
Pre Match filters are executed (none if your case)
Fetch your root resources classes (in your example, all classes in the test package)
Find if one of those class match the request URL
None are found, a 404 status is returned
To avoid unnecessary URL conflicts, the best options would be having a dedicated URL for your REST methods
If you mention in web xml like following all the request receive by 'Jersey Web Application' servlet. so request to index.jsp also redirect to 'Jersey Web Application' servlet
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
To avoid this add some prefix to the url to separate rest request like following
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>rs/*</url-pattern>
</servlet-mapping>

Spring MVC request mapping conflict

I'm having an issue regarding #RequestMapping on classes. Say I have these two controllers:
#Controller
#RequestMapping(value="/controller1")
public class Controller1 {
#RequestMapping(value="/method11.do")
public #ResponseBody method11(){
//...
}
#RequestMapping(value="/method12.do")
public ModelAndView method12(){
//This method redirects me to another jsp where I'll call Controller2 methods
return new ModelAndView("test");
}
}
#Controller
#RequestMapping(value="/controller2")
public class Controller2 {
#RequestMapping(value="/method21.do")
public #ResponseBody method21(){
//...
}
}
When I first call via AJAX method11, it works fine, the url generated is http://mydomain/myapp/controller1/method11.do
Then, I call method12 and get redirected to test.jsp, and from there, I call to method21, and here is the problem, the url generated is not the expected http://mydomain/myapp/controller2/method21.do, but something else, depending on how I make the AJAX call:
url:'controller2/method21' --> http://mydomain/myapp/controller1/controller2/method21.do
url:'/controller2/method21' --> http://mydomain/controller2/method21.do
So, in what way should I make the calls so that they always start at http://mydomain/myapp/...?
I believe I could just use url:'/myapp/controller2/method21.do', but I guess there should be a more generic way in which I don't have to use 'myapp' on every call.
This is my web.xml:
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
You should make the client aware of the proper URL by retrieving the context root within your script using JSP EL.
In JSP
<script>var ctx = "${pageContext.request.contextPath}"</script>
You can then use ctx as a prefix to the URLs constructed via Javascript.
var url = ctx + "/rest_of_url"
On the server side, you can use:
${pageContext.request.contextPath} or JSTL has a tag, <c:url> which will append your context root.

url pattern syntax (java servlet)

I want to do something like this:
localhost:7001/servlet/character?name=zombies
I tried doing this:
<servlet-mapping>
<servlet-name>zombies</servlet-name>
<url-pattern>/character?name=zombies</url-pattern>
</servlet-mapping>
but it doesn't work and giving me not found error. Any advice or solution on how to do it?
The ?name=zombies portion of your url-pattern should not be used in the web.xml. It is a query parameter that is not actually a part of the servlet mount point. You would need to access the variable name in your zombies servlet via request.getParameter("name").
you are trying to append query string the stuff followed by ? with your URL pattern.
URL pattern is meant to map your servlet class. if you can pass query string in the address bar itself.
If you want to pass a parameter to your servlet then do like this
<servlet>
<servlet-name>zombies</servlet-name>
<servlet-class>com.ZombiesDemo</servlet-class>
<init-param>
<param-name>name</param-name>
<param-value>zombies</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>zombies</servlet-name>
<url-pattern>/character</url-pattern>
</servlet-mapping>
This you can retrive in ZombiesDemo.java servlet as
public void init(ServletConfig servletConfig) throws ServletException{
String name = servletConfig.getInitParameter("name");
}

Java Servlet Web XML URL Mapping

I've been struggling with this web xml file for Tomcat for a while.
<context-param>
<param-name>name</param-name>
<param-value>Bob</param-value>
</context-param>
<servlet>
<servlet-name>test</servlet-name>
<servlet-class>TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>test</servlet-name>
<url-pattern>/servlet/*</url-pattern>
</servlet-mapping>
I know that this file is being read because when i test using
public class TestServlet extends HttpServlet{
public void doGet(HttpServletRequest req, HttpServletResponse res){
res.setContentType("text/html");
String name = getServletContext().getInitParameter("name");
PrintWriter out = null;
try{
out = res.getWriter();
}catch(Exception e){}
out.println("<html><head></head><body><img src=\"/twitter.png\"><p>Hi my name is " + name + "</p></body></html>");
}
}
I am able to read the name I put into the context-param. My question for you guys is how do I create a URL mapping such that I do not have to go through /servlet/ to access my servlets in the URL? When I try to make a url-pattern such as
/test/*, i cannot access the servlet even if i say website/test/TestServlet. I get a 404 Not Found error from the browser
Put the servlet class in a package and do not rely on InvokerServlet. It's disabled since Tomcat 5.5 and removed in Tomcat 7.0.
Please do not read 10~15 year old tutorials/books. Technology changes every year.
See also:
How to invoke a servlet without mapping in web.xml?

GWT + GAE Servlet URL and Servlet Mapping

http://127.0.0.1:8888/socialnetwork/contactsService
That's the current URL for one of my servlets. My question is, how do I change it?
In my web.xml file, altering
<servlet-mapping>
<servlet-name>contactsServiceServlet</servlet-name>
<url-pattern>/socialnetwork/contactsService</url-pattern>
</servlet-mapping>
to
<servlet-mapping>
<servlet-name>contactsServiceServlet</servlet-name>
<url-pattern>/a/contactsService</url-pattern>
</servlet-mapping>
Makes absolutely NO difference to the URL it requests when I make an RPC-call to the servlet.
Once you have done the above you need to change where you invoke (Which is described in the Annotation below) as in...
// The RemoteServiceRelativePath annotation automatically calls setServiceEntryPoint()
#RemoteServiceRelativePath("email")
public interface MyEmailService extends RemoteService {
void emptyMyInbox(String username, String password);
}
See http://google-web-toolkit.googlecode.com/svn/javadoc/1.6/com/google/gwt/user/client/rpc/RemoteServiceRelativePath.html

Categories