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
Related
I'm invoking a web service that requires WS-Addressing SOAP headers. I'm using Apache Camel with CXF to invoke the web service. When I configure the CXF endpoint with the web service's WSDL, it's smart enough to automatically add WS-Adressing SOAP headers, but I need to set a custom MessageId.
Here is the message that is currently being sent:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Header>
<ws:international xmlns:ws="http://www.w3.org/2005/09/ws-i18n">
<ws:locale xmlns:ws="http://www.w3.org/2005/09/ws-i18n">en_CA</ws:locale>
</ws:international>
<fram:user wsa:IsReferenceParameter="true" xmlns:fram="http://wsbo.webservice.ephs.pdc.ibm.com/Framework/" xmlns:wsa="http://www.w3.org/2005/08/addressing">BESTSystem</fram:user>
<Action soap:mustUnderstand="true" xmlns="http://www.w3.org/2005/08/addressing">http://webservice.ephs.pdc.ibm.com/Client/QueryHumanSubjects</Action>
<MessageID soap:mustUnderstand="true" xmlns="http://www.w3.org/2005/08/addressing">urn:uuid:945cfd10-9fd2-48f9-80b4-ac1b9f3293c6</MessageID>
<To soap:mustUnderstand="true" xmlns="http://www.w3.org/2005/08/addressing">https://panweb5.panorama.gov.bc.ca:8081/ClientWebServicesWeb/ClientProvider</To>
<ReplyTo soap:mustUnderstand="true" xmlns="http://www.w3.org/2005/08/addressing">
<Address>http://www.w3.org/2005/08/addressing/anonymous</Address>
</ReplyTo>
</soap:Header>
<soap:Body>
<ns2:queryHumanSubjectsRequest xmlns:ns2="http://wsbo.webservice.ephs.pdc.ibm.com/Client/" xmlns:ns3="http://wsbo.webservice.ephs.pdc.ibm.com/FamilyHealth/">
<!-- stuff -->
</ns2:queryHumanSubjectsRequest>
</soap:Body>
</soap:Envelope>
As you can see, the MessageId value is "urn:uuid:945cfd10-9fd2-48f9-80b4-ac1b9f3293c6". I need to set a custom value.
I tried adding the MessageId header they way I add the other headers like "international" and "user", but some part of the framework overrides the value.
// Note this doesn't work! Something overrides the value. It works for other headers.
#Override
public void process(Exchange exchange) throws Exception {
Message in = exchange.getIn();
List<SoapHeader> headers = CastUtils.cast((List<?>) in.getHeader(Header.HEADER_LIST));
SOAPFactory sf = SOAPFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
QName MESSAGE_ID_HEADER = new QName("http://www.w3.org/2005/08/addressing", "MessageID", "wsa");
SOAPElement messageId = sf.createElement(MESSAGE_ID_HEADER);
messageId.setTextContent("customValue");
SoapHeader soapHeader = new SoapHeader(MESSAGE_ID_HEADER, messageId);
headers.add(soapHeader);
}
The CXF website has some documentation on how to set WS-Addressing headers, but I don't see how to apply it to Apache Camel. The Apache Camel CXF documentation doesn't specifically mention WS-Addressing either.
The documentation links you posted actually do have the information you need, although it's not immediately obvious how to apply it to Camel.
The CXF documentation says that:
The CXF org.apache.cxf.ws.addressing.impl.AddressingPropertiesImpl object can be used to control many aspects of WS-Addressing including the Reply-To:
AddressingProperties maps = new AddressingPropertiesImpl();
EndpointReferenceType ref = new EndpointReferenceType();
AttributedURIType add = new AttributedURIType();
add.setValue("http://localhost:9090/decoupled_endpoint");
ref.setAddress(add);
maps.setReplyTo(ref);
maps.setFaultTo(ref);
((BindingProvider)port).getRequestContext()
.put("javax.xml.ws.addressing.context", maps);
Note that it sets the addressing properties on the "RequestContext".
The Apache Camel documentation says that:
How to propagate a camel-cxf endpoint’s request and response context
CXF client API provides a way to invoke the operation with request and response context. If you are using a camel-cxf endpoint producer to invoke the outside web service, you can set the request context and get response context with the following code:
CxfExchange exchange = (CxfExchange)template.send(getJaxwsEndpointUri(), new Processor() {
public void process(final Exchange exchange) {
final List<String> params = new ArrayList<String>();
params.add(TEST_MESSAGE);
// Set the request context to the inMessage
Map<String, Object> requestContext = new HashMap<String, Object>();
requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, JAXWS_SERVER_ADDRESS);
exchange.getIn().setBody(params);
exchange.getIn().setHeader(Client.REQUEST_CONTEXT , requestContext);
exchange.getIn().setHeader(CxfConstants.OPERATION_NAME, GREET_ME_OPERATION);
}
});
The above example has some stuff we don't need, but the important thing is that it shows us how to set the CXF Request Context.
Put them together and you get:
#Override
public void process(Exchange exchange) throws Exception {
AttributedURIType messageIDAttr = new AttributedURIType();
messageIDAttr.setValue("customValue");
AddressingProperties maps = new AddressingProperties();
maps.setMessageID(messageIDAttr);
Map<String, Object> requestContext = new HashMap<>();
requestContext.put(JAXWSAConstants.CLIENT_ADDRESSING_PROPERTIES, maps);
exchange.getIn().setHeader(Client.REQUEST_CONTEXT, requestContext);
}
// org.apache.cxf.ws.addressing.JAXWSAConstants.CLIENT_ADDRESSING_PROPERTIES = "javax.xml.ws.addressing.context"
// org.apache.cxf.endpoint.Client.REQUEST_CONTEXT = "RequestContext"
Warning: In my route, I invoke multiple different web services sequentially. I discovered that after setting the RequestContext as shown above, Camel started using the same RequestContext for all web services, which resulted in an error: "A header representing a Message Addressing Property is not valid and the message cannot be processed". This is because the incorrect "Action" header was used for all web service invocations after the first.
I traced this back to Apache Camel using a "RequestContext" Exchange property, separate from the header we set, which apparently takes priority over the header. If I remove this property prior to calling subsequent web services, CXF automatically fills in the correct Action header.
if your problem not solved, I suggest you to combine your cxf service with custom interceptor. it easy to work with your soap message. like this:
<bean id="TAXWSS4JOutInterceptorBean" name="TAXWSS4JOutInterceptorBean" class="com.javainuse.beans.SetDetailAnswerInterceptor " />
<cxf:cxfEndpoint id="CXFTest" address="/javainuse/learn"
endpointName="a:SOATestEndpoint" serviceName="a:SOATestEndpointService"
serviceClass="com.javainuse.SOATestEndpoint"
xmlns:a ="http://javainuse.com">
<cxf:binding>
<soap:soapBinding mtomEnabled="false" version="1.2" />
</cxf:binding>
<cxf:features>
<wsa:addressing xmlns:wsa="http://cxf.apache.org/ws/addressing"/>
</cxf:features>
<cxf:inInterceptors>
<ref bean="TAXWSS4JInInterceptorBean" />
</cxf:inInterceptors>
<cxf:inFaultInterceptors>
</cxf:inFaultInterceptors>
<cxf:outInterceptors>
<ref bean="TAXWSS4JOutInterceptorBean" />
</cxf:outInterceptors>
<cxf:outFaultInterceptors>
</cxf:outFaultInterceptors>
</cxf:cxfEndpoint>
and in the interceptor you can set soap headers like this:
public class SetDetailAnswerInterceptor extends WSS4JOutInterceptor {
public SetDetailAnswerInterceptor() {
}
#Override
public void handleMessage(SoapMessage mc) {
AttributedURIType value = new AttributedURIType();
value.setValue("test");
((AddressingProperties) mc.get("javax.xml.ws.addressing.context.outbound")).setMessageID(value);
}
}
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
I am a beginner in JBoss.
I am making a database application that uses JPA. For exposing the same I have to expose a SOAP based web service. I followed the basic JBoss tutorial
http://docs.jboss.org/tools/4.1.0.Final/en/ws_soap_reference/html/topdown.html#bottomupws
to create a web service.
To consume the web service I created a client using the following tutorial.
http://docs.jboss.org/tools/4.1.0.Final/en/ws_soap_reference/html/client.html
But when I am executing this client I am getting a 404 error. The exact same issue is reported on the JBoss community
https://community.jboss.org/thread/164471?tstart=0
My Webservice bean looks something like this:
#WebService(name = "Management", targetNamespace = "http://www.example.org/Management")
public class Management {
#PersistenceContext
private EntityManager em;
#EJB(name = "ejb/ar/ClientEjb", mappedName = "ejb/ar/ClientEjb")
ClientRegistration clientReg;
#WebMethod(action = "http://www.example.org/Management/getAccount")
#WebResult(name = "getAccountResponse", partName = "getAccountResponse")
public String getAccount(
#WebParam(name = "getAccountRequest", partName = "getAccountRequest") String param) {
return "account-56789012354349";
}
#WebMethod(action = "http://www.example.org/Management/addClient")
public List<Client> addClient
(#WebParam(name = "clientId", partName = "clientId") long clientId ){
//For time being let's forget this method.
return null;
}
}
The web.xml has:
<servlet>
<display-name>Management</display-name>
<servlet-name>Management</servlet-name>
<servlet-class>org.jboss.tools.examples.service.Management</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Management</servlet-name>
<url-pattern>/Management</url-pattern>
</servlet-mapping>
The Management.wsdl has:
<wsdl:service name="ManagementService">
<wsdl:port name="ManagementPort" binding="tns:ManagementServiceSoapBinding">
<soap:address location="http://localhost:9090/Management"/>
</wsdl:port>
</wsdl:service>
The ClientSample.java is:
public class ClientSample {
public static void main(String[] args) {
System.out.println("***********************");
System.out.println("Create Web Service Client...");
ManagementService service1 = new ManagementService();
System.out.println("Create Web Service...");
Management port1 = service1.getManagementPort();
System.out.println("Call Web Service Operation...");
System.out.println("Server said: " + port1.getAccount(null));
System.out.println("Server said: " + port1.addClient(0));
//Please input the parameters instead of 'null' for the upper method!
System.out.println("Create Web Service...");
Management port2 = service1.getManagementPort();
System.out.println("Call Web Service Operation...");
System.out.println("Server said: " + port2.addClient(Long.parseLong(args[1])));
System.out.println("Server said: " + port2.getAccount(null));
//Please input the parameters instead of 'null' for the upper method!
System.out.println("***********************");
System.out.println("Call Over!");
}
}
Exception is like below:
***********************
Create Web Service Client...
Create Web Service...
Call Web Service Operation...
Exception in thread "main" com.sun.xml.internal.ws.client.ClientTransportException: The server sent HTTP status code 404: Not Found
at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.checkStatusCode(HttpTransportPipe.java:196)
at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.process(HttpTransportPipe.java:168)
at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.processRequest(HttpTransportPipe.java:83)
at com.sun.xml.internal.ws.transport.DeferredTransportPipe.processRequest(DeferredTransportPipe.java:105)
at com.sun.xml.internal.ws.api.pipe.Fiber.__doRun(Fiber.java:587)
at com.sun.xml.internal.ws.api.pipe.Fiber._doRun(Fiber.java:546)
at com.sun.xml.internal.ws.api.pipe.Fiber.doRun(Fiber.java:531)
at com.sun.xml.internal.ws.api.pipe.Fiber.runSync(Fiber.java:428)
at com.sun.xml.internal.ws.client.Stub.process(Stub.java:211)
at com.sun.xml.internal.ws.client.sei.SEIStub.doProcess(SEIStub.java:138)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:98)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:78)
at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:110)
at com.sun.proxy.$Proxy29.getAccount(Unknown Source)
at org.jboss.tools.examples.service.jaxws.clientsample.ClientSample.main(ClientSample.java:20)
I feel this may be because the service is not getting published, but I can't find I way to publish it.
I am using jboss-as-7.1.0.Final Runtime Server.
Note: Just to see if my Client code is correct I published the bean using
Endpoint.publish("http://localhost:9090/Management", new org.jboss.tools.examples.service.Management());
in the client code itself. The web service could be hit, but this is not in the application context of my application.
Desperately need help here securing a simple Apache CXF web service. Attempts with Spring Security is taking me no where so I need to find a different strategy. This is to implement authorization on a legacy Java service implemented for some of our clients.
This simple Apache CXF web service was created using Maven's cxf-jaxws-javafirst prototype.
It produced a web.xml and beans.xml file and sample code. Besides beans.xml which remains in default state, I have modified these entities as follows:
web.xml:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/beans.xml</param-value>
</context-param>
<context-param>
<param-name>shiroConfigLocations</param-name>
<param-value>WEB-INF/shiro.ini</param-value>
</context-param>
<filter>
<filter-name>ShiroFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ShiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<display-name>CXF Servlet</display-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
and my Shiro.ini file looks like this:
# =======================
# Shiro INI configuration
# =======================
[main]
authc = org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
[users]
o = o, OPERATOR
a = a, ADMIN
s = s, SUPERVISOR
[roles]
SUPERVISOR = *
ADMIN = sayHiAdmin
OPERATOR = deleteAccounts
My simple webservice code is as follows:
import javax.jws.WebService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.Permission;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.subject.Subject;
#WebService(endpointInterface = "org.myCo.com.CxfShiroSecuredService.HelloWorld")
public class HelloWorldImpl implements HelloWorld {
public String sayHi(String text) {
if (isAuthorized("sayHi")) {
return "Successfully said hi " + text;
}
if (hasRole("OPERATOR")){
return "User is OPERATOR";
}
if (hasRole("ADMIN")){
return "User is OPERATOR";
}
throw new UnauthorizedException("Logged user does not have OPERATOR's permission");
}
public String sayHiAdmin(String text) {
if (isAuthorized("sayHiAdmin")) {
return "Successfully said hi Admin " + text;
}
throw new UnauthorizedException("Logged user does not have ADMIN permission");
}
public String deleteAccounts(String text) {
if (isAuthorized("deleteAccounts")) {
return "Successfully deleted accounts " + text;
}
throw new UnauthorizedException("Logged user does not have SUPERVISOR permission");
}
private Boolean isAuthorized(String operation){
Subject currentUser = SecurityUtils.getSubject();
return currentUser.isPermitted(operation); //currentUser.isAuthenticated(); // && currentUser.isPermitted(operation);
}
private Boolean hasRole(String role){
Subject currentUser = SecurityUtils.getSubject();
return currentUser.hasRole(role);
}
}
I have a C# test client that passes authentication information in the SOAP header before invoking webservice like so:
private void OnButtonClick(object sender, RoutedEventArgs e)
{
var client = new HelloWorldClient();
var response = "";
using (new OperationContextScope(client.InnerChannel))
{
var httpRequestProperty = new HttpRequestMessageProperty();
httpRequestProperty.Headers[System.Net.HttpRequestHeader.Authorization] = "Basic " +
Convert.ToBase64String(Encoding.ASCII.GetBytes(UserName.Text + ":" + Password.Text));
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;
try
{
response = client.sayHi("hi " + UserName.Text);
}
catch (TimeoutException tex)
{
response = tex.Message;
}
catch (CommunicationException cex)
{
response = cex.Message;
}
}
TextBox.Text = response;
}
I have used this same strategy for other web services that require Basic authentication
before invoking method calls with success but this service does not seem to be recognizing my credentials. For each method call invoked, regardless of username/password combination, I get the UnAuthorizedException thrown. Can someone shed me some light?
Thanks in advance.
You need a [urls] section in your shiro.ini file. Something like this:
[urls]
/** = authc
Check out the documentation for further details here.
I have deployed a simple hello service in jboss server. I can view the wsdl file. Can someone help me with the client side. I mean how to access this service? Is there any way to access from web browser? Method deployed is
#WebMethod
public String greet( #WebParam(name = "name")
String name )
{
return "Hello" + name;
}
Try to know what is the wsdl url to access the service which you have just exposed. It might most probably be something like "http://localhost: < port-number >/ems-ejb/?wsdl"
If you type the same in the browser, you should be able to see the wsdl file (page with full of xml tags).
Once done, follow the steps provided here
Example on how to call the method once client stub is generated
String endpoint = "your wsdl url";
GreetImplServiceLocator objGreetImplServiceLocator = new GreetImplServiceLocator();
java.net.URL url = new java.net.URL(endpoint);
GreetIntf objGreetIntf = objGreetImplServiceLocator.getFaultImplPort(url);
String greetings=objFaultIntf.greet("stackoverflow");