ModeShape WebService REST - java

I work on modeshape 3.7.2 and i would like to use its REST API.
First of all i would like to know whether an API exists to Retrieve a list of available nodes in a give workspace?
Second how to interpret the syntax: http://<host>:<port>/<context>
What is <context>?
In the documentation they mention a Reponse format: Does this mean I should change the config.json file ?
Similarly to create a node: http://<host>:<port>/<context>/<repository_name>/<workspace_name>/items/<node_path>
What does the URI parameters stands for:
<context>
<workspace_name>
<node_path>
Here is the link for the URL syntax.
Is there any example for each of above cases?

First, there is no method in ModeShape's RESTful service to return all nodes from a repository. A repository can have millions of nodes with lots of content, so such a request would be make no sense and could have a monstrously-large response. Instead, there are methods to return some/all of the children (or descendants up to some depth) under a parent.
Secondly, the "context" is a term used in servlet-based applications, and typically refers to the location where the application is started within the server. By default this is "modeshape-rest", although you can change it to something else by modifying the web.xml in the WAR file.
The "response format" is typically JSON.
The RESTful service can access multiple repositories deployed in the same server, so in the URL format
http://<host>:<port>/<context>/<repository_name>/<workspace_name>/items/<node_path>
the variables in angle brackts(e.g., "<repository_name>") would be replaced with the actual value. For example, if the RESTful service is accessible on the local machine on port 8080 in the default app context "modeshape-rest" in the repository named "my-repository" with workspace "default", you can get the node at the path "/a/b/c" by making an HTTP GET request at this URL:
http://localhost:8080/modeshape-rest/my-repository/default/items/a/b/c HTTP/1.1
where the actual HTTP request might look like this:
GET /modeshape-rest/my-repository/default/items/a/b/c HTTP/1.1
Host: http://localhost:8080
Accept: application/json
and the response will be a JSON file describing the node. All of the other methods on the RESTful service use a similar pattern and are described in the service documentation.

Related

How does Jersey determine the base URI of an application?

I have a java application running in a tomcat. In one endpoint of the application I want to return a HTTP-response of type See-Other.
#GET
#Path("logout")
#Produces(MediaType.TEXT_HTML)
public Response logOut(#Context HttpServletRequest request) throws URISyntaxException {
// logout logic omitted
Response.ResponseBuilder response = Response.seeOther(new URI("../jsp/login.jsp"));
return response.build();
}
When I test this on my local machine everything works fine. On the production system however jersey seems to be unable to resolve the correct hostname from the relative path "../jsp/login.jsp". Although the host is called myhost the relative path is resolved as http://localhost:7080/myapplication/jsp/login.jsp.
new URI("../jsp/login.jsp") returns an Object where all fields are null and only path="../jsp/login.jsp". For this reason the root of the behavior must be in the Response class. I checked the documentation and figured that Response.seeOther makes a call to the Response.location method. The documentation states that
If a relative URI is supplied it will be converted into an absolute
URI by resolving it relative to the base URI of the application
Does anyone know how Jersey determines the base URI of the application? Is there some config file in the tomcat or an environment variable I set wrong?
The base URI of the application is computed using the properties of the HttpServletRequest object and is of the form:
<scheme>://<serverName>:<serverPort>/<contextPath><servletPath>/
The <serverName> and <serverPort> are usually supplied by the HTTP client, while the rest is fixed by Tomcat's or your application's configuration:
<scheme> is configured using the homonymous attribute of a <Connector> (cf. Tomcat's documentation) or can be set by the RemoteIpValve (cf. documentation),
<serverName> is supplied by the HTTP client, but can be overridden using the proxyName attribute of a connector,
<serverPort> is supplied by the HTTP client, but can be overridden using the proxyPort attribute of a connector or by the RemoteIpValve,
<contextPath> depends on how you deploy your application (e.g. it depends on the name of the WAR file in the webapps directory),
<servletPath> is configured in the web.xml descriptor or through the #ApplicationPath annotation.
What probably happens in your production environment is that Tomcat is behind a reverse proxy. To configure the base URI correctly in such a situation you have two choices:
Statically configure the correct values of scheme, secure, proxyName and proxyPort on your <Connector>,
Use the RemoteIpValve and configure the proxy server to send the original Host header and add the X-Forwarded-For and X-Forwarded-Proto headers.
If your proxy forwards different kinds of requests to Tomcat (e.g. both HTTP and HTTPS requests), the RemoteIpValve is your only choice.
Remark: The base URI can also be based on the request URI if you set the ServerProperties.LOCATION_HEADER_RELATIVE_URI_RESOLUTION_RFC7231 property to true: cf. this question.

Transforming CXF SOAP web-service into a custom HTTP / JSON web-service

I have created a SOAP web-service, running in a tomcat container, using CXF and a WSDL contract approach. The Java code was generated from the WSDL using the maven plugin "cxf-codegen-plugin".
Now, I would like to also expose the web-service as a custom HTTP / JSON web-service by mapping the XML data into JSON data. But I haven't been successful yet and I would appreciate any help to achieve that.
I found that old documentation https://cxf.apache.org/docs/json-support.html on CXF's website (which has also been recently duplicated and not corrected here https://cwiki.apache.org/confluence/display/CXF20DOC/JSON+Support). I got it running with a small fix : sf.setBindingId(HTTPBinding.HTTP_BINDING); instead of sf.setBindingId(HttpBindingFactory.HTTP_BINDING_ID); since HttpBindingFactory does not exist anymore in CXF 3.x versions.
The first issue with that solution is that it depends on jettison-json whose last release was published in July 2016. The project looks dead. I could not find any suitable replacement. I only found StAXON which is worst : last release in February 2014.
Is there any other library that is well maintained and that implements StAX ?
The second issue is that the example uses a server bean while I already have a container. For the SOAP service, I simply use the public static Endpoint publish(String address, Object implementor) function.
How can I use both the Tomcat container and the JSON/XML conversion ?
The third issue is that I could not send a valid JSON request so far. The absence of documentation does not help. Still, I managed to get as far as sending a valid JSON equivalent of the SOAP header content. But I could not manage to guess how to make CXF also reads the equivalent of the SOAP body. The Java interface of the web-service is public Response get(Header header, Body body); and I keep getting errors : org.apache.cxf.interceptor.Fault: wrong number of arguments while invoking public abstract Response ServicePort.get(Header,Body) with params [Header#88f6973[user=bbcc2545-27ea-43cd-a1fe-c4a194258e0f]]. Obviously the body is missing.
Is there anyone who knows the right JSON syntax to send a request to a CXF HTTP / JSON web-service that relies on jettison-json ? (Or where could one find a comprehensive documentation ?)

Configuring cxf service listing in karaf

It is a web service deployed on Apache Karaf using camel-cxf. I am able to see the cxf service listing in URL localhost:8181/cxf which has some rest and soap services deployed on it.
The problem is it is returning the service listing whenever any request comes with keyword "services". For example the url http://localhost:8181/abcd/services returns cxf service listing page instead of processing the actual request.
I got to know from http://cxf.apache.org/docs/jaxrs-services-description.html that its is because of the default value of service-list-path of CXFServet is services.
Here is my Question. If I want to override this, I should set this property in etc/org.apache.cxf.osgi.cfg. This cfg file is not present under etc folder in my karaf. What are the steps to be taken if I am creating this property file manually? What features I need to install? Or creating this cfg is sufficient ?
Appreciate your help !
There should be no extra installation requirements, just create a new file etc/org.apache.cxf.osgi.cfg.
There are three settings you may be interested in:
org.apache.cxf.servlet.context = /mycxf
org.apache.cxf.servlet.service-list-path = /myservices
org.apache.cxf.servlet.hide-service-list-page = false
Where the default URL for the CXF service listing is usually like http://localhost:8181/cxf/services, with the changes above the URL would become http://localhost:8181/mycxf/myservices
If you change from false (default value) to true, then your services will be hidden and you will instead get a page stating No service was found.
Because these are initialisation settings you need to shut down Karaf for the changes to apply.
I see several points here --
The CXF framework is installed by default in karaf under the context-path /cxf.
/cxf/services can be considered as a CXF internal app that displays the list of services deployed in CXF. I don't think you can configure the name "services" here (and why would you change that?)
the "url-pattern in web.xml" you speak of (if I understand correctly) determines the context path of your servlet/application. You can specify this is camel like this:
<cxf:rsServer id="secureRsServer" address="https://0.0.0.0:8182/my/path/"
serviceClass="....">
(for the RS Server, probably same for the WS server).

WSDL without endpoint URL

Can a WSDL exist without an Endpoint defined in it? I received an WSDL from client which dont have have endpoint defined.
Just want to know what are the possibilities if it exist somewhere else or in some other relative location etc since I don't have expertise in SOAP services.
To make clear further the WSDL dont have soap:address neither service tag.
It sure can. The same WSDL can be defined for multiple endpoints. You need to ask the client which address(es) to use with that.
You can bind the end point at runtime dynamically even if it has not been defined in the WSDL. Below is the example of javax.xml.ws.BindingProvider. You can configure your end point in DB or configuration file thus it can be changed as per the environment.
((BindingProvider)port).getRequestContext().put(
BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endPoint);

How to get XML file from Java Request object before sending. Web services SOAP

I am building Java application for Online Web Services and let's call it application A . I got the WSDL file form the second party so I can communicate with their application and let's call it application B.
From the WSDL file I generate the Java classes needed which are Requests and Responses classes. Application A will send some request object after setting the needed parameters and excepting response object from application B.
The connection is established and both applications A and B are communicating with each other.
Question:
From application A how can I get the xml data(file or text) for the request object before sending it to application B?
As described the connection is done by passing Java object as request and I know that in some point this request will be converted to xml file. How to get it?
--- EDIT ----
Important Information is missing that may cause confusion.
I am generated the Java Classed have been generated using Axis framework
I don't have much reputation to post a comment, so here is my answer: If you aren't yet using some framework use Apache CXF, If you want to capture the request before sending it application , you can either use cxf interceptors there are some inbuilt interceptors which can do this or you can create a custom interceptor with correct phase ( e.g. post marshal)
The problem is solved by adding the following statements in the bindingStub class that has been auto generated from the WSDL file for the web-services you are trying to access.
String request = _call.getMessageContext().getRequestMessage().getSOAPPartAsString();
String response = _call.getMessageContext().getResponseMessage().getSOAPPartAsString();
These statements should be placed after the following method call _call.invoke otherwise you will get NullPointerException .
_call is a variable of type org.apache.axis.client.Cal and it is auto generated by Axis

Categories