I have created a JaX Webservice through RAD(eclipse), and I am able to use the #WebParam annotation with my function parameter, however I also want to use #webresult etc but Don't know where should i specify them, on google I got interfaces but here i only have class and delegate class.
my class is
public class GetFPDDataClass {
public String GetFPDDataInput(String PolicyNumber)
{
return PolicyNumber;
}
}
and this is my delegate class
#WebService (targetNamespace="fpd", serviceName="GetFPDDataClassService", portName="GetFPDDataClassPort")
public class GetFPDDataClassDelegate{
fpd.GetFPDDataClass _getFPDDataClass = null;
public String GetFPDDataInput (#WebParam(name="PolicyNumber") String PolicyNumber) {
return _getFPDDataClass.GetFPDDataInput(PolicyNumber);
}
public GetFPDDataClassDelegate() {
_getFPDDataClass = new fpd.GetFPDDataClass(); }
}
Both #WebResult and #WebMethod are set on the method level.
#WebResult is used to customize name of the XML element that represents the return value.
#WebMethod is used to mark business methods that are exposed to web service clients. By default all public methods in your class are exposed, if you don't implement web service interface.
Example:
#WebMethod
#WebResult(name="hellomessage")
public String getHello() {
....
}
UPDATE:
If I dont have #WebResult I see the following xml:
<ns2:getHelloResponse>
<return>hello fff</return>
</ns2:getHelloResponse>
with #WebResult:
<ns2:getHelloResponse>
<hellomessage>hello fff</hellomessage>
</ns2:getHelloResponse>
Related
I have created REST controller with base request mapping on class.
#RestController
#RequestMapping(".../{type}/{typeId}/param..")
public class FooController{
#Autowired
BarServiceProxy proxy;
public List<Foo> getFoo(){
return proxy.get(getType());
}
/*
public Type getType(???){
return type;
}
*/
}
Next I have enum Type which determines what service will be used by proxy service (ie. proxy has injected list of serivces and gets one that supports type). I am wondering if there is any way how to make part of request mapping {type} and get it in getter method below so I don't have to repeat it in every request mapping in this class.
I only figured one alternative solution - make this class abstract and then extend it and return constant. This would however leave me with lot of classes without any added value. For example:
#RequestMapping(".../{typeId}/param..")
public abstract class FooController{
#Autowired
BarServiceProxy proxy;
public List<Foo> getFoo(){
return proxy.get(getType());
}
protected abstract Type getType();
}
#RestController
#RequestMapping("/typeAbc)
public class TypeAbcFooController extends FooController{
public Type getType{
return Type.Abc;
}
}
So is it possible to bind #PathVariable from URL specified on class #RequestMapping in some shared method? Thanks
I hope i've understood your problem, but one way of improving your design could be to implement a strategy per type, to inject them, and to use them corresponding to your type received in your controller.
Exemple:
public enum MyType {
TYPE1,
TYPE2
}
public interface IService {
MyType getHandledType();
List<Foo> getFoo();
}
#Service
public class Type1Service implements IService {
#Override
public MyType getHandledType() {
return MyType.TYPE1;
}
#Override
public List<Foo> getFoo() {
// IMPLEMENTATION FOR TYPE1;
}
}
public class FooController{
#Autowired
List<IService> services;
public List<Foo> getFoo(MyType requestType){
IService service = services.stream().filter(iService -> iService.getHandledType() == requestType).findFirst().get();
return service.getFoo();
}
}
This way your controller is agnostic of the underlying service implementation, which is a big responsability.
I have routes like:
GET /job$id<[0-9]+>/ controllers.Jobs.index(id)
POST /job$id<[0-9]+>/done controllers.Jobs.done(id)
POST /job$id<[0-9]+>/update controllers.Jobs.update(id)
DELETE /job$id<[0-9]+>/remove controllers.Jobs.remove(id)
and I' like to secure it. Each job has an owner. So I made
public class Secured extends Security.Authenticator {
...
}
Then I tryed to secure all my Actions by "#With()" annotatian, but I need to pass "Id" param to my secure method, so I wrote smth like:
#With(IsOwner.class)
#Target({ElementType.TYPE, ElementType.METHOD})
#Retention(RetentionPolicy.RUNTIME)
public #interface Owner {
long value() default 0;
}
public static class IsOwner extends Action<Owner>{
#Override
public Promise<SimpleResult> call(Context ctx) throws Throwable {
if(!isOwner(configuration.value())){
return Promise.pure(redirect(..));
}
return delegate.call(ctx);
}
}
But I can't pass my action parametr to annotation.
#Security.Authenticated(Secured.class)
#Owner(id) //**this part I want to work**
public class Jobs extends Controller {
//#Owner(id) - or at list there
public static Result index(Long Id){
//I have too many Actions and don't want to do every time this
/*if(!Secured.isOwnerMethod(Id)){
return forbidden();
}*/
return ok();
}
Other way I see is get params from Context in IsOwner.call() method...
Please, give me a recommendation or good practise for such situations.
Thanks.
I ran into this problem and came up with a Play extension that exposes all url parameters as common request parameters... You can check it out here => https://github.com/asouza/reverse-route-plugin
Basically you have to extend from my Global class.
Cheers,
Alberto
I don't have any specific examples in front of me right now, but I've had this issue in the past.
When I have a resource that extends another class and utilizes annotations, can the base class have annotations that are read as if they're part of the child class? I've tried to do this in some scenarios and it doesn't ever seem to work. Is there some way to make this possible? Is this a scope issue with no #Path being defined for the base class?
#Path("/workflow")
#Consumes({MediaType.APPLICATION_JSON})
#Produces({MediaType.APPLICATION_JSON})
public class WorkflowResource extends BaseWorkflowResource {
#GET
#Path("/getAllActive")
public Collection<WorkflowEntity> getActive () {
return MyClass.getAllActive();
}
}
//THIS CALL WON'T BE AVAILABLE
public class BaseWorkflowResource {
#GET
#Path("/getMyString")
public String getActiveString () {
return "my string";
}
}
This method
public Collection<WorkflowEntity> getActive()
will override this method
public String getActive()
This is not a matter of JAX-RS but of plain Java. Both methods have the same signature (name, parameters).
Try using different method signatures in parent and child class.
Is there a way to use abstract or annotated class as MXBean descriptor? I have interface like:
#MXBean
public interface Peer {
public String getName();
}
and want that MXBean to be combined in class with more local-side-only methods like:
public class PeerCombinedMXBean {
// Expose this as MXBean attribute
public String getName() { ... }
// This method is local-instance-oriented
public boolean isValid() { ... }
}
I need model like above to avoid chain-in proxy object instead to use complex half-proxified instance like:
PeerCombinedMXBean peer = JMX.newMXBeanProxy(connection, name, PeerCombinedMXBean.class);
if (peer.isValid()) System.out.println(peer.getName());
Edit
This question is related to java.net article. What is they progress? Can I use MBeans with annotation safely now?
What I ended up doing for this was writing a custom annotation that you place on a method or property. Then, I implemented the DynamicMBean interface in such a way that it parsed out the annotations on the class in question and then registers them with the PlatformMBeanServer. As far as I know, there are no public implementations of this available, I also searched extensively about this topic before I just did it myself.
For example, here is the class that I wish to manage from JConsole:
public class Foo
{
// In JMX Console
#Managed
private boolean isBar;
// Not in JMX Console
private boolean isFoo;
// In JMX Console
#Managed
public String getClassName()
{
return Foo.class.getName();
}
}
Then, when my application starts up, I register an instance of this class using my implementation of DynamicMBean and parse out the annotations.
Using Jersey 1.7, JAX-WS 2.2.3, Tomcat 6.0.30 and the following method declaration prevents Jersey servlet to start:
#POST
#Produces("text/plain")
public void postIt(#WebParam(name = "paramOne") final String paramOne,
final String paramTwo) {
// ...
}
The generated exception is:
SEVERE: Missing dependency for method public
java.lang.String com.sun.jersey.issue.MyResource.postIt(
java.lang.String,java.lang.String) at parameter at index 0
SEVERE: Method, public void
com.sun.jersey.issue.MyResource.postIt(
java.lang.String,java.lang.String),
annotated with POST of resource,
class com.sun.jersey.issue.MyResource,
is not recognized as valid resource method.
If the #WebParam annotation is removed, it all works fine.
Now, please have in mind that I am not trying to work with mere strings, rather, I am migrating complicated Objects that got marshalled/unmarshalled using SOAP to RESTful services, but I must provide both interfaces for a while, without breaking the previous WASDs. The method is just a minimalistic scenario.
Has any of you any idea of the status of this? Has it been fixed? Suggestions?
The specification is clear on this. Section 3.3.2.1 tells us that:
Resource methods MUST NOT have more
than one parameter that is not
annotated with one of the above listed
annotations.
The above listed annotations are the JAX-RS parameter annotations: #QueryParam, #MatrixParam, etc.
There is, however, a Jersey specific way to solve this problem. Using InjectableProvider. So, a method that defines two non-JAX-RS parameters:
#POST
public void postIt(#CustomInjectable final Customer customer,
final Transaction transaction) {
// ...
}
Of course, we have to code the annotation:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.PARAMETER)
public #interface CustomInjectable {
}
An implementation of InjectableProvider that knows how to provide Customers:
import com.sun.jersey.spi.inject.Injectable;
import com.sun.jersey.spi.inject.InjectableProvider;
import com.sun.jersey.api.model.Parameter;
#Provider
public class CustomerInjectableProvider implements
InjectableProvider<CustomInjectable, Parameter> {
// you can use #Context variables, as in any Provider/Resource
#Context
private Request request;
public ComponentScope getScope() {
// ComponentScope.Singleton, Request or Undefined
}
public Injectable getInjectable(ComponentContext i,
CustomInjectable annotation,
Parameter param) {
Injectable injectable = null;
if (Customer.getClass().isAssignableFrom(param.getParameterClass()) {
injectable = getInjectable();
}
return injectable;
}
private Injectable getInjectable() {
return new Injectable<Customer>() {
public Customer getValue() {
// parse the customer from request... or session... or whatever...
}
};
}
}
But, Jersey considers only the last annotation (see JERSEY-ISSUE-731), so be careful.
And, a more portable way (if you do care about that, anyway):
// simple bean
public class CustomerWithTransaction {
private Customer customer;
private Transaction transaction;
// getters and setters
}
Then change the method to:
#POST
public void postIt(CustomerWithTransaction customerWithTransaction) {
// ...
}
Then create your own MessageBodyReader for CustomerWithTransaction, where you can also access any context variables (request, headers, etc.).