How can I cache a GET response for 5 hours? - caching

WHAT I WANT
I'm working on a maven-jetty-plugin that uses jersey to map resources. How can I cache the version number for 5 hours so that I don't have to GET it every time the page loads?
MY CODE
Here is the html code that will contain the version number once it is loaded:
...
<footer>
<hr/>
VERSION: <span id="version-container">...Loading...</span>
</footer>
Here is the web.xml with the servlet mapping to 'localhost:8080/rest/':
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>
com.sun.jersey.spi.container.servlet.ServletContainer
</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.resources</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
Here is the java code to handle a GET at 'localhost:8080/rest/version':
/* ... package & imports omitted ... */
#Path("/")
public class RootResource {
#GET
#Path("/version")
#Produces(MediaType.APPLICATION_JSON)
public String versionAsJson(){
return String.format("{ \"version\": \"%s\"}", "v.01");
}
}
Here is the javascript code to load the version after the page loads (using jQuery):
$(document).ready(function() {
$.get("http://localhost:8080/rest/version",
function(response){
$("#version-container").html(response.version);
},
"json"
).error(function(){
$("#version-container").html("[FAILED TO GET VERSION]");
});
}

The Guava library has very nice cache support:
#Path("/")
public class Service {
protected LoadingCache<String, String> cache = CacheBuilder.newBuilder()
.expireAfterWrite(5L, TimeUnit.HOURS).maximumSize(1L)
.build(new CacheLoader<String, String>() {
#Override
public String load(String key) throws Exception {
return String.format("{ \"version\": \"%s\"}", "v.01");
}
});
#GET
#Path("/version")
#Produces(MediaType.APPLICATION_JSON)
public String run() throws ExecutionException {
return cache.get("version");
}
}

Related

getting 404 cannot find requestmapping

need your help,I am getting HTTP Status 404 when access this url
localhost:8080/SurakartaSmart/adm-ser/view-all
below is my controller
#Controller
#RequestMapping("/adm-ser")
public class adminController {
#Autowired
adminService serv;
#RequestMapping(value="/view-all", method=RequestMethod.GET)
public #ResponseBody List<adminModel>viewall()throws Exception{
List<adminModel>data = null;
try{
data = serv.viewall();
}catch(Exception e){
e.getMessage();
}
return data;
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>surakarta-smar</display-name>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
where lies the fault that I need to improve?

JavaEE - Cannot get rid of session

I built web application using JavaEE, JSF and one Servlet.
I use security via Glassfish and web.xml . When I'm logged in I can do whatever I'm allowed to but as soon as I log out the problem happens.
Exactly I logout, I'm redirected to the homepage, in the other (unsecured) pages is the session no longer visible, but as soon as I get into the secured page - here it is named secured.xhtml - I get my session back and I can see my info and do whatever I was allowed to do before once again.
Imo the problem starts at user data constraint in web.xml and
transport guarantee set to CONFIDENTIAL. If I don't set it my informations are not visible on the other pages, but the logout is still not working, if it is set it just shows it on all pages as said before.
This is my web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app
id="WebApp_ID" version="3.1"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<display-name>IssueTrack</display-name>
<!-- Change to "Production" when you are ready to deploy -->
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<!-- Welcome page -->
<welcome-file-list>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
<!-- JSF mapping -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Map these files with JSF -->
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.faces</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>issuetrack-realm</realm-name>
</login-config>
<security-role>
<role-name>User</role-name>
</security-role>
<security-role>
<role-name>Admin</role-name>
</security-role>
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/index.xhtml</location>
</error-page>
<session-config>
<tracking-mode>COOKIE</tracking-mode>
<cookie-config>
<secure>true</secure>
<http-only>true</http-only>
</cookie-config>
<session-timeout>5</session-timeout>
</session-config>
<security-constraint>
<web-resource-collection>
<web-resource-name>Secured pages</web-resource-name>
<description/>
<url-pattern>secured.xhtml</url-pattern>
</web-resource-collection>
<auth-constraint>
<description/>
<role-name>*</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
</web-app>
LogoutServlet which (should) logout logged user.
public class LogoutServlet extends HttpServlet {
#Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// Destroys the session for this user.
HttpSession session = request.getSession(false);
if (session != null) {
session.invalidate();
request.logout();
}
response.sendRedirect("/");
}
}
EDIT
context.xml looks like this
<?xml version="1.0" encoding="UTF-8"?>
<Context antiJARLocking="true" path="/" />
glassfish-web.xml looks like
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-web-app PUBLIC
"-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN"
"http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app error-url="/">
<context-root>/</context-root>
<security-role-mapping>
<role-name>Admin</role-name>
<principal-name>Admin</principal-name>
<group-name>Admin</group-name>
</security-role-mapping>
<security-role-mapping>
<role-name>User</role-name>
<principal-name>User</principal-name>
<group-name>User</group-name>
</security-role-mapping>
</glassfish-web-app>
My Beans all look like this..
#Named
#RequestScoped
public class IssueBean extends BasicBean {
private long id;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
#Inject
private IssueService gServ;
private Issue issue = new Issue();
public List<Issue> getIssues() {
try {
return gServ.viewAll();
} catch (ValidationException ex) {
showException(ex);
return null;
}
}
public Issue getIssueById() {
if (id < 1) {
navigate("/issues.xhtml");
}
try {
issue = gServ.view(id);
} catch (ValidationException ex) {
showException(ex);
}
if (issue == null || issue.getPriority()== null) {
navigate("/issues.xhtml");
}
return issue;
}
public Issue getIssue() {
return issue;
}
public void setIssue(Issue issue) {
this.issue = issue;
}
public String saveIssue() {
try {
gServ.add(issue);
return "/issues.xhtml?faces-redirect=true";
} catch (ValidationException ex) {
showException(ex);
return "";
}
}
public String updateIssue() {
try {
gServ.edit(issue);
return "/issues.xhtml?faces-redirect=true";
} catch (ValidationException ex) {
showException(ex);
return "";
}
}
public void init() {
if (id < 1) {
navigate("/issues.xhtml");
}
try {
issue = gServ.view(id);
} catch (ValidationException ex) {
showException(ex);
}
if (issue == null || issue.getPriority()== null) {
navigate("/issues.xhtml");
}
}
}
Where Basic Bean looks like this
public class BasicBean {
protected void navigate(String where) {
ConfigurableNavigationHandler nav
= (ConfigurableNavigationHandler) FacesContext.getCurrentInstance().getApplication().getNavigationHandler();
nav.performNavigation(where);
}
protected void showException(Exception ex){
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Validation Error - " + ex.getMessage(), ex.toString()));
}
}
I guess this is happening because you are using BASIC auth method in your application which doesn't require cookies, session identifier and login pages, rather uses standard HTTP headers. This means once user is authenticated, each request contains login info, so user is automatically logged in next time he access the site.
So one way to deal with it is to implement Form-Based Authentication. Or if you wish to stick with BASIC - use suggestions given in this thread.
For more info on authentication mechanisms see Java EE tutorial.
I think you are able to use the previous secured pages because the session is being cached by your browser. Include the following as part of the logout so that the response is not cached. This should also work on all browsers.
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);

Jersey HelloWorld throwing 404 error

I'm trying to learn jersey and using this simple example of printing Hello Jersey but when accessing the servlet at http://localhost:8080/testjersey2/hello getting 404 error. Deployed on tomcat 7. What am i possibly doing wrong here ? I dont see any errors in the tomcat logs either.
Hello.java,
package com.nixgadget.jersey;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
//Sets the path to base URL + /hello
#Path("hello")
public class Hello {
// This method is called if TEXT_PLAIN is request
#GET
#Produces(MediaType.TEXT_PLAIN)
public String sayPlainTextHello() {
return "Hello Jersey";
}
// This method is called if XML is request
#GET
#Produces(MediaType.TEXT_XML)
public String sayXMLHello() {
return "<?xml version=\"1.0\"?>" + "<hello> Hello Jersey" + "</hello>";
}
// This method is called if HTML is request
#GET
#Produces(MediaType.TEXT_HTML)
public String sayHtmlHello() {
return "<html> " + "<title>" + "Hello Jersey" + "</title>"
+ "<body><h1>" + "Hello Jersey" + "</body></h1>" + "</html> ";
}
}
In web.xml,
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>testjersey2</display-name>
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<!-- Register resources and providers under com.vogella.jersey.first package. -->
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.nixgadget.jersey</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
Directory structure,

how to handle url that are not mapped in spring

My dispatcher servlet mapping
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/springconfig/dispatcher-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
And the controller has handler like
#RequestMapping("moduleone")
public class ApplicationController {
#RequestMapping(value="Login.html",method=RequestMethod.GET)
public ModelAndView showLoginPage(){
ModelAndView mv=new ModelAndView("../moduleone/Login");
mv.addObject("loginForm", new LoginForm());
return mv;
}
#RequestMapping(value="Home.html", method = RequestMethod.GET)
public ModelAndView showHome(HttpServletRequest request) {
ModelAndView mv=new ModelAndView("Home");
mv.addObject("customerName",appCon.getFirstName() );
return mv;
}
}
Is it possible to handler request that are not mapped in controller
like
http://localhost:8090/Project/moduleone/invalidpage.html
http://localhost:8090/Project/moduleone/invalidurl/invalidpage
I have tried #RequestMapping(value="*",method=RequestMethod.GET) but doest work
As 404 (page not found) actually produces an exception on web container level, containers usually provide an exception handling mechanism, thus you can try exception (or so called error) handling, as shown below;
First create a controller
#Controller
public class PageNotFoundErrorController {
#RequestMapping(value="/pageNotFound.html")
public String handlePageNotFound() {
// do something
return "pageNotFound";
}
}
and configure web.xml in order to map the error to the controller written above;
<error-page>
<error-code>404</error-code>
<location>/pageNotFound.html</location>
</error-page>
you can also extend it by simply adding 403, 500 and other error-codes to web.xml and mapping them to any controller.
What is even more fascinating is that you can also map any exception (even the ones created by your code); here you can find a nice example about it http://www.mkyong.com/spring-mvc/spring-mvc-exception-handling-example/
I try the code block and if change your scenario a bit i can handle it.
//This one is OK
http://localhost:8090/Project/moduleone/invalidpage.html
//add invalid.html not a folder it should be file
http://localhost:8090/Project/moduleone/invalidurl/invalidpage.html
HomeController.java
#RequestMapping(value = {"*/*.html","*.html"}, method = RequestMethod.GET)
public String test(HttpServletResponse response) throws IOException {
return new String("home");
}
dispatcher-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>TestSpringMVC</display-name>
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>SpringDispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/springconfig/dispatcher-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringDispatcher</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
</web-app>
I can handle both request with this way.
I think you should define an exception page for your second scenario.
Also you can read this issue

Cannot perform correctly spring-mvc mapping

I'm developing spring-mvc web-application and I faced some mapping problems:
My web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>Spring MVC Application</display-name>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<welcome-file-list>
<welcome-file>pages/index.jsp</welcome-file>
</welcome-file-list>
</web-app>
My controller:
#Controller
public class MainController {
#Autowired
UserService userService;
#Autowired
PhotosService photosService;
#RequestMapping(method=RequestMethod.GET)
public String loadIndex(Model model)
{
model.addAttribute("firstName", "WWWALTER");
return "index";
}
#RequestMapping(value = "/upload", method = RequestMethod.POST)
public String save( #ModelAttribute("document") PhotosEntity photosEntity,
#RequestParam("file") MultipartFile file) {
Blob blob = null;
try {
blob = new SerialBlob(file.getBytes());
} catch (SQLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// PhotosEntity photosEntity = new PhotosEntity();
photosEntity.setContent(blob);
photosEntity.setFilename(file.getOriginalFilename());
photosService.saveFile(photosEntity);
return "index";
}
Also I have a application name in tomcat 7 -"c2". So should I map with "c2/" prefix?
Can you please help me create correct mapping?
I want to add an attribute in first method and retrieve it in jsp page:
#RequestMapping(method=RequestMethod.GET)
public String loadIndex(Model model)
{
model.addAttribute("firstName", "WWWALTER");
return "index";
}
- but this method isn't invoked.
You can retrieve the attribute like this: ${firstName} from your jsp-page.
Also try changing #RequestMapping(method=RequestMethod.GET) to #RequestMapping(value = "/", method=RequestMethod.GET)
It sounds so stupid. But I just forgot to put
<mvc:annotation-driven />
in servlet context file. Sorry!

Resources