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

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.

Related

Apache Camel web service using spring

I am very new to Apache Camel an please dont mind if I am wrong at any point.
I have two questions regarding apache camel.
In apache camel examples in internet, I can only see hitting a web service and routing the same to another. How can I call a WebService, unmarshall the object and use in my application instead of routing to another.
In the examples, for calling camel context, we have to call
CamelContext context = new DefaultCamelContext();
context.start()
and
context.stop()
Is there any other way in spring to create a Singleton object in the application context and autowire the bean in my service class in the enterprise project?
Also It will be very helpful if anyone could point me any resources such as pdf or websites that can help me with this.
Just declare camel context as a normal bean
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd">
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<package>my.package.with.routebuilders</package>
</camelContext>
And wire it in your service class
#Autowired
private CamelContext camelContext;
to 1st:
you can create a processor to handle data from your webservice. your processor can be wired to your route builder. your routebuilder could look like the follwoing:
public class MyRouteBuilder extends SpringRouteBuilder {
#Autowired
private MyProcessor myProcessor;
#Override
public void configure() throws Exception {
from("xy")
.process(myProcessor);
}
}
your processor:
public class MyProcessor implements Processor {
public void process(Exchange exchange) throws Exception {
Message msg = exchange.getIn();
//do something with your message
}
}
of course you have to create a bean of your processor. you could do it with annotating it and enable the spring component scan or define it in your spring-context.xml:
<bean class="com.package.of.your.processor.MyProcessor" />
to 2nd:
it is like #Sergey said. you can instanciate your context in your spring config.
with my example your springconfig would look like:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean class="com.package.of.your.processor.MyProcessor" />
<bean id="myRouteBuilder" class="com.package.of.your.routbuilder.MyRouteBuilder" />
<camel:camelContext id="camelContext">
<camel:routeBuilder ref="myRouteBuilder" />
</camel:camelContext>
</beans>

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

Scope of variables in a class implementing webservice

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

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);

Unable to understand web.xml mapping and package definitions

My web.xml is
<servlet>
<servlet-name>SwipeXBackendServices</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.mycompany.backend.webservices</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SwipeXBackendServices</servlet-name>
<url-pattern>/webservices/*</url-pattern>
</servlet-mapping>
Why does the mapping have to be /webservices/* and not com.mycompany.backend.webservices/*.
This is my webservice code
package com.swipex.backend.webservices;
#Path("/Activation")
public class Activation {
private static final Logger log = Logger.getLogger(Activation.class);
private DeviceDetails deviceDetailsTable = DeviceDetails.getInstance();
#POST
#Path("Request")
#Consumes({ MediaType.APPLICATION_JSON })
public Response post(JAXBElement<CDeviceDetails> device) {
Edit : Junit Client Code
#Test
public void testPost() throws Exception {
/*
* Activate
*/
// Initialize Web Services
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
//
// Activation Service
//
URI url = UriBuilder.fromUri(
"http://" + SERVER + "/SwipeXBackEnd/Activation/Request")
.build();
WebResource service = client.resource(url);
System.out.println(url);
// Get the data ready
CDeviceDetails newDevice = new CDeviceDetails(null, "mac id", "model",
"manufacturer", "androidVersion", Calendar.getInstance()
.getTime(), "buildID", "fingerPrint", "board",
"bootLoader", "hardware", "id", "product", "serial", Calendar
.getInstance().getTime(), Calendar.getInstance()
.getTime(), Globals.ACTIVE);
String deviceUniqueIdentity = service.type(MediaType.APPLICATION_JSON)
.post(String.class, newDevice);
assertNotNull(deviceUniqueIdentity);
System.out.println("Activation Passed " + deviceUniqueIdentity);
Url pattern doesn't have any relationship with your java package structure. In your case, you've mapped the SwipeXBackendServices servlet to listen on the '/webservices' url (ex : http://localhost:8080/webservices/). i.e., when a request comes for '/webservices', it'll be routed to your 'SwipeXBackendServices' servlet class.
And also your jax-rs (rest) class 'Activation' is mapped to the url '/activation' (ex : http://localhost:8080/activation).
Mapping of url & class :
/webservices ===> SwipeXBackendServices
/activation ===> Activation
So, don't confuse the package name with the url name.
As Sriram says the servlet mappings have no relation with the packages.
The com.sun.jersey.config.property.packages parameter for the SwipeXBackendServices servlet just tells Jersey which package to scan for discovering REST resources.
The servlet-mapping for the SwipeXBackendServices servlet tells the servlet container on which URLs the servlet will answer. In this case, it will answer to all URLs prefixed with /webservices. Meaning that all REST resources will be prefixed with /webservices.
Then, the URLs for any REST resource will be the concatenation of
The WAR context root
The Jersey servlet mapping
The REST resource path (being itself the concatenation of the class's path and the method's path)
Hence, assuming the context root for your WAR is /myWebApp, the URL for a POST request to your Activation resource will be: http://localhost:8080/myWebApp/webservices/Activation/Request