Scope of variables in a class implementing webservice - web-services

This may be stupid question, but i want to know the root cause.
I am implementing a simple webservice using jersey. I have declared a global variable i and initialised to 0;
I set i to 10 in sayPlainTextHello() method but when i display i in sayXMLHello() it is still 0 ; What is the reason behind this behavior.
server side code
#Path("/hello")
public class Hello
{
int i = 0;
#GET
#Path("/string")
#Produces(MediaType.TEXT_PLAIN)
public String sayPlainTextHello()
{
i = 10;
System.out.println("string hello");
System.out.println("i in string " + i);
return "Hello";
}
#GET
#Path("/xml")
#Produces(MediaType.TEXT_XML)
public String sayXMLHello()
{
System.out.println("i in xml"+i);
System.out.println("xml hello");
return "<?xml version=\"1.0\"?>" + "<hello> Hello Jersey" + " </hello>";
}
This is my web.xml file
<?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>com.vogella.jersey.first</display-name>
<welcome-file-list>
<welcome-file>home.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class> com.sun.jersey.spi.container.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.spaneos.webservices</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
</web-app>

The default scope of resource classes is per-request (or request scoped). For each request a new resource instance will created to handle that particular request.
You can make your classes singleton scoped, meaning only one object will be created for the entire application, but that may not be desired for a few reasons.
If you do want to make your resource class singleton scoped, then you can just annotate your Hello class with #com.sun.jersey.spi.resource.Singleton
That said, unless you have a direct requirement to make the resource class stateful, I would aim to keep the classes stateless.
See more at Life-cycle of Root Resource Classes

Related

How to acess Servlet from Rest web service using Jersey [duplicate]

This question already has an answer here:
Using special auto start servlet to initialize on startup and share application data
(1 answer)
Closed 6 years ago.
I have a Webservice using jersey. I want to access a hashmap which is created in a servlet from rest service. That hashmap in servlet sholud be created only once during application startup.
this is 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>GrpService_Map</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>jersey-serlvet</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.ericsson.mapService</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
Service class TestSErvice is within com.ericsson.mapService package .My question is where will I place the required servlet that creates the hashmap and how will I access that map from TestSErvice ?
This is my service class TestService.java
#Path("/Service")
public class TestService {
#GET
#Consumes("application/xml")
#Produces(MediaType.TEXT_PLAIN)
#Path("/cacheserviceTestMap")
public String createGroupCache(#Context HttpServletRequest request)
throws IOException {
//here i want to access the IndexMap hashmap
return "Success";
}
}
This is my servlet class
public class TestSerlvet extends HttpServlet{
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException
{
Map<String, Map<String,List<String>>> IndexMap = new HashMap<String, Map<String,List<String>>>();
Map<String,List<String>> signumMap = new HashMap<String,List<String>>();
List<String> grp = new ArrayList<String>();
grp.add("1");
grp.add("2");
signumMap.put("eab", grp);
signumMap.put("eabc",grp);
signumMap.put("exy",grp);
IndexMap.put("I", signumMap);
}
}
Thank you
The servlet should be initialized (and mapped) in web.xml with load-on-startup set to a lower value than that of jersey-servlet in order for it to be loaded during container startup before any REST call can be serviced. The servlet's doGet method's IndexMap local variable should be converted into a static field of the servlet which can be publicly accessed. The initialization of that field should occur in the servlet's init() method in order to ensure that the HashMap is initialized before any REST endpoint can access it.
Once the above is done, TestService.createGroupCache() should be able to read the already initialized HashMap by calling the static getter method of the servlet.

securing ,html with jetty and shiro due to caching

i am having issues securing my .html files with shiro.
my app is .html/jquery with rest calls.
user hit landing page redirects to /secure/index.html
user logs in.
user redirected to secure page /secure/index.html
user logouts and goes to /logout.html (shiro confirms logout)
type in browser address "/secure/index.html" and the page is
displayed despite being logged out.
at step5. the access,log is not showing any activity.
according to chrome developer tools the page is loading from cache.
the issue seems to be the browser is not reloading the page and hence shiro filter never gets to fire, and the contents of the secure html file is visible.
it is very evident that the browser cache bypasses the shiro auth.
only if i Ctl+F5 refresh will the page be reload from jetty and security is activated.
shiro.ini
======================
authc.loginUrl = /login.html
authc.usernameParam = username
authc.passwordParam = password
authc.rememberMeParam = remember
logout.redirectUrl = /logout.html
Solution #1
my solution was to force the browser to have a 'no-cache'on the .html files.
however i want cache control for my static content.
i know the DefaultServlet can do this so i created another 2 instances of the DefaultServlet (staticDefaultServlet and webDefaultServlet) to server different cache-control headers for my content.
<servlet>
<servlet-name>webDefaultServlet</servlet-name>
<servlet-class>org.eclipse.jetty.servlet.DefaultServlet</servlet-class>
<init-param>
<param-name>cacheControl</param-name>
<param-value>max-age=5,no-store</param-value>
</init-param>
<init-param>
<param-name>pathInfoOnly</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>staticDefaultServlet</servlet-name>
<servlet-class>org.eclipse.jetty.servlet.DefaultServlet</servlet-class>
<init-param>
<param-name>cacheControl</param-name>
<param-value>max-age=604800</param-value>
</init-param>
<init-param>
<param-name>pathInfoOnly</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>staticDefaultServlet</servlet-name>
<url-pattern>/static/**</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>webDefaultServlet</servlet-name>
<url-pattern>/pages/**</url-pattern>
</servlet-mapping>
however the cache headers are not coming thru.
Questions
Q1. can i use multiple instances of DefaultServlet to have different each control for different paths?
Q2. Is there another mechanism to protect .html files with shiro?
thanks
-lp
this is too difficult.
i abandoned the defaultservlet solution and instead used a Filter to manage my cacheControl for different paths.
public class CacheControlFilter implements Filter
{
String cacheControl;
//#Override
public void init(FilterConfig filterConfig) throws ServletException
{
cacheControl = filterConfig.getInitParameter("cacheControl");
}
//#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
if (response instanceof HttpServletResponse)
{
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.addHeader("Cache-Control", cacheControl);
}
chain.doFilter(request, response);
}
and deployed in web.xml
<filter>
<filter-name>WebCacheControlFilter</filter-name>
<filter-class>com.asteriski.itaxreport.filter.CacheControlFilter</filter-class>
<init-param>
<param-name>cacheControl</param-name>
<param-value>no-cache, no-store, must-revalidate</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>WebCacheControlFilter</filter-name>
<url-pattern>/pages/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
-lp

Is it possible to integrate a web service in a spring + JSF project?

I need to establish a connexion between my android client and my spring + JSF server
I need to send files from my android client and receive them in the server side
for that, i tried to send the file directly to a bean which contains this function
#Component
#Scope("request")
#Path("/file")
public class RestWebService {
#POST
#Path("/upload")
#Consumes(javax.ws.rs.core.MediaType.TEXT_PLAIN)
public String uploadFile(
#FormParam("file") InputStream uploadedInputStream,
#FormParam("file") FormDataContentDisposition fileDetail,
#QueryParam("inputFileName") String inputFileName) throws FileNotFoundException{
System.out.println("start upload");
System.out.println(fileDetail.getFileName());
return "";
}
and i added to my web.xml this lines:
<display-name>Restful Web Application</display-name>
<servlet>
<servlet-name>jersey-serlvet</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.test.WebService</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
but it seems that JSF block the connexion
i want to know if it is possible to continue in this way or i must change this solution and in this case how ??
JSF not blocking REST access url. You need just properly configuration.
You can have a look JSF/REST project which is run under wildfly, you can access REST via url within JSF application, please have a look
https://github.com/armdev/wildfly-jsf2.3-web

Embed Jetty loading web context issue

I want to load a web context not by xml, but configure programatically.
If I use the method setwar(), it worked.
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
<web-app id = "DERBYNET_ID">
<servlet>
<servlet-name>H2Console</servlet-name>
<servlet-class>org.h2.server.web.WebServlet</servlet-class>
<init-param>
<param-name>webAllowOthers</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>H2Console</servlet-name>
<url-pattern>/console/*</url-pattern>
</servlet-mapping>
</web-app>
But, I want to remove webapp. becasuse it has a xml only. So, I want to set the servlet programmatically like below.But, it's not working. I can't see the error log on the console when I run application. But, If I connect the web page, it gives 503 status code. Why this source code doesn't work??
ServletHandler servletHandler = new ServletHandler();
ServletHolder holder = new ServletHolder("H2Console", (Class<? extends Servlet>) WebServlet.class);
holder.setInitOrder(1);
holder.setInitParameter("webAllowOthers", "true");
ServletHolder[] holders = { holder };
ServletMapping servletMapping = new ServletMapping();
servletMapping.setServletName("H2Console");
servletMapping.setPathSpec("/console/*");
ServletMapping[] servletMappings = {servletMapping};
servletHandler.setServlets(holders);
servletHandler.setServletMappings(servletMappings);
derbyWebapp.setServletHandler(servletHandler);

Why is my local website unable to access my local REST service?

I have a Spring MVC REST service running locally through Tomcat on port 8080. When I hit the service directly through the browser or fiddler, it works as expected. I also have a local website built with AngularJS. If I place this website in the Tomcat directory and navigate to the website's link served by Tomcat, everything still works fine.
The problem is when I don't place the website in the Tomcat directory. Say I place the website project on my desktop and navigate to a page that is supposed to retrieve data from the local REST service... I can see in fiddler that the request is going through, hitting the service, and the service returns the data... but the website doesn't display it!
Why would it work fine only when both are served by Tomcat?
Link to hit service directly:
http://localhost:8080/CPProject/users (returns all the users, in JSON format)
Website (this works):
http://localhost:8080/CPWebsite/app/#/users
Website (doesn't work):
http://localhost:63342/CPWebsite/app/index.html#/users (63342 is the port used by Webstorm 7.0)
or
file:///C:/Users/someuser/CPWebsite/app/index.html#/users
My Angular controllers look like this:
cpControllers.controller('UserListCtrl',
function($scope, $http) {
$http.get('http://localhost:8080/CP/users')
.success(function(data) {
$scope.users = data;
}
)
}
);
I've also created a CORS filter in my Sprint MVC service:
#Component
public class SimpleCORSFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS, HEAD");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "X-PINGOTHER, Origin, X-Requested-With, Content-Type, Accept");
chain.doFilter(req, res);
}
public void init(FilterConfig filterConfig) {}
public void destroy() {}
}
You'll need to add correct configured CORS filter to your app that allows preflight requests. Here's an example configuration:
<filter>
<filter-name>CORS</filter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
<init-param>
<param-name>cors.allowGenericHttpRequests</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>cors.allowOrigin</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.allowSubdomains</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>cors.supportedMethods</param-name>
<param-value>GET, HEAD, POST, PUT, DELETE, OPTIONS</param-value>
</init-param>
<init-param>
<param-name>cors.supportedHeaders</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.supportsCredentials</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>cors.maxAge</param-name>
<param-value>3600</param-value>
</init-param>
<init-param>
<param-name>cors.tagRequests</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CORS</filter-name>
<url-pattern>/api/*</url-pattern>
</filter-mapping>
Thanks for the answers above. It turns out my CORS filter was fine, but I had forgotten to add it to my application initializer in order for the filter to actually work:
public class WebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) {
WebApplicationContext rootContext = createRootContext(servletContext);
configureSpringMvc(servletContext, rootContext);
FilterRegistration.Dynamic corsFilter = servletContext.addFilter("corsFilter", SimpleCORSFilter.class);
corsFilter.addMappingForUrlPatterns(null, false, "/*");
}
See here for more info: http://jpgmr.wordpress.com/2013/12/12/cross-origin-resource-sharing-cors-requests-with-spring-mvc/