I have a WCF service with yet only one method:
[OperationContract]
void SaveDocument (InwardDocument doc);
[DataContract]
public class InwardDocument{
[DataMember]
public Citizen Citizen {get;set;}
....
}
[DataContract]
public class Citizen{
[DataMember]
public string LastName {get;set;}
....
}
I've tested the service with both WCF test client and a separate .NET console application. In both cases the service works as expected. But when a java client tries to consume it, a deserialization problem occurs. I've put some markers inside the SaveDocument method to see what causes the problem:
public void SaveDocument(InwardDocument doc){
if(doc==null)
throw new ArgumentnullException("InwardDocument");
if(doc.Citizen==null)
throw new ArgumentnullException("InwardDocument.Citizen");//This exception is thrown when consumed by java client
}
As you can see the first exception is skipped which means doc argument itself is not null but for some reason, the Citizen property is null. The guy who generates the request in java client confirms that the InwardDocument.Citizen property is not null by debugging the code. In fact we've had a problem generating the proxy class in that java client which I describe in this SO thread. So I'm assuming it has something to do with that same problem.Maybe I need to add some more attributes to my classes and their members to care of any such problems that might occur in other platforms? Any suggestions are appreciated.
Have you tried to add Know Type attribute in your InwardDocument class. See link here.
[DataContract]
[KnownType(typeof(Citizen))]
public class InwardDocument{
[DataMember]
public Citizen Citizen {get;set;}
....
}
The problem was caused by incorrect creation of the corresponding JAXBelement instances. The solution to the problem is in this SO thread answer
Related
Good morning everyone.
I am developing a plugin for my project which will consuimir a web service in the system and my question is how to have a general standard of access where each user has an ID registered in the database, giving you access to the API that will be consumed.
Example DB:
User 1 - Name, API_KEY ...
User 2 - Name, API_KEY ...
My question is what is the best way to get these values, leaving my unbound plugin for my whole system, and can even be reused by others. At first a bean that receives configuration via constructor parameters:
class ExpediaConfiguration implements Configuration {
private final String cid;
private final String apiKey;
private final String minorRev;
private final String customerSessionId;
private final String customerIpAddress
public ExpediaConfiguration(String cid, String apiKey, String minorRev, String customerSessionId, String customerIpAddress) {
//do some
}
#Override
public void configure() {
// TODO Auto-generated method stub
}
}
Maybe he receive the Properties were more interesting?
But I'm not sure this is the ideal implementation, perhaps the Spring help me more but do not know how.
I appreciate the answers.
I wrote a web service using cxf web service. I want to send different error messages to client. I have a method and this method return an object if everything is ok. Method receives parameters if one of parameters is wrong, method must send different messages. But i can not change method return type so i cant send different objects. How can i do that?
Try to use the exceptions.
Within the java annotations cxf system you can return an exception if it looks like this :
import javax.xml.ws.WebFault;
#WebFault(name = "UsageMyException")
public class MyException extends Exception
{
private static final long serialVersionUID = 1L;
public MyException(final String string)
{
super(string);
}
public MyException(final Exception e)
{
super(e);
}
}
You can use more than one exception that extends each other. The exception corresponds to wsdl/soap FaultMessage.
I have recently started working on (Java)Web Services.
I have certain web methods that accept different arguments - primitives,Maps,HttpServletRequest,FlowJob(Spring) etc.
I got numerous issues while attempting this - from a failed web service deployment saying 'interfaces not supported by JAX-WS' to runtime exceptions 'java.lang.Object cannot be cast to org.w3c.dom.Element' !
I have not put the steps deliberately;all I need to know is that is it possible to pass the above arguments to a Java Web Service method? In short,is something like this possible :
#WebService(serviceName = "WS")
public class WS {
#WebMethod
public Object processJob(MapargsMap){
}
#WebMethod
public String processJob(SomeCustomObject object){
}
}
}
Are there any work-arounds to make JAXB marshal and unmarshal custom objects,Maps etc.?If yes,what are they?
Thanks & regards !
I am deploying a restful web services using Netbeans EE6 and jersey libraries with the tutorial http://netbeans.org/kb/docs/websvc/rest.html.
When I create a restful web services from entities that hold composite primary keys in the database, the project gives me an error when I try to test the web services:
SEVERE: Missing dependency for method public entities.RMSchedule service.RMScheduleFacadeREST.find(entities.RMSchedulePK) at parameter at index 0
SEVERE: Method, public entities.RMSchedule service.RMScheduleFacadeREST.find(entities.RMSchedulePK), annotated with GET of resource, class service.RMScheduleFacadeREST, is not recognized as valid resource method.
Is the error due to composite primary keys or is there a step that I should include?
Many thanks in advance.
I think this issue is related to Netbeans bug:
https://netbeans.org/bugzilla/show_bug.cgi?id=208375
When creating entity class which has composite primary keys,
two entity files are created. (ex CustomerEntity.jave, CustomerEntityPK.java)
Then if you choose to create the servlet from the entity class, the servlet comes with automatically generated code such as below:
#DELETE
#Path("{id}")
public void remove(#PathParam("id") CustomerEntityPK id) { //error
super.remove(super.find(id));
}
#GET
#Path("{id}")
#Produces({"application/xml", "application/json"})
public CustomerEntity find(#PathParam("id") CustomerEntityPK id) { //error
return super.find(id);
}
The issue is that argument being passed to the servlet methods is CustomerEntityPK which has composite primary key.
If you change the argument type to something like String then the error went away in my case.
#DELETE
#Path("{id}")
public void remove(#PathParam("id") String id) { //type set to String now
super.remove(super.find(id));
}
But in my project I did not need such auto generated code so I simply choose to create servlet class by hand and has no problem.
Hope that helps.
I have some services at the moment that return a dto with the following fields:
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
and I want to add more to this service by adding the following properties:
[DataMember]
public virtual DateTime StartDate { get; set; }
I'm not in a position where i can update the consumers of these services though - the client does that themselves.
My question is - will the old clients be able to just skip these new properties? and the new ones take advantage of them or will the serialization be an issue with the new properties?
w://
As long as the old properties do not change (and the new one is marked as optional) you should be alright.
Said so, you should publish the new contract and get the clients to regenerate the service reference - or deploy the new version to a different endpoint so that when they're ready to switch they are forced to point to the new one.
From what I have seen, the DataContractSerializer just puts null in for properties not found when deserializing. Makes tracking down some bugs quite tricky - sometimes I would prefer if it were more strict and gave an exception.
Another option to consider is subclassing the original DTO to create a new derived class.
In order for serialization to work properly, you need to specify the available derived classes for the supertype with an attribute:
[DataContract]
[KnownType(typeof(DerivedDTO))]
public class OriginalDTO
In code where you use the additional property, you will need to cast the object to a DerivedDTO to get access to the property (I use the as keyword for this and check whether the resulting reference is null before using it)
As long as the new member StartDate is not declared a required field - so this would not work:
[DataMember(IsRequired="True")]
public virtual DateTime StartDate { get; set; }
But as long as you leave out the IsRequired=True, you should be fine.