Renaming the argument name in JAX-WS - java

I created a web service using JAX-WS in RSA 7.5 and Websphere 7 using bottom-up approach. When I open the WSDL in SOAP UI, then the arguments section is appearing like this:
<!--Optional-->
<arg0>
<empID>?</empId>
</arg0>
<!--Optional-->
<arg1>
<empName>?</empName>
</arg1>
<!--Optional-->
<arg2>
<empAddress>?</empAddress>
</arg2>
<!--Optional-->
<arg3>
<empCountry>?</empCountry>
</arg3>
The service method takes the above 4 elements as the parameters to return the employee details.
1) I want to rename this arg0, arg1, and so on with some valid names.
2) I want to remove the <!--optional--> present above the arg tags. (For removing the <!--optional--> from elements name, I used #XMLElement(required=true)). But I am not sure where exactly to use this annotation in this case :(
Please help.
Regards,

You put the #XMLElement(required=true) above the variables in your class that are being returned from your service. I just learned about that option about a month ago. So right above where you declare empName put the tag and required.
To rename the parameters of your service use the #WebParam(name="<name you want in soap>") in front of each input variable to the service.
For example, if you have a service method called get(String name) it would look something like get(#WebParam(name = "name") String name)
You are correct, now that I read your comment again. The services I support use Objects in the input and output, which is why I put the XMLElement tag in the class of those objects.
You need to put the tag in the class that declares your variables that are passed in or returned to the service. If those happen to be declared in your service class that is fine. The main point is that you put that XMLElement tag above the variable declaration, versus putting it on a getter or setter.
This tutorial shows some examples of the usage. JAXB tutorial

Related

How to get default application name in cli?

I want to create a framework that shows the application name on statup. Targeting command line interface applications.
Question: how can I get such an application name in a generic way?
Eg spring offers a property, but which is not set by default:
#Value("${spring.application.name}")
private String appname;
And I don't want to set that property explicit. Looking for some kind of "default application name".
In a Java EE container there is also the following option:
String myApplicationName = (String) initialContext.lookup("java:app/AppName");
But how about CLI apps? How can I get some kind of generic application name?
The closest you can get, if I interpreted correctly your question, is to:
find which class is running public static void main(String [] args) method
get its simpleName
store aforementioned name into a system property
and in order to do so, you have two options:
call Thread.currentThread().getStackTrace(), and inspect its tail element. But this has to be executed in the main thread as well, otherwise you wont retrieve the correct StackTraceElement;
call Thread:getAllStackTraces(), and parse the entire map to identify the main Thread, get the corresponding value, and pick its last StackTraceElement
Once you have StackTraceElement, you can call StackTraceElement:getClassName() which will return something like
scala.tools.nsc.MainGenericRunner
Split the string, save it into a system property, and you're good to go.
Hope it will help you.

Java : Is `#WebParam` optional?

I put in place a simple web service using JAX-WS RI (default Java implementation).
I read many tutorials where I find web methods with parameters declared with the WebParam annotation. Ex:
#WebMethod
void foobar(#WebParam("foo") String bar);
In my case I didn't put it and it worked.
Is #WebParam optional ?
Regards.
Yes its Optional, This Option is basically used to give a custom name to your web-Method param, and also the proper format is:
#WebMethod
void foobar(#WebParam(name="foo") String bar);
Also there's a concept of Holder's as well so this annonation can be help ful in that as well, i.e. if you want your method to return more one thing then try the method below
#WebMethod
void foobar(#WebParam(name="foo", Mode=INOUT) Holder<String>bar,
#WebParam(name="param2", Mode=INOUT) Holder<String> newParam);
Now what this will do , you can input two string in the web service and get in return two ouputs from that service's method
Last thing to mention there are three Mode's supported
IN
OUT
INOUT

Passing array with in GAE Endpoints

I am just trying out the first example of GAE Endpoints, I modified the sample API Method to resemble this.
#ApiMethod(name = "sayHi")
public MyBean sayHi(#Named("name") String[] names) {
My expectation is to receive a array of strings.
Now when I use the Google API Explorer to test this, [https://apis-explorer.appspot.com/apis-explorer/]
it generates API like this
POST https://myprojectid.appspot.com/_ah/api/myApi/v1/sayHi/arg1/arg2/arg3?fields=data
It eventually returns 404 error. Since the endpoint is not recognized.
What am I doing wrong here? In fact explorer shows name as String not String[]. Any help is appreciated!
First things first: does this work when there is a single String parameter? There's some servlet mapping magic that needs to happen to expose endpoints, and if that is not present in the project, things won't work. See this link to make sure your web.xml is as it should be.
Looking at this link, it seems that if your method parameter is a basic type (not a real Java object), and if it is not specifically included in a #Path annotation, there's some uncertainty in what will happen in your Api:
Path parameters are the method parameters included in the path property of the #ApiMethod annotation. If path is unspecified, any parameters not annotated with #Nullable or #DefaultValue will be automatically added to the path (they will be path parameters).
So it seems that by not including "name" in a #Path annotation, the docs don't state what the format of the path will be. The generated descriptor that the Explorer is looking at seems to think the right answer is /names[0]/names[1]/names[2], kind of like C-style varargs. It might be this disconnect that causes your 404 to happen. Can you try by including "name" in a #Path annotation?
Instead of having an array as a parameter of the endpoint method, you should put an object (java bean) which contains an array as a property.
Then you get the object in your method and you just read the property and treat it as an array.
Edit after some more research, following your comment
Indeed when you try to pass an array as a Path parameter it doesn't work. The different elements of your array are added to the URL (as you show in your question) and it generates a 404 Not Found error. The trick is that you should pass this array as a Query parameter and not a Path Parameter. See this doc: https://cloud.google.com/appengine/docs/java/endpoints/parameter-and-return-types#path_parameters
And indeed, if you do something like that it works very well:
#ApiMethod(name = "sayHi",
path = "sayHiWithName")
public MyBean sayHi(#Named("name") String[] names) {
MyBean response = new MyBean();
response.setData("Hi, " + names[0] + names[1]);
return response;
}
Note that the parameter is NOT added to the path (i.e. we don't have a path like sayHiWithName/{name}).

Getting empty sequence for the complex type in generated XSD when developing JAX-WS web services

I seem to be having an issue with Java and NetBeans when it comes to writing web services.
I have searched for a couple of days with no luck, finding people with the same issue as me with zero replies.
I have created a web service which returns a complex type (LoginReply), and that complex type contains an array of another complex type (AppInfo)
However when I generate the WSDL from this, the complex type definition in the XSD is blank, and manually adding the information still makes the web service return null even when data is successfully passed to the web service.
<xs:complexType name="appInfo">
<xs:sequence/>
</xs:complexType>
LoginReply: http://pastebin.com/Umx6ayvi
AppInfo: http://pastebin.com/566WnZ4H
If anyone could point out what I'm doing wrong, or if this is a bug with NetBeans, I'm new to Java so I can't rule out that I'm simply not understanding something, but I'm close to pulling my hair out here.
EDIT:
Just noticed when i deploy to tomcat via NetBeans I get the following error:
WARNING: duplicate class definition bug occured? Please report this : uk/co/example/ComplexTypes/LoginReply$JaxbAccessorM_getApplications_setApplications_[Luk_co_example_ComplexTypes_AppInfo;
java.lang.ClassFormatError: Illegal class name "uk/co/example/ComplexTypes/LoginReply$JaxbAccessorM_getApplications_setApplications_[Luk_co_example_ComplexTypes_AppInfo;" in class file uk/co/example/ComplexTypes/LoginReply$JaxbAccessorM_getApplications_setApplications_[Luk_co_example_ComplexTypes_AppInfo;
Notice the random L before co_uk_example. My research suggests this is an old bug that should be fixed, and that no one else has reported this issue in over a year, no sure where to go from here.
Another edit:
Just added a new web method on the service that simply gets a list of appInfo and returns it to the client. This still fails the same way with NetBeans refusing to generate a sequence inside AppInfo.
I'm sure I'm missing something to declare the class, but I have checked it countless times to ensure I'm not missing anything.
warning gives you good hint: "WARNING: duplicate class definition bug occured"
your ws implementation class directly uses LoginReply class which directly uses AppInfo (+you are maybe also directly using this class in your ws implementation) => jaxb finds it
#XMLSeeAlso(...) tells jaxb to "link" referenced class
=> two definitions of the same class (not sure if it is by design or a bug that jaxb is not able to handle this case more gracefully)
to fix this just remove #XmlSeeAlso from your LoginReply class and you should be fine
This Issue came down to a very simple mistake. The AppInfo class was using non-standard getters and setters.
public void SetAppID(int AppID)
{
this.AppID = AppID;
}
This is INCORRECT (notice the capital on the Set), it should be:
public void setAppID(int AppID)
{
this.AppID = AppID;
}
Using a capital is not standard for JavaBeans and as such JAX-WS didn't know how to generate WSDL for this class. Thanks too shyam from the following link for answering the question
How to return a custom complex type in JAX-WS web services?
I don't think you can send "complex types" over the net (programmed port types) in http protocol, however an array may be implicitly converted to a delimited string set , check the docs for data transfer.

Play 2.0: Push a URL parameter to the view

I'm just learning how the Play 2.0 framework. So I have a quite basic question: I just want to take a URL parameter and display it in the view. How do you do that?
I created the URL pattern:
GET /test/:id controllers.Application.testOutput(id: Long)
And an apporoptiate methode in Application:
public static Result testOutput(long id) {
return ok(
views.html.test.render(id)
);
}
How do I call the id variable form the view? I know how to call methodes defined in the model in the view, but I don't know how to display the id variable in the view. Is it the right way to pass the id variable to the render methode?
I'd like to understand the underlying concept, so an detailed explanation to the answer would be great!
Our test URL will be http://localhost:9000/greeter?message=hello and this will output a text/plain response with the content of the parameter message (ie hello). First, let's define the route
GET /greeter controllers.Greeter.say(message: String)
Then, create a Greeter controller (I use Java)
package controllers;
import play.*;
import play.mvc.*;
// This lets you call the template without the views.html prefix
// import views.html.*;
import views.txt.*;
public class Greeter extends Controller {
public static Result say(String message) {
return ok(greeter.render(message));
}
}
You can see that ok() calls a scala function defined in the file app/views/greeter.scala.txt Here is the content of that file (the first line defines the message parameter of type String used inside the function
#(message: String)
I'm the content. Note that you can place
anything you want here. Scala expressions
begin with the '##' character. For example
next line contains the content of message:
#message
In this case I used .txt for file extensions because I wanted plain text response. If you want to produce HTML output, simply make a .scala.html file
The client request is handled by the Play router, which in turn forwards it to some action (which is a method inside a Controller)
GET /greeter Greeter.say
From the Play doc
The last part of a route definition is the Java call. This part is
defined by the fully-qualified name of an action method. The action
method must be a public static void method of a Controller class. A
Controller class must be defined in the controllers package and must
be a subclass of play.mvc.Controller.
You can add a Java package before the Controller class name if it
isn’t defined directly under the controllers package. The controllers
package itself is implicit, so you don’t need to specify it
Inside the action, you can get the parameters via the param object or directly by the method signature:
public static void say(String what) {
...
}
and you can pass objects to the template via render(what) like you do in your sample.
Finally your template can access those object with the ${what} syntax.
EDIT This is the Play 1.x way of doing things. I didn't notice your tag, but still hope this helps. Play2 uses the new Scala template engine, here is the guide. It seems you must declare your parameters at the beginning of the template, then you can access them via the #what syntax. That's because the template is now a compiled Scala function, so it can do type checking at compile time and things like this. You pass parameters to this function with render(what) (like you do) . I personally don't use Play2.0 myself: it's a big improvement from the technical point of view, at the cost of being less intuitive and more verbose. I don't think that simpler projects benefit from these improvements
In Play 2 templates are just plain functions, so you can call them as you would call any function.

Categories

Resources