I've created simple jax-ws (anotated Java 6 class to web service) service and deploied it on glassfish v3. The web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app>
<servlet>
<servlet-name>MyServiceName</servlet-name>
<description>Blablabla</description>
<servlet-class>com.foo-bar.somepackage.TheService</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>MyServiceName</servlet-name>
<url-pattern>/MyServiceName</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
</web-app>
There is no sun-jaxws.xml in the war.
The service works fine but I have 2 issues:
I'm using apache common configuration package to read my configuration, so i have init function that calls configuration stuff.
1. How can I configure init method for jaxws service (like i can do for the servlets for example)
2. the load on startup parameter is not affecting the service, I see that for every request init function called again (and c-tor). How can I set scope for my service?
Thanks a lot,
How can I configure init method for jaxws service (like i can do for the servlets for example)
JAX-WS endpoints, both web and EJB, can have optional life-cycle methods that are automatically called if present. Any method can be used as a life-cycle method with the correct annotation:
#PostConstruct - Called by the container before the implementing class begins responding to web service clients.
#PreDestroy - Called by the container before the endpoint is removed from operation
So annotating your init() method with #PostConstruct should do the trick.
the load on startup parameter is not affecting the service, I see that for every request init function called again
Try to use the suggested annotation first. And if you are still facing unexpected behavior, post your code.
Thanks for the quick answer, Pascal.
BTW, I warmly suggest to use a "valid" servlet 2.5 or servlet 3.0 web.xml (using a version attribute in the web-app element and the xsd declaration).
I'm using 2.5 version, I just didn't paste this part in my post
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:j2ee="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.5"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<description>WebTier for the Login Manager Service</description>
<display-name>LoginManagerWAR</display-name>
<servlet>
<description>Endpoint for Login Manager Web Service</description>
<display-name>LoginManagerControllerService</display-name>
<servlet-name>LoginManagerController</servlet-name>
<servlet-class>loginmanager.controller.LoginManagerController</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>LoginManagerController</servlet-name>
<url-pattern>/LoginManagerControllerService</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>54</session-timeout>
</session-config>
The PostConstruct works fine , thank you, but load-on-startup still didn't happen.
#WebService(
name="LoginManagerController",
serviceName="LoginManagerControllerService"
)
public class LoginManagerController {
private ILoginManager manager;
#Resource
private WebServiceContext wsContext;
#PostConstruct
private void init(){
.....
}
More over, now every client request makes 2 init() calls of the webservice:
like I can see in chainsaw, first called init() of the service, then it called again and then the actually client's function (I print the hash code of the webservice class instance and it the same instance for both calls!!!):
> Message Inside init() method ... controller=31641446
> Message login manager = 11229828
> .....init of elements....blablabla.....
> Message Exiting init() method
> Message Inside init() method ... controller=31641446
> Message login manager = 32361523
The controller is the service and the manager (wich hash code has been changed from first call to the second) created inside the init () of the controller.
I failed to understand what is wrong ....
UPDATE
It seems like a to glassfish v3 related issue (maybe my env setup or glassfish configuration). I tried this war on Sailfin and Glassfish V2 and its perfectly working ....
Related
I have an annotated rest controller, like the one below. I'm able to get the services to host fine, but only if I configure the full path for each individual service in web.xml:
#RestController
#RequestMapping("/service/")
public class StuffRestController
{
#RequestMapping("/getStuffList")
public List<Stuff> getStuffList() {
... make stuff ...
return stuffList;
}
... many other similar services ...
}
This is really the only spring resource in my application; although, we are using spring security.
The below are the only lines spring4-servlet.xml:
<mvc:annotation-driven />
<context:component-scan base-package="com.me.stuff.presentation.controller" />
<context:component-scan base-package="com.me.stuff.security" />
The StuffRestController class resides in the "...controller" package.
web.xml:
<servlet>
<servlet-name>spring4</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/spring4-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring4</servlet-name>
<url-pattern>/service/getStuffList</url-pattern>
</servlet-mapping>
All of the above actually all works fine and dandy, but there are 30 other services in this controller and I would rather not make a new servlet mapping for every method. The issue occurs when I attempt to "wildcard" the mapping. I've tried /service/, /service, and /service/*. And many other combinations.
Most all simply don't map properly, and I receive 404 errors. If I use /service/* it will engage the dispatcher servlet when /service/getStuffList is called, but it responds with:
WARNING: No mapping found for HTTP request with URI [/myapp/service/getStuffList] in DispatcherServlet with name 'spring4'
I'm sure this is something simple with how URL mappings are created, but it is eluding me.
The issue is you've included the path: /service/getStuffList in both your DispatcherServlet and the #RestController request mapping. So to access the rest controller method, you've to hit the following URL:
{contextPath}/service/getStuffList/service/getStuffList
So, either change the dispatcher servlet url-pattern to /, so it will handle every request coming to your application, and then based on path after myApp, will redirect to appropriate controller. Or, set the RestController mapping to /*. You should prefer the former approach.
If you want to have your servlet handle request coming at /service, then change the url-pattern to /service/*. But then you've to remove all the request mapping from class level. Else at current scenario, you've to hit the following url:
{contextPath}/service/service/getStuffList
However, if you want to include the dispatcher servlet url-pattern in path resolution (i.e., you want to map the class at /service and also map servlet to that path), you can set alwaysUseFullPath property to true of URL handler mapping. For that, add the following to your spring context xml file:
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name = "alwaysUseFullPath" value = "true" />
</bean>
I'm writing a simple game with JavaEE Websocket technology. Using JSR356, my server-side socket class looks like following:
#ServerEndpoint(
value = "/sock",
decoders = { SocketDecoder.class }
)
public class CardsSocket {
....
#OnMessage
public void onMessage(final SocketInput message, final Session session) {
...
}
...
}
It works perfectly fine, and has no issues. But then I decided to create also some web page for info and stuff. So, without changing anything on previous class, I have created a new one:
#ServerEndpoint(value = "/cards")
public class CardsWebPage extends HttpServlet {
#Override
public void doGet(...) {
...
}
}
And configured web.xml file in WEB-INF directory.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1"
metadata-complete="true">
<servlet>
<servlet-name>CardsWebPage</servlet-name>
<servlet-class>server.CardsWebPage</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CardsWebPage</servlet-name>
<url-pattern>/cards</url-pattern>
</servlet-mapping>
</web-app>
And there began troubles. My servelet works - browser shows page on localhost:8080/cards, but client-side socket class can no longer initiate - it falls with Exception:
"javax.websocket.DeploymentException: The HTTP response from the server [HTTP/1.1 404 Not Found] did not permit the HTTP upgrade to WebSocket"
, and nothing seems to fix it. Have I missed some documentation? Is it impossible for a single project to contain both servlets and websocket classes? Because, if I delete web.xml file, then sockets are starting to work like before. Server startup logs containing no warnings or errors in both cases.
Yeah, perhaps sparks is right, and I should simply deploy multiple projects.
Hi why decorating CardsWebPage with #ServerEndpoint? Nothing or if you can to get rid of web.xml #WebServlet should be fine.
My web.xml looks like this:
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.ajayramesh.jrecycled.servlets.Login</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
I have a class called Login.java with an auto-generated annotation that says:
#WebServlet("/login")
right above my HttpServlet class extension declaration. When this annotation is present, I get the following error when I try to start my server:
The servlets named [LoginServlet] and [com.ajayramesh.jrecycled.servlets.Login] are both mapped to the url-pattern [/login] which is not permitted
I only have one definition in my web.xml and only a single web.xml. When I remove this annotation, the server works fine. To my understanding, annotations are not supposed to have an effect on the runtime of the program, and are only meant to optimize compilation? On a side note, what exactly does that annotation do?
You can't use the same mapping for both annotation and web.xml, you can use either one of it. App server treat it as duplicate url mapping.
Basically, declaring servlet and servlet-mapping elements in web.xml is equal to annotating a servlet class with #WebServlet.
I'm trying to create a WebService stub. I like to react to all of the request in one single place. I have a sample value generator, which handles the type of the request and creates a sample response, so I don't need the code-generation things with a lots of classes. Only a really simple one.
I have found http://jax-ws.java.net/nonav/2.2.1/docs/provider.html WebServiceProvider which is exactly for getting raw SOAP messages, and create a response in a single place.
The main problem is I'm new to this magical EE world :) and I simply can not start WebServiceProvider sample anyway.
I have Spring, SpringSource ToolSuit, Axis installed/configured, all of the other things are working.
Thank you all for your help, and please excuse me if the question is too simple for you. Maybe I just did not find/read something.
M.
Finally I have found the solution (thanks for the help from my workmates).
If you are using JAX-WS, there is a simple solution.
You need a sun-jaxws.xml in your WEB-INF folder containing the following:
<?xml version="1.0" encoding="UTF-8"?>
<endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime" version="2.0">
<endpoint
name="RawWS"
implementation="com.stg.pack.MyServiceProvider"
url-pattern="/HotelServices200631"/>
</endpoints>
And you need a com.stg.pack.MyServiceProvider class which looks like:
package com.stg.pack;
#ServiceMode(value = Service.Mode.MESSAGE)
#WebServiceProvider(portName = "ThePortNameOfWebService",
serviceName = "TheNameOfWebService",
targetNamespace = "http://www.example.com/target/namespace/uri")
public class MyServiceProvider implements Provider<SOAPMessage> {
#Override
public SOAPMessage invoke(SOAPMessage request) {
SOAPMessage result = null;
// create response SOAPMessage
return result;
}
}
And before I forget, you need to define some things in web.xml:
<listener>
<listener-class>
com.sun.xml.ws.transport.http.servlet.WSServletContextListener
</listener-class>
</listener>
<servlet>
<servlet-name>RawWS</servlet-name>
<servlet-class>
com.sun.xml.ws.transport.http.servlet.WSServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RawWS</servlet-name>
<url-pattern>/TheNameOfWebService</url-pattern>
</servlet-mapping>
If you use it like this, all of the request are handled by the invoke method.
you basically must deploy your provider to some sort of Container. developing in J/EE basically mandates that you compile some sort of EAR or WAR or JAR and tell an app server to deploy it (be that app server a JBOSS, glassfish, Weblogic, Websphere, Tomcat, etc).
Have you tried doing this?
it also may be possible to test your provider using the javax.xml.ws.Endpoint class, although I have to admit I've never chosen to per-sue this in favor of deploying to an app server.
Application configuration:
Web application using java first method of creating JAX-WS 2.0 Web Services with annotations.
WebLogic 10.3
My Requirements
The requirements I have are to deploy a single web service implementation class, but change logic based on the URL from which the service was accessed.
Question:
I'm assuming a good way to do this is to deploy different mappings in web.xml and initialize them with different parameters. Is there a better way?
What is the best way to switch logic off the URL from which the web service was accessed? Should I try to configure two servlet mappings in web.xml with initialization parameters (tried, but couldn't get it to work), or should I parse the URL in the service impl? Any other alternatives?
What I've Tried (but didn't work)
I have tried adding the <init-param> in the <servlet> element in web.xml. However, can't get to the ServletConfig object inside the web service to retrieve the param. The web service does not have all the functionality of a standard Servlet (even if I implement Servlet or ServletContextListener). I only have access to the WebServiceContext (it seems) and from there I can only get <context-param> elements--but I would need <init-param> elements instead.
In web.xml, I enter two <servlet> elements using the same Java class, but which map to two different URLs as follows. Notice how the "source" param is different in each Servlet mapping.
<servlet>
<servlet-name>Foo</servlet-name>
<servlet-class>com.Foo</servlet-class>
<init-param>
<param-name>source</param-name>
<param-value>1</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Foo</servlet-name>
<url-pattern>/Foo</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>Bar</servlet-name>
<servlet-class>com.Foo</servlet-class>
<init-param>
<param-name>source</param-name>
<param-value>2</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Bar</servlet-name>
<url-pattern>/Bar</url-pattern>
</servlet-mapping>
You very well may have, but did you try using MessageContext at runtime to determine what the source is?
#WebService
public class CalculatorService implements Calculator
{
#Resource
private WebServiceContext context;
#WebMethod
public void getCounter()
{
MessageContext mc = wsContext.getMessageContext();
// you can grab the HttpSession
HttpSession session = (HttpServletRequest)mc.get(MessageContext.SERVLET_REQUEST)).getSession();
// ...or maybe the path info is enough
String path = mc.get(MessageContext.PATH_INFO);
// the query itself should almost definitely be enough
String query = (String) mc.get(MessageContext.QUERY_STRING);
}
}
I got the idea from http://sirinsevinc.wordpress.com/category/jaxws/. Haven't tried it, though.