I'm using JAX-WS api for wsdl generation.
Java-bean class is something like:
public class MyBean {
private String nullableField;
private String notNullableField;
// and here appropriate get/set/ters
}
When wsdl is generated then nullability of this fields is not specified.
Question: what (and where) necessary to specify that fields have corresponding nillable='' value in wsdl? I.e. how can I specify fields nullability in plain java code for wsdl?
At this time I'm generating wsdl and then correcting xml manually for fields nullability. That's not convenient. I want this nillable attribute'll be generated by java-ws automatically.
Any suggestions?
Thanks.
AFAIK, it is still not possible to generate nillable=false when using #WebParam i.e. when using a Java-first approach (as discussed in this thread). Actually, I'd recommend to use a WSDL-first approach if you want fine control.
Related
I am trying to make my #webparam mandatory using (#XmlElement(required=true) but the generated XSD still shows this as minOccurs="0". Also tried setting nillable=false but still not working.
Here is my web method :
#WebMethod
#WebResult(name = "Biller")
public Biller getBiller(#XmlElement(required=true) #WebParam(name = "billerId") Integer billerId){}
Please suggest.
As specified by me in comments - either you need to wrap your Integer variable into some Java POJO and apply rules for specific fields in that POJO or change to primitive type because - reference types are always optional but constituent fields of wrapper types can be made required or optional.
Primitive types are always required.
Refer this answer
Then comes the question about default values - and for that refer Answers to this question and summary is - if nothing is specified -
minOccurs and maxOccurs default to 1
Now why your call succeeds with SOAP UI - Your xsd is correct and that is acknowledged by SOAP UI so my guess is client might be attaching some default values when its missing. I haven't used SOAP UI. Try examining your request ans see if value is really missing. If value is indeed missing in request then try to examine as why validation is not kicking in.
I'm trying to use DynamicEntity to unmarshal some simple JSON, and it's totally bombing on me. Docs are rather sparse, is it even possible to do this? I'm basically doing this;
JAXBContext jaxbContext = JAXBContext.newInstance(DynamicEntity.class);
DynamicEntity entity = (DynamicEntity) jaxbContext.createUnmarshaller().unmarshal(entityStream);
This is straight from the XML docs here: https://wiki.eclipse.org/EclipseLink/Examples/MOXy/Dynamic/XmlToDynamicEntity
And I get;
Caused by:
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
org.eclipse.persistence.dynamic.DynamicEntity is an interface, and JAXB can't handle interfaces.
this problem is related to the following location:
at org.eclipse.persistence.dynamic.DynamicEntity
Has anyone managed to get this to work? I'm basically trying to avoid building POJOs since my backend store doesnt care about them anyway, I just want to deserialize to a generic object and pass it along. In .NET I'd just use dynamic but I'm pretty stumped on how to do this with Moxy.
In order to get DynamicEntity, it is neccessary to use DynamicJAXBContext. It can be configured using the following in jaxb.properties file:
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContextFactory
or you can use DynamicJAXBContextFactory directly.
Although Dynamic MOXY does not require any java classes for the bindings (the POJOs), you need to provide binding metadata when creating the context. It can be XSD or binding.xml that describes the mapping. So instead of creating the context using JAXBContext.newInstance(DynamicEntity.class), you would need to use alternative methods - see links below.
See example here (using XSD):
https://wiki.eclipse.org/EclipseLink/Examples/MOXy/Dynamic/JAXBContextFromXMLSchema
or more complex example using binding.xml and also JSON:
https://wiki.eclipse.org/EclipseLink/Examples/MOXy/Dynamic/Flickr
I am using hibernate reverse engineering and trying to get my Timestamps to map to a JodaTime type.
I have setup my hibernate.reveng.xml file properly
<sql-type jdbc-type="TIMESTAMP" hibernate-type="org.joda.time.contrib.hibernate.PersistentDateTime" not-null="true"></sql-type>
The issue is that when i run the rev-eng process my Java classes also get the members created as PersistentDateTime objects, but I don't want that because they are not usable. I need the java objects to be org.joda.time.DateTime
So I tried creating a custom engineering strategy
public class C3CustomRevEngStrategy extends DelegatingReverseEngineeringStrategy {
public C3CustomRevEngStrategy(ReverseEngineeringStrategy res) {
super(res);
}
public String columnToHibernateTypeName(TableIdentifier table, String columnName, int sqlType, int length, int precision, int scale, boolean nullable, boolean generatedIdentifier) {
if(sqlType==Types.TIMESTAMP) {
return "org.joda.time.DateTime";
} else {
return super.columnToHibernateTypeName(table, columnName, sqlType, length, precision, scale, nullable, generatedIdentifier);
}
}
}
My thought was that the hibernate mapping files would get the hibernate.reveng.xml file settings and the java objects would get the settings from the custom strategy file...but that was not the case. Both the mapping file and Object are of type "org.joda.time.DateTime" which is not what I want.
How can I achieve my goal? Also, I am NOT using annotations.
Hibernate 3.6
JodaTime 2.3
JodaTime-Hibernate 1.3
Thanks
EDIT: To clarify exactly what the issue is
After reverse engineering this is what I get in my mapping file and POJO class
<property name="timestamp" type="org.joda.time.contrib.hibernate.PersistentDateTime">
private PersistentDateTime timestamp;
As a POJO property, PersistentDateTime is useless to me as I cannot do anything with it such as time manipulations or anything. So this is what I want after my reverse engineering
<property name="timestamp" type="org.joda.time.contrib.hibernate.PersistentDateTime">
private org.joda.time.DateTime timestamp;
Using the Jidira library as suggested below gives me the same result, a POJO that I cannot use.
The JodaTime-Hibernate library is deprecated, and is probably the source of your problem. Don't dispair however as there is a (better) alternative.
You will need to use the JadiraTypes library to create the correct JodaTime objects from Hibernate. Add the library which can be found here to your project classpath and then change your type to org.jadira.usertype.dateandtime.joda.PersistantDateTime. All of the JodaTime objects have a corresponding mapping in that package, so if you decide to change to another object then just update your type.
This should ensure that your objects get created correctly.
I should add a caveat to my answer, which is that I have never used the JadiraTypes library with Hibernate 3. If it only supports Hibernate 4 (I don't see why it would, but...) let me know and I'll delete my answer.
The Hibernate Tools don't seem to separate Hibernate Types from the Java types. If you would be using annotations, this would be more clear as in that case you'd need an #Type annotation, which Hibernate will not generate at all. So using the exposed APIs won't help here.
Fortunately, Hibernate lets you plug into the actual code (or XML) generation after it does its processing. You can do that by replacing the Freemarker templates it uses to generate both XML and Java code. You'll need to use Ant for reverse engineering, however.
To start using Ant for this purpose (if you're not doing so already), you can either pull Hibernate Tools in as a build-time dependency using your dependency manager or download a JAR. Put the jar in Ant's classpath, but also extract the template files from it: since you're using XML configuration, you'll be interested in the /hbm directory. Then add the task using <taskdef> and, assuming that you extracted the templates to TPL_PATH/hbm/*.ftl, call it using <hibernatetool templatepath="TPL_PATH" ...>. (For more info, see below for a link to the docs). Using Ant also helps with automation, for example on CI servers where you won't have Eclipse.
You'll want to keep hibernate-type="org.joda.time.DateTime" in your hibernate.reveng.xml so that the Java files get generated correctly, but replace it with org.joda.time.contrib.hibernate.PersistentDateTime in the generated XML. To do that, edit TPL_PATH/hbm/property.hbm.ftl, replace ${property.value.typeName} with ${javaType}, and assign javaType to the right value before it's used:
<#assign javaType=property.value.typeName>
<#if javaType.equals("DateTime")>
<#assign javaType="org.jadira.usertype.dateandtime.joda.PersistentDateTime">
</#if>
<property
name="${property.name}"
type="${javaType}"
...
You might want to remove newlines to keep the generated XML clean.
This is all described in the Hibernate Tools documentation at http://docs.jboss.org/tools/archive/3.2.1.GA/en/hibernatetools/html/codegen.html#d0e6349 - except that the documentation doesn't tell you exactly which templates you need to modify, you need to figure that out by reading the templates.
I am trying to develop a IBM JAX_WS web service using RSA 7.5 and Websphere 7 server. Since I am a beginner, hence I am following Java-class first approach i.e. I am creating the Java classes first and then generating the WSDL file.
When i try to create the wsdl file, i am getting an exception:
java.security.PrivilegedActionException:com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationsException
Class has two properties of the same name "planId"
My class refered here looks something like this:
public class MemberDetails{
#XMLElement(required=true)
private String planId;
//public getters and setters for the planId;
}
I dont have any idea like why is this exception happening. Via Google search I tried a few alternatives to resolve it but none of them worked for me :(
Note:
This is the only annotation I am using throughout my workspace. I am not sure if this is dependent on some other annotations or not. But I tried with a few such as #XMLElement(name="Plan",required=true), #XMLType, etc but every time I am getting this exception.
This exception is occuring during wsgen. (java.lang.reflect.InvocationTargetException)
EDIT
Basically, when we create a wsdl from java service method and open that WSDL in SOAP UI, then we get <!--Optional--> at the top of every element. I want to remove this option tag <!--Optional--> tag, hence I am trying for #XMLElement(required=true) approach so that when I open the WSDL in SOAP UI <!--Optional--> does not appears for compulsary elements.
According to my concept, #XMLElement(required=true) will set the minOccurs to 1 i.e. greater than zero and hence the optional comment will be removed from WSDL when I open it in SOAP UI. But Unfortunately its not working hence my concept is incorrect. After the WSDL is generated, I can see that the minOccurs is still 0.
Please explain how can I remove the optional tag when I open the WSDL in SOAP UI.
Regards,
By default JAXB (JSR-222) implementations process public accessor methods and annotated fields. If you annotate a field that you also have get/set methods for you will get this exception:
If you are going to annotate fields then you should specify #XmlAccessorType(XmlAccessType.FIELD)
#XmlAccessorType(XmlAccessType.FIELD)
public class MemberDetails{
#XMLElement(required=true)
private String planId;
//public getters and setters for the planId;
}
Or you can annotate the property
public class MemberDetails{
private String planId;
#XMLElement(required=true)
public String getPlanId() {
return planId;
}
}
For More Information
http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html
For JAXB2.0 annotating with #XmlTransient on getter or setter will prevent the conflict.
See more here: http://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/XmlTransient.html
I am writing a RESTful web service using Java and Jersey, where the service will accept either XML or JSON inputs. Jackson is used as the JSON deserializer, and integrated into the Jersey config.
One of the endpoints is a POST request to a URL, where the content can be one of several different Java classes, and there is a common base class. These classes - with XML annotations - are:
#XmlRootElement(name = "action")
#XmlAccessorType(XmlAccessType.NONE)
#XmlSeeAlso({ FirstAction.class, SecondAction.class, ThirdAction.class })
public abstract class BaseAction {
}
#XmlRootElement(name = "first-action")
#XmlAccessorType(XmlAccessType.NONE)
public class FirstAction extends BaseAction implements Serializable {
}
// Likewise for SecondAction, ThirdAction
In my resource I can declare a method like:
#POST
#Path("/{id}/action")
public Response invokeAction(#PathParam("id") String id, BaseAction action) {...}
Then I can POST an XML fragment that looks like <firstAction/> and my method will be invoked with a FirstAction instance. So far so good.
Where I'm struggling is getting the JSON deserialization to work as seamlessly as the XML deserialization. Where the #XmlSeeAlso annotation was critical to get the XML deserialization working properly, it seemed that the equivalent for JSON was #JsonSubTypes. So I annotated the classes like this:
// XML annotations removed for brevity, but they are present as in the previous code snippet
#JsonSubTypes({ #JsonSubTypes.Type(name = "first-action", value = FirstAction.class),
#JsonSubTypes.Type(name = "second-action", value = SecondAction.class),
#JsonSubTypes.Type(name = "third-action", value = ThirdAction.class) })
public abstract class BaseAction {
}
#JsonRootName("first-action")
public class FirstAction extends BaseAction implements Serializable {
}
// Likewise for SecondAction, ThirdAction
I then feed it my test input: { "first-action": null } but all I can get is:
"org.codehaus.jackson.map.JsonMappingException: Root name 'first-action' does not match expected ('action') for type [simple type, class com.alu.openstack.domain.compute.server.actions.BaseAction]"
Unfortunately since I'm trying to be compatible with someone else's API I can't change my sample input - { "first-action": null } has to work, and deliver to my method an object of class FirstAction. (The action doesn't have any fields, which is why null shouldn't be a problem - it's the type of the class that's important).
What's the correct way to have the JSON deserialization work in the same way as the XML deserialization already is?
If you are using Jackson, you are looking for #JsonTypeInfo and #Type . Please see here for more information
JSON does not work the way XML does, so the solution is not identical.
What you need to use is (like the other answer said), #JsonTypeInfo. That only triggers inclusion and use of the type identifier. If so, then '#JsonSubTypes` will be of use in deserialization.
The reason this indicator must be used is simple: if you have more than one alternative type to deserialize to, there must be something to differentiate.
Note, too, that this does NOT have to be a property -- while most users choose "As.PROPERTY" inclusion, it is not (IMO) the best way. "WRAPPER_OBJECT" may be what you are looking for, as it adds an extra intermediate JSON property, which is somewhat similar to what XML does.
I investigated the use of #JsonTypeInfo but ran into problems because I could not alter the input format. The parser absolutely had to be able to handle input { "first-action":null }. This ruled out the possibility of adding an #type or #class property. Using a wrapper object may have worked, but it choked on the null payload.
A crucial point was that I was using the UNWRAP_ROOT_PROPERTY configuration option. Jackson was absolutely insisting on finding an action property and I could not get it to consider anything else. So, I had to selectively disable UNWRAP_ROOT_PROPERTY for certain domain objects, so that Jackson would be open to parsing alternatives. I modified the project's ContextResolver.getContext(...) implementation to check for a #JsonRootName annotation - since this only has meaning if wrapping is enabled, I used the presence of this annotation to determine whether to return an object mapper configured with root property wrapping on, or off.
At this stage, I might have been able to use #JsonTypeInfo(include=JsonTypeInfo.As.WRAPPER_OBJECT, ...), except for the issue with the null payload mentioned above (this is used to indicate that the child object has no properties - if the spec I was working from had given an empty object {} instead then there would not be a problem). So to proceed I needed a custom type resolver.
I created a new class that extended org.codehaus.jackson.map.TypeDeserializer, with the purpose that whenever Jackson is called to deserialize a BaseAction instance, it will call this custom deserializer. The deserializer will be given a subtypes array, which for BaseAction maps first-action, second-action, etc. to FirstAction.class, etc. The deserializer reads the input stream for the field name, then matches the name to a class. If the next token is an object, then it finds and delegates to the appropriate deserializer for that class, or if it is null it finds the no-args constructor and invokes it to get an object.
A class that implements org.codehaus.jackson.map.jsontype.TypeResolverBuilder is needed that can build an instance of this previous class, and then the TypeResolverBuilder is given as a #JsonTypeResolver annotation on the BaseAction class.