I want to create a SOAP service method which consume data from URL as query param. But i am not sure, How can we pass data as query param in SOAP URL. I have created the method as below accepting data but that will come from SOAP request:
Also let me know how we would be passing data in the Query param from SOAP UI:
#WebMethod
public String test(String str){
System.out.println("Test method called:"+ str);
return str;
}
It would be very helpful if any of you help me out. Thanks in advance!
The following code uses the Servlet context to obtain the query param(s). I've provided two methods. The first method just uses the numbers passed via the SOAP request. The second method deals with one or more query parameters passed and gives two examples of accessing the query parameters.
package net.myco.ws;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.Resource;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.servlet.http.HttpServletRequest;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;
#WebService
public class SOAPWSWithQueryParam {
#Resource
private WebServiceContext ctx;
/**
* Default no arg constructor
*/
public SOAPWSWithQueryParam() {
super();
}
/*
* Web Service that adds two numbers together
*/
#WebMethod
public int addTwoNumbers(
#WebParam(name="inputNumber1") int inputNumber1,
#WebParam(name="inputNumber2") int inputNumber2
){
int result;
result = inputNumber1 + inputNumber2;
return result;
}
/*
* Web Service that adds two numbers together, *but* also inspects
* the HTTP POST for a single queryParam and adds that as well.
*
* Example URL:
* http://localhost:8080/SOAPWSWithQueryParam/SOAPWSWithQueryParam?number1=8&number2=6
*
* Note, we're only getting the first query param, we could split based on "&" and get
* other params.
*
*/
#WebMethod
public int addThreeNumbers(
#WebParam(name="inputNumber1") int inputNumber1,
#WebParam(name="inputNumber2") int inputNumber2
){
int result;
int queryStringNumber1 = 0;
Map <String, String[]>quesryStringMap;
HttpServletRequest servletRequest = (HttpServletRequest) ctx.getMessageContext().get(MessageContext.SERVLET_REQUEST);
/*
* Likely want to add a try catch on this or other logic in case there isn't a query string param.
* Also, because the example URL contains a second param, we split again at the "&" in URL else the
* result would be "8&number2"
*/
queryStringNumber1 = Integer.valueOf(servletRequest.getQueryString().split("=")[1].split("&")[0]);
/*
* The second and more elegant way of accomplishing it is using the Parameters Map, because we're
* adding the second way of doing it, the returned value is increased as it was 17 based on our URL
* and the WS two input numbers. Now it becomes 31.
*
*/
quesryStringMap = servletRequest.getParameterMap();
Iterator<Entry<String, String[]>> mapIterator = quesryStringMap.entrySet().iterator();
while (mapIterator.hasNext()) {
Map.Entry<String, String[]> pair = (Entry<String, String[]>)mapIterator.next();
System.out.println(pair.getKey() + " = " + pair.getValue()[0]);
/*
* Prints:
07:43:57,666 INFO [stdout] (default task-10) number1 = 8
07:43:57,666 INFO [stdout] (default task-10) number2 = 6
*/
//Add the other param values
queryStringNumber1 += Integer.valueOf(pair.getValue()[0]);
mapIterator.remove();
}
result = inputNumber1 + inputNumber2 + queryStringNumber1;
return result;
}
}
From SOAP UI, after you have created a new SOAP project it would look like this, I've shown two examples (right pane), the first example calls the web service method which just adds the two numbers together passed in the SOAP body as arguments. The second method (bottom) first gets a single query parameter even though their are two, adds that to queryStringNumber1 it then has a second example which uses a iterator to iterate through the parameter map and then adds any passed values to queryStringNumber1. Finally, it adds the soap input variables to queryStringNumber1 and returns that value.
You could also uses the Binding Provider such as purpose of bindingprovider in jax-ws web service and google provides even more examples.
Related
I am working with a microservice architecture where a Zuul gateway contacts a Eureka server to discover published microservices. I want my zuul gateway to accept path in a particular format.
It received a URL call with a member id sent as a token. Because we want to avoid sending sensitive information in URLs, these expirable tokens would be parsed by Zuul, translated to a Social Security Number, for example, and the ssn would be sent in a header.
For example, a bank acct GET:
http://zuulgateway/member/11/account/
would map to
http://microservice/account
X-MEMBER-SSN: 1112223333
My plan is to set up a "pre" Zuul filter to parse out the member token "11" and use it to get the SSN, then add it to the header.
But I'm not sure how I configure this route or if it is even possible.
zuul.routes.account.path: /member/*/**
does not achieve it. Is there some other mechanism I can use?
There are a few forum posts on the Zuul github regarding this issue but none of the solutions were working for me. I couldn't figure out why and finally realized: the hot deployment into Zuul from my Spring Tool Suite was restarting the application, but not deploying the latest changes (perhaps this is an endorsement for JRebel in the end!). Once I realized this I started experimenting with stop/deploy/start coding until I got a solution working with ZuulFilter.
The solution involves a "pre" filter which rewrites the contextURL to remove the /member/\d+/ portion of the URL so that the context can be directly mapped to the
Here is some example code:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
#Component
public class SpecialFilter extends ZuulFilter {
private static final String REQUEST_URI_KEY = "requestURI";
private static final Pattern URL_PATTERN = Pattern.compile("^\\/?(\\d+)\\/(.+)$");
#Override
public boolean shouldFilter() {
return isMember(RequestContext.getCurrentContext());
}
private boolean isMember(RequestContext currentContext) {
String path = (String) currentContext.get(REQUEST_URI_KEY);
Matcher m = URL_PATTERN.matcher(path);
return m.matches();
}
#Override
public Object run() {
RequestContext context = RequestContext.getCurrentContext();
String originalRequestPath = (String) context.get(REQUEST_URI_KEY);
Matcher m = URL_PATTERN.matcher(originalRequestPath);
System.out.println("Parsing original "+originalRequestPath + " against " + URL_PATTERN.toString());
if(!m.matches()) {
System.err.println("Invalid URL");
return null;
}
String ssn = translateSSN(m.group(1));
String requestPath = m.group(2);
String modifiedRequestPath = "/" + requestPath;
context.put(REQUEST_URI_KEY, modifiedRequestPath);
//Add this header to the request
context.addZuulRequestHeader("X-SSN", ssn);
return null;
}
#Override
public String filterType() {
return "pre";
}
#Override
public int filterOrder() {
// Should proceed this filter
return FilterConstants.PRE_DECORATION_FILTER_ORDER + 1;
}
}
The version of Playframework is 1.2.x,and I want to transform the query.ResultList to VO.
I created a Part entity bean as below:
#Entity
#Table(name="evaluation_part")
public class Part extends Model {
public String name;
public String collegeName;
public int peopleNum;
}
The data:
id name collegeName peopleNum
1 Jsj1 JJJJ 32
2 Jsj2 JJJJ 23
3 Jsj3 JJJJ 32
4 Tjb1 TTTT 11
5 Tjb2 TTTT 14
6 Tjb3 TTTT 16
My value object class:
public class PartVO {
public String collegeName;
public int peopleNum;
}
And I want to use the native query to get the result:
String sql="select collegeName,SUM(peopleNum) as peopleNum from evaluation_part group by collegeName";
The query result is:
collegeName peopleNum
TTTT 41
JJJJ 87
I tried:
String sql="select collegeName,SUM(peopleNum) as peopleNum from evaluation_part group by collegeName";
Query query =JPA.em().createNativeQuery(sql);
List<PartVO> partVOs = query.getResultList();
for(int i=0;i<partVOs.size();i++) {
System.out.println(partVOs.get(i).collegeName);
}
Following error is what i am getting
ClassCastException occured : [Ljava.lang.Object; cannot be cast to valueobject.PartVO
You don't have to user raw sql to do that. With hql you can use the new operator to create your VO (see http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/queryhql.html#queryhql-select)
You have to define a two arg constructor in your partVO class, then you can do
select new package.PartVO(collegeName, SUM(peopleNum)) from Part group by collegeName
Solution 1:Only use 'select new Part()'(constructor defined in the Part class) in the HQL that u can convert object to Part.Hibernate use reflection to automatically inject all the fields u need.
Solution 2:Here the returned type of result must be Object[],so that u can got every field of the record fetched from database by the index of array;
The difference between solution1 and solution2:the previous use constructor in the query and the later transform a record into Object[].
In your case,ignore the complex relationship between entities,solutions above will make work.
Referenced Code here:
package controllers;
import play.*;
import play.db.jpa.JPA;
import play.mvc.*;
import java.util.*;
import models.*;
/**
* This demo is intended for fetching data from MYSQL.
* #author dhl#oopsplay.org
*/
public class Application extends Controller {
public static void index() {
render();
}
/**
* Prepare some data to test.
*/
public static void addPart() {
//Add a part record to database.
Part newPart=new Part("software","zjut",8).save();
if(newPart.isPersistent()){
renderText("Add successfully,there are %s records in the \'evaluation_part\' table.For convenience,please click the back button in the browser to go back previous page.",Part.count());
}
}
/**
* Fetch part entities from database;
*/
public static void fetchPart() {
//-------------------Solution 1-------------------
//[Pay attention]:Only use 'select new Part()'(constructor defined in the Part class) in the query that u can convert object to Part.
//Hibernate use reflection to automatically inject all the fields u need.
List<Part> parts1=JPA.em().createQuery("select new Part(name,collegeName,peopleNum) from Part").getResultList();
//For convenience, i output the detail in the console, focus on the change there.
Logger.info("The name of first record is :%s", parts1.get(0).name);
//-------------------Solution 2-------------------
//[Pay attention]:Here the returned type of result must be Object[],so that u can got every field of the record fetched from database;
List<Object[]> parts2=JPA.em().createNativeQuery("select name,collegeName,peopleNum from evaluation_part").getResultList();
Logger.info("The name of first record is :%s", parts2.get(0)[0]);
for(int i=0;i<parts2.size();i++){
//The difference between solution1 and solution2:the previous use constructor in the query and the later transform a record into Object[].
Logger.info("Name from parts1 is: %s", parts1.get(i).name);
Logger.info("Name from parts2 is: %s", parts2.get(i)[0]);
}
renderText("There are %s record in the \'evaluation_part\' table",parts2.size());
}
}
You can use the version of createNativeQuery(...) method that also accepts as argument the Class of the result instance(s):
http://docs.oracle.com/javaee/6/api/javax/persistence/EntityManager.html#createNativeQuery(java.lang.String, java.lang.Class).
However make sure this actually works, as Play Framework doesn't implement all the features of JPA in it's implementation of the API.
I am in very bad situation, I got the objectiveC classes from the sudzc website.
using "http://www.xxx.in/mstore/api/soap/?wsdl"
in "SDZMagentoServiceExample.m" class I get one method
[service call:self action:#selector(callHandler:) sessionId: #"" resourcePath: #"catalog_category.level" args: (id)args];
It always gives me parameter error like
"Invalid website code requested:" if I pass dictionary or array in the args.
Please help me, I am in very bad situation.
thanks in advance.
From
/**
* Catalog category api
*
* #category Mage
* #package Mage_Catalog
* #author Magento Core Team <core#magentocommerce.com>
*/
class Mage_Catalog_Model_Category_Api extends Mage_Catalog_Model_Api_Resource
{
Following code:
/**
* Retrieve level of categories for category/store view/website
*
* #param string|int|null $website
* #param string|int|null $store
* #param int|null $categoryId
* #return array
*/
public function level($website = null, $store = null, $categoryId = null)
{
So nor array, nor dictionary would be accepted. Only raw string or int value.
I will not be able to help you in Objective C code, but I can show you some light with PHP. You can try out this type of call:-
$proxy = new SoapClient('http://www.iphone5case.in/mstore/api/soap/?wsdl');
$sessionId = $proxy->login('apiUser', 'apiKey');
/**
* As defined in the "Manage Stores" section of Admin panel,
* where you need to use the specific Website Code and/or Store Code
*/
$websiteCode = null;
$storeCode = 'german';
// Parent Category ID
$parentCategoryId = 2;
$firstLevel = $proxy->call($sessionId, 'category.level', array($websiteCode, $storeCode, $parentCategoryId));
Now if you print this variable "$firstLevel", you will get your required output, from this Web Service API.
Also whenever you are using Magento SOAP API v1, then each of the arguments will need to be as an array element. In this case, following are the main parameters expected for this API call "category.level":-
Website Code or ID
Store View Code or ID
Parent Category ID
So you need to create an array, and put sequentially each of the above arguments as array elements, like:-
array(
$websiteCode,
$storeCode,
$parentCategoryId
)
Lastly, please make sure that you reference this article always, as you can get the usage of almost all the Web Service API methods here.
Hope it helps.
Lets say I have an already functioning Play 2.0 framework based application in Scala that serves a URL such as:
http://localhost:9000/birthdays
which responds with a listing of all known birthdays
I now want to enhance this by adding the ability to restrict results with optional "from" (date) and "to" request params such as
http://localhost:9000/birthdays?from=20120131&to=20120229
(dates here interpreted as yyyyMMdd)
My question is how to handle the request param binding and interpretation in Play 2.0 with Scala, especially given that both of these params should be optional.
Should these parameters be somehow expressed in the "routes" specification? Alternatively, should the responding Controller method pick apart the params from the request object somehow? Is there another way to do this?
Encode your optional parameters as Option[String] (or Option[java.util.Date], but you’ll have to implement your own QueryStringBindable[Date]):
def birthdays(from: Option[String], to: Option[String]) = Action {
// …
}
And declare the following route:
GET /birthday controllers.Application.birthday(from: Option[String], to: Option[String])
A maybe less clean way of doing this for java users is setting defaults:
GET /users controllers.Application.users(max:java.lang.Integer ?= 50, page:java.lang.Integer ?= 0)
And in the controller
public static Result users(Integer max, Integer page) {...}
One more problem, you'll have to repeat the defaults whenever you link to your page in the template
#routes.Application.users(max = 50, page = 0)
In Addition to Julien's answer. If you don't want to include it in the routes file.
You can get this attribute in the controller method using RequestHeader
String from = request().getQueryString("from");
String to = request().getQueryString("to");
This will give you the desired request parameters, plus keep your routes file clean.
Here's Julien's example rewritten in java, using F.Option: (works as of play 2.1)
import play.libs.F.Option;
public static Result birthdays(Option<String> from, Option<String> to) {
// …
}
Route:
GET /birthday controllers.Application.birthday(from: play.libs.F.Option[String], to: play.libs.F.Option[String])
You can also just pick arbitrary query parameters out as strings (you have to do the type conversion yourself):
public static Result birthdays(Option<String> from, Option<String> to) {
String blarg = request().getQueryString("blarg"); // null if not in URL
// …
}
For optional Query parameters, you can do it this way
In routes file, declare API
GET /birthdays controllers.Application.method(from: Long, to: Long)
You can also give some default value, in case API doesn't contain these query params it will automatically assign the default values to these params
GET /birthdays controllers.Application.method(from: Long ?= 0, to: Long ?= 10)
In method written inside controller Application these params will have value null if no default values assigned else default values.
My way of doing this involves using a custom QueryStringBindable. This way I express parameters in routes as:
GET /birthdays/ controllers.Birthdays.getBirthdays(period: util.Period)
The code for Period looks like this.
public class Period implements QueryStringBindable<Period> {
public static final String PATTERN = "dd.MM.yyyy";
public Date start;
public Date end;
#Override
public F.Option<Period> bind(String key, Map<String, String[]> data) {
SimpleDateFormat sdf = new SimpleDateFormat(PATTERN);
try {
start = data.containsKey("startDate")?sdf.parse(data.get("startDate") [0]):null;
end = data.containsKey("endDate")?sdf.parse(data.get("endDate")[0]):null;
} catch (ParseException ignored) {
return F.Option.None();
}
return F.Option.Some(this);
}
#Override
public String unbind(String key) {
SimpleDateFormat sdf = new SimpleDateFormat(PATTERN);
return "startDate=" + sdf.format(start) + "&" + "endDate=" + sdf.format(end);
}
#Override
public String javascriptUnbind() {
return null;
}
public void applyDateFilter(ExpressionList el) {
if (this.start != null)
el.ge("eventDate", this.start);
if (this.end != null)
el.le("eventDate", new DateTime(this.end.getTime()).plusDays(1).toDate());
}
}
applyDateFilter is just a convienence method i use in my controllers if I want to apply date filtering to the query. Obviously you could use other date defaults here, or use some other default than null for start and end date in the bind method.
I'm using GWT 2.4. I'm trying to submit an AJAX request with the only input being the value of a text field on the page. Here is how I attach the handler to the page's button ...
public void onModuleLoad() {
...
final com.google.gwt.dom.client.Element submitElement = Document.get().getElementById(SUBMIT_BUTTON_ID);
final Button submitButton = Button.wrap(submitElement);
...
// Add a handler to send the name to the server
GetHtmlHandler handler = new GetHtmlHandler();
submitButton.addClickHandler(handler);
}
But here's the problem. In my handler, whenever I try and get the value of the text field, it always returns the value entered in the text field when the page was first loaded, as opposed to what the most current value is ...
class GetHtmlHandler implements ClickHandler {
/**
* Fired when the user clicks on the submitButton.
*/
public void onClick(ClickEvent event) {
submitRequest();
}
/**
* Send the name from the nameField to the server and wait for a
* response.
*/
private void submitRequest() {
...
final Element nameFieldElement = DOM.getElementById(Productplus_gwt.NAME_FIELD_ID);
// This always returns an old value.
String docId = nameFieldElement.getAttribute("value");
Anyone know how I can write GWT code inside my handler to return the most current value of a text field given its page id?
Thanks, - Dave
Try using DOM.getPropertyString / DOM.getElementProperty
Following is the javadoc from GWT source for getAttribute function. It clearly says that the support for javascript's "getAttribute" function could be inconsistent for a few browsers and thus Element and subclasses should be used.
Alternatively you can use DOM.getPropertyString to fetch a value which uses object notation of javascript to get te current value
/**
* Retrieves an attribute value by name. Attribute support can be
* inconsistent across various browsers. Consider using the accessors in
* {#link Element} and its specific subclasses to retrieve attributes and
* properties.
*
* #param name The name of the attribute to retrieve
* #return The Attr value as a string, or the empty string if that attribute
* does not have a specified or default value
*/
public final String getAttribute(String name) {
return DOMImpl.impl.getAttribute(this, name);
}
I tried using javascript's "getAttribute" function to get value of a text field in IE8 and FF6. IE gave the updated value of the text field while FF did not. Here is the fiddle
http://jsfiddle.net/GvNu4/
Well like you said it's an AJAX request so whatever code you have on ... the GWT code will continue to run.
You should use the callback of the request and check the value of the nameFieldElement at that moment.