I'm working in a framework that does a lot of inheritance, and I've found that Natvis for one base class will interfere with that for another.
Here's a dumb example:
class MainBase {};
class ExtraBase {};
class Derived: MainBase, ExtraBase {};
With this natvis:
<Type Name="MainBase">
<Expand>
<Item Name="MainBaseItem">23</Item>
</Expand>
</Type>
<Type Name="ExtraBase">
<Expand>
<Item Name="ExtraBaseItem">42</Item>
</Expand>
</Type>
...I get this:
https://i.stack.imgur.com/0dMNu.png
The expansion for MainBaseItem has shown up fine, but the one for ExtraBaseItem is nowhere to be seen.
In my real-world case, the natvis for the MainBase equivalent is very important, so I can't solve the problem by adding Inheritable="false" to it. It's also not practical to add specialised natvis for the derived class itself - there are thousands of derived classes. Given these unhelpful constraints, is there anything I can do to make ExtraBaseItem show up?
<Type Name="ExtraBase">
<Expand>
<!-- Example of hierarchical class shown below-->
<Item Name="MainBaseItem [base]">(MainBaseItem*)this</Item>
</Expand>
</Type>
Idk if i understand this correct ....
Related
I want to extend a natvis visualizer for a (C++) template class. Is there a way to display a type name of the first template parameter?
It would be great for boost::variant<int,bool> v; v=1; to display 1 (int) or something like that
If you want to show $T1 as a string, wrap it with ". For example, for
<DisplayString>{*($T1*)storage_.data_.buf} {"$T1"}</DisplayString>
in your case you will see 1 "int"
In my opinion the best solution is to use the standard C++17 std::variant. MSVC comes with natvis for this type so that you have a pretty view of the value that is stored.
Here is some natvis code that I just wrote and tested:
<Type Name="boost::variant<*>">
<DisplayString Condition="which_==0">{*($T1*)storage_.data_.buf}</DisplayString>
<DisplayString Condition="which_==1" Optional="true">{*($T2*)storage_.data_.buf}</DisplayString>
<DisplayString Condition="which_==2" Optional="true">{*($T3*)storage_.data_.buf}</DisplayString>
<DisplayString Condition="which_==3" Optional="true">{*($T4*)storage_.data_.buf}</DisplayString>
<DisplayString Condition="which_==4" Optional="true">{*($T5*)storage_.data_.buf}</DisplayString>
<DisplayString Condition="which_==5" Optional="true">{*($T6*)storage_.data_.buf}</DisplayString>
<DisplayString Condition="which_==6" Optional="true">{*($T7*)storage_.data_.buf}</DisplayString>
<Expand>
<Item Name="which">which_</Item>
<Item Name="value0" Condition="which_==0">*($T1*)storage_.data_.buf</Item>
<Item Name="value1" Condition="which_==1" Optional="true">*($T2*)storage_.data_.buf</Item>
<Item Name="value2" Condition="which_==2" Optional="true">*($T3*)storage_.data_.buf</Item>
<Item Name="value3" Condition="which_==3" Optional="true">*($T4*)storage_.data_.buf</Item>
<Item Name="value4" Condition="which_==4" Optional="true">*($T5*)storage_.data_.buf</Item>
<Item Name="value5" Condition="which_==5" Optional="true">*($T6*)storage_.data_.buf</Item>
<Item Name="value6" Condition="which_==6" Optional="true">*($T7*)storage_.data_.buf</Item>
</Expand>
</Type>
It works for any boost::variant<type_or_types>.
It has a DisplayString that takes the variant's member storage_ and extracts the buffer buf. The address of the buffer is then cast to a pointer to the type that was provided to std::variant. As you can see in my code which_ is zero based, whereas the template parameters are 1 based. I am not interested in the address but in the value, so I am adding a * in front of the value.
I also added an Expand section so that you can expand a variant. This allows me to show which_ and to show the value again - this time the column Type will show the correct type as you can see in my screen capture (for the variant itself the type is displayed as boost::variant<…> and I do not know how to add the type name into the DisplayString).
Please note that the Optional="true" are required because otherwise we would get a parsing error in cases where less than 7 type parameters are passed (as in boost::variant<int,bool>and natvis does not have a $T7.
If you need more template parameters, you can easily extend the code.
If you want the DisplayString to also shows the index (as an explicit value or coded into the name value…), you can easily change it accordingly as in
<DisplayString Condition="which_==0">{{which={which_} value0={*($T1*)storage_.data_.buf}}}</DisplayString>
Last but not least please note that I did not test very much and that I did not look into boost::variant into detail. I saw that storage_ has members suggesting that there is some alignment in place. So it might not be sufficient to just use storage_.data_.buf. It might be necessary to adjust the pointer depending on the alignment being used.
For elements with multiplicity > 1 (i.e.. where maxOccurs>1 or maxOccurs=unbound), e.g.:
<element name="Name" type="tns:Type" minOccurs="0" maxOccurs="unbound"/>
JAXB generates the following code:
#XmlElement(name = "Name")
protected List<type> name;
Strictly speaking the above schema describes an XML snippet that looks like so:
<Name attr1="a" attr2="x">
<Name attr1="b" attr2="y">
<Name attr1="c" attr2="z">
i.e. a sequence of "Name" elements (and only that!).
When marshalling a Java object to XML the JAXB runtime creates XML, which contains an additional wrapper element around the list, like so:
<Name>
<Name attr1="a" attr2="x">
<Name attr1="b" attr2="y">
<Name attr1="c" attr2="z">
<Name>
By default the wrapping element has the same name as the individual items. Note, that there is no Java class representing that element!
One can overrule the naming to something that makes more sense by manually (!) adding a java-annotation "#XmlElementWrapper" annotation, like so:
#XmlElementWrapper(name = "NameList")
#XmlElement(name = "Name")
protected List<Type> name;
which then yields the following XML:
<NameList>
<Name attr1="a" attr2="x">
<Name attr1="b" attr2="y">
<Name attr1="c" attr2="z">
<NameList>
I agree that such a wrapper element is syntactically nice and makes the XML more readable, BUT there is a severe problem with this: the generated Java code (with or without renaming the wrapper element) generates and expects an XML dialect which - strictly speaking - does not match the original schema anymore! There is no mentioning or any implicit notion of any such wrapper element in the original schema!
The issue only surfaces, if one uses the original schema in different tools (e.g. to create web forms or a different schema-based code generator) and if their result then adheres and/or expects the original XML (i.e. the bare sequence without any wrapper element), while the JAXB-generated code creates and insists on the presence of the wrapper element. Then the two cannot understand each other!
My question thus: how can one instruct JAXB to NOT add/expect said wrapper element while marshalling/unmarshalling XML?
I have searched the web now for quite a while for solutions or work-arounds to this but found nothing! I can't imagine that nobody else before ever stumbled over this and that there seems no other solution to this other problem than to hand-tweak the XML marshalling/unmarshalling code. Any ideas or suggestions to solve this issue?
I am trying to use the .natvis file for Visual Studio 2012 to display a customised class in the Watch window but I cannot get it to display.
If I have this structure
namespace a {
namespace b {
template<class T, class myClass, class myOtherclass> class hereBeDragons;
}
typedef b::hereBeDragons<firstParam, secondParam, thirdParam> IWantToSeeThis;
}
and I want to display objects of the class IWantToSeeThis. What is the syntax I need to use?
I have tried these:
<Type Name="a::IWantToSeeThis">
<DisplayString> Here are my values </DisplayString>
</Type>
<Type Name="a::b::hereBeDragons">
<DisplayString> Here are my values </DisplayString>
</Type>
<Type Name="a::b::hereBeDragons&at;&bt;&ct">
<DisplayString> Here are my values </DisplayString>
</Type>
<Type Name="a::IWantToSeeThis&at;&bt;&ct;">
<DisplayString> Here are my values</DisplayString>
</Type>
but none of them see to cause the structure to be displayed.
I have tried enabling the diagnostics by creating the registry key as explained here:
https://code.msdn.microsoft.com/Writing-type-visualizers-2eae77a2
But when I restarted dev studio no diagnostics were displayed in the output window.
I have worked it out:
<Type Name="a::b::hereBeDragons<*,*,*>">
<DisplayString>
Here are my values
</DisplayString>
</Type>
I was looking for a fast and easy way to write a very cross platform desktop application. This leads me to thinking that the JVM is the place to be. Since Groovy (Grails) is used in my workplace I thought I would try Griffon since they claim it is essentially Grails for the desktop.
I wanted a persistence management layer and it doesn't not appear that GORM is showtime ready in this environment so I moved towards hibernate using the Hibernate4 plugin for Griffon.
Not that I've really used Hibernate in general however I believe, based on the guides, that I am doing things correctly. My gatherings indicate that this doesn't support annotations to wire up classes so I am using hbm.xml files.
The provided sample for the plugin isn't complex but I don't understand where I am deviating.
Here is a sample class file as it stands:
package gwash
import groovy.beans.Bindable
class DeliveryMethodModel {
// #Bindable String propName
}
Here is some of the stack trace:
org.hibernate.InvalidMappingException: Could not parse mapping document from res
ource gwash\DeliveryMethod.hbm.xml
at org.hibernate.cfg.Configuration$MetadataSourceQueue.processHbmXml(Con
figuration.java:3415)
at org.hibernate.cfg.Configuration$MetadataSourceQueue.processHbmXmlQueu
e(Configuration.java:3404)
at org.hibernate.cfg.Configuration$MetadataSourceQueue.processMetadata(C
onfiguration.java:3392)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:
1341)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.jav
a:1737)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.jav
a:1788)
at org.hibernate.cfg.Configuration$buildSessionFactory.call(Unknown Sour
ce)
at griffon.plugins.hibernate4.Hibernate4Connector.connect(Hibernate4Conn
ector.groovy:72)
at griffon.plugins.hibernate4.Hibernate4Connector.connect(Hibernate4Conn
ector.groovy)
at griffon.plugins.hibernate4.Hibernate4Connector$connect.call(Unknown S
ource)
at Hibernate4GriffonAddon.addonInit(Hibernate4GriffonAddon.groovy:27)
at griffon.core.GriffonAddon$addonInit.call(Unknown Source)
at griffon.core.GriffonAddon$addonInit.call(Unknown Source)
at org.codehaus.griffon.runtime.util.AddonHelper.handleAddon(AddonHelper
.groovy:155)
at org.codehaus.griffon.runtime.util.AddonHelper.handleAddonsAtStartup(A
ddonHelper.groovy:105)
at org.codehaus.griffon.runtime.core.DefaultAddonManager.doInitialize(De
faultAddonManager.java:33)
at org.codehaus.griffon.runtime.core.AbstractAddonManager.initialize(Abs
tractAddonManager.java:101)
at org.codehaus.griffon.runtime.util.GriffonApplicationHelper.initialize
AddonManager(GriffonApplicationHelper.java:320)
at org.codehaus.griffon.runtime.util.GriffonApplicationHelper.prepare(Gr
iffonApplicationHelper.java:123)
at org.codehaus.griffon.runtime.core.AbstractGriffonApplication.initiali
ze(AbstractGriffonApplication.java:221)
at griffon.swing.AbstractSwingGriffonApplication.bootstrap(AbstractSwing
GriffonApplication.java:74)
at griffon.swing.AbstractSwingGriffonApplication.run(AbstractSwingGriffo
nApplication.java:131)
at griffon.swing.SwingApplication.main(SwingApplication.java:36)
Caused by: org.hibernate.PropertyNotFoundException: field [id] not found on gwas
h.DeliveryMethodModel
at org.hibernate.property.DirectPropertyAccessor.getField(DirectProperty
Accessor.java:182)
at org.hibernate.property.DirectPropertyAccessor.getField(DirectProperty
Accessor.java:189)
at org.hibernate.property.DirectPropertyAccessor.getField(DirectProperty
Accessor.java:189)
at org.hibernate.property.DirectPropertyAccessor.getField(DirectProperty
Accessor.java:189)
at org.hibernate.property.DirectPropertyAccessor.getField(DirectProperty
Accessor.java:189)
at org.hibernate.property.DirectPropertyAccessor.getField(DirectProperty
Accessor.java:174)
at org.hibernate.property.DirectPropertyAccessor.getGetter(DirectPropert
yAccessor.java:197)
at org.hibernate.internal.util.ReflectHelper.getter(ReflectHelper.java:2
53)
at org.hibernate.internal.util.ReflectHelper.reflectedPropertyClass(Refl
ectHelper.java:229)
at org.hibernate.mapping.SimpleValue.setTypeUsingReflection(SimpleValue.
java:326)
at org.hibernate.cfg.HbmBinder.bindSimpleId(HbmBinder.java:449)
at org.hibernate.cfg.HbmBinder.bindRootPersistentClassCommonValues(HbmBi
nder.java:382)
at org.hibernate.cfg.HbmBinder.bindRootClass(HbmBinder.java:322)
at org.hibernate.cfg.HbmBinder.bindRoot(HbmBinder.java:173)
at org.hibernate.cfg.Configuration$MetadataSourceQueue.processHbmXml(Con
My xml mapping file:
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="gwash">
<class name="DeliveryMethodModel" table="[DELIVERY METHODS]">
<id name="id" column="[DELIVERY METHOD ID]">
<generator class="increment"/>
</id>
<property name="method" column="[DELIVERY METHOD]"/>
</class>
</hibernate-mapping>
EDIT: I've removed the brackets and spaces as indicated. Changed the DataSource.groovy to 'create' on the DB side. Still experiencing the same issues. The examples for hibernate integration with griffon/hsqldb/groovy are scant on details. Do I need to create all given properties for the model files for this to parse correctly? I've never used hibernate. Nor groovy. Nor griffon. I would definitely provide feedback for the community if I can get this resolved, if not I'll be rolling me own ORM since this is a rather small project. Rather not roll me own.
do you actually have the strings wrapped with [and ]?
I would suspect that for a class defined as
package gwash
import groovy.beans.Bindable
class DeliveryMethodModel {
Long id
#Bindable String method
}
the mapping file would be
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="gwash">
<class name="DeliveryMethodModel" table="DELIVERY_METHODS">
<id name="id" column="DELIVERY_METHOD_ID">
<generator class="increment"/>
</id>
<property name="method" column="DELIVERY_METHOD"/>
</class>
</hibernate-mapping>
I'm currently working with the Dynamics CRM 4.0 webservice. First thing I did, was generating the right classes with wsimport for Java/JAX-WS based on the WSDL of the webservice. While generating the classes I got some errors:
[ERROR] A class/interface with the same name
"com.microsoft.schemas.crm._2007.webservices.RetrieveResponse" is already in use. Use a class customization to resolve this conflict.
line 979 of file://src/main/webapp/WEB-INF/classes/META-INF/wsdl/CrmServiceWsdl.wsdl
[ERROR] (Relevant to above error) another "RetrieveResponse" is generated from here.
line 12274 of file://src/main/webapp/WEB-INF/classes/META-INF/wsdl/CrmServiceWsdl.wsdl
Line 979 tells us:
<s:element name="RetrieveResponse">
<s:complexType>
<s:sequence>
<s:element name="RetrieveResult" type="s3:BusinessEntity" />
</s:sequence>
</s:complexType>
</s:element>
And line 12274 gives us:
<s:complexType name="RetrieveResponse">
<s:complexContent mixed="false">
<s:extension base="tns:Response">
<s:sequence>
<s:element ref="s3:BusinessEntity" />
</s:sequence>
</s:extension>
</s:complexContent>
</s:complexType>
Both parts are in the same namespace. Both will be generated as RetrieveResponse.class and so they are colliding. I've found a solution for this problem which is the JAX-B binding xml file:
<bindings node="//xsd:complexType[#name='RetrieveResponse']">
<jaxb:class name="RetrieveResponseType"/>
</bindings>
This works (not sure if this is the correct approach..?)..
So after this, I've managed to create some successful calls to the webservice, which is great!
Now comes the problem: some business entities in dynamics crm uses the class Picklist. This type of entity can be queried with the Metadata service: http://msdn.microsoft.com/en-us/library/bb890248.aspx
So the next thing I did was, again, generating the classes for the metadata service, based on it's WSDL. The result of the generated classes are not as we except. For example, it generates a class 'com.microsoft.schemas.crm._2007.webservices.ExecuteResponse'. But this class also exists in the exact same package of the CrmService generated classes. Differences between the 2 are:
Metadataservice ExecuteReponse:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"response"
})
#XmlRootElement(name = "ExecuteResponse")
public class ExecuteResponse {
#XmlElement(name = "Response")
protected MetadataServiceResponse response;
etc...
CrmService ExecuteReponse:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"response"
})
#XmlRootElement(name = "ExecuteResponse")
public class ExecuteResponse {
#XmlElement(name = "Response", required = true)
protected ResponseType response;
etc...
Now this class is just one example (another example is CrmAuthenticationToken), which is a almost exact duplicate of another class. To be able to use the same classes, I've added a package-suffix to the CrmService classes (displayed as prefix.).
So now when I try to call the CrmService, I get the following exception:
Two classes have the same XML type name "{http://schemas.microsoft.com/crm/2007/CoreTypes}CrmAuthenticationToken". Use #XmlType.name and #XmlType.namespace to assign different names to them.
this problem is related to the following location:
at com.microsoft.schemas.crm._2007.coretypes.CrmAuthenticationToken
at public com.microsoft.schemas.crm._2007.coretypes.CrmAuthenticationToken *prefix*.com.microsoft.schemas.crm._2007.coretypes.ObjectFactory.createCrmAuthenticationToken()
at *prefix*.com.microsoft.schemas.crm._2007.coretypes.ObjectFactory
this problem is related to the following location:
at *prefix*.com.microsoft.schemas.crm._2007.coretypes.CrmAuthenticationToken
at public javax.xml.bind.JAXBElement *prefix*.com.microsoft.schemas.crm._2007.webservices.ObjectFactory.createCrmAuthenticationToken(*prefix*.com.microsoft.schemas.crm._2007.coretypes.CrmAuthenticationToken)
at *prefix*.com.microsoft.schemas.crm._2007.webservices.ObjectFactory
I personally think it's weird they put different classes with the same name in the same package structure. This means you can never use the 2 webservices at the same time..
Is this a Microsoft, a WSimport bug or just a stupid mistake at my end? Hope somebody can help me with this problem!
Thanks for your time!
This is Microsoft inconsistency combined with wsimport being somewhat hard to use.
The PickList and the CRMAuthenticationToken sound like custom datatypes, you'd expect for these to get reused from service to service.
You'd also expect certain CRM-specific entities (say, Customer or Business or Address) to get reused from service to service.
It is bad manners on the Microsoft side of things that they define these differently for different services. This makes it hard to take the answer of one service and send it on to another service.
Had the services shared one or more common schemas, you could've compiled those first, using xjc. Then you could've provided a so-called episode file to wsimport to tell it to use those classes instead of generating new ones. See the metro guide. This is quite a puzzle, I can tell you from experience, I ran into bug JAXB-829, xjc forgets to generate if-exists attributes in the episode file.
What I'd do, I'd compile each wsdl to its own package and treat the generated classes as simple unintelligent Data Transfer Objects.
If I wanted to send an object I'd just retrieved from one service on to a second service, I'd convert between the both.
If this results in terribly unwieldy code, or if you wish to add logic to certain entities, I'd suggest you write your own proper model classes for the Entities you wish to share and write converters to and from the DTO objects in the web services packages you wish to use them with.