I'm porting my Coldspring xml into Wirebox, but I'm stuck.
<map> in Coldspring can create a struct of singletons and then pass that struct into the 'bean' by constructor or setter. And <list> creates an array.
What do I write in Wirebox.cfc to do the same thing?
<bean id="Foo" class="com.foo">
<constructor-arg name="something">
<map>
<entry key="apple">
<ref bean="apple"/>
</entry>
<entry key="banana">
<ref bean="banana"/>
</entry>
</map>
</constructor-arg>
</bean>
<bean id="bar" class="com.bar">
<constructor-arg name="anArray">
<list>
<bean class="com.XX"/>
<bean class="com.YY"/>
</list>
</constructor-arg>
</bean>
Update: I have found a clean way to support this after reading how ColdSpring does it.
First, create a cfc with 2 methods:
component
{
struct function buildStruct() {
return arguments;
}
array function buildArray() {
var array = [];
for (var index = 1; index <= arrayLen(arguments); index++)
array[index] = arguments[index];
return array;
}
}
Then in wirebox config.cfc:
map("Factory")
.to("com.util.wirebox.Factory")
.asSingleton()
.noAutowire();
map("something")
.toFactoryMethod(factory="Factory", method="buildStruct")
.methodArg(name="apple", ref="apple")
.methodArg(name="banana", ref="banana");
map("Foo").to("com.Foo").initArg(name="something", ref="something").asSingleton();
Original Answer:
Luis Majano's Answer:
// Map Binder so you can do utility methods
map("myBinder").toValue( this );
// Map the singleton maps
map("s1Map").toFactoryMethod("myBinder", "buildMap")
.methodArg(name="mapType", value="1");
// Map A service with a singleton map
map("Service").to("path")
.initArg(name="myMap", ref="s1Map");
He suggested me to file an ER, and here is it: http://coldbox.assembla.com/spaces/coldbox/support/tickets/1387-support-for--list--and--map--of-coldspring-xml
Let's break this down and see whats going on here.
1.) You are creating a new bean with an id of foo and its mapped to com.foo. To do this in wirebox use the map method and pass in whatever key you want to reference it by later. Next use the to method to map that key to a path
2.) You want to pass a map (structure) to the components init method. To do so just pass in a normal structure. This can be any value including other beans by using the initWith method.
<cfscript>
map("Foo")
.to("com.foo")
.initWith({apple=apple,banana=banana})
</cfscript>
You can also download the Coldbox plugin for ColdFusion builder. This has a nice little utility in that will allow you to right click on a coldspring definition file and convert it to wirebox. Hope this helps.
Related
Hi I had created eProductForm bean in the commerecefacades-beans.xml I added custom attribute of ProductData.
<bean class="de.hybris.platform.commercefacades.product.data.ProductData">
<property name="eProductForm" type="String"/>
</bean>
then in commercewebservice-beans.xml, I added the custom attribute of ProductWsDTO
<bean class="de.hybris.platform.commercewebservicescommons.dto.product.ProductWsDTO">
<property name="eProductForm" type="String"/></bean>
from SearchResultProductPopulator populated productdata of eProductForm from my search result.
target.setEProductForm(this.<String> getValue(source, "E_PRODUCT_FORM"));
PFB
dto mapping
<bean parent="fieldSetLevelMapping" id="productWsDTOFieldSetLevelMapping">
<property name="dtoClass" value="de.hybris.platform.commercewebservicescommons.dto.product.ProductWsDTO"/>
<property name="levelMapping">
<map>
<entry key="BASIC"
value="purchasable,stock,name,baseProduct,availableForPickup,code,url,price"/>
<entry key="DEFAULT"
value="summary,averageRating,purchasable,stock(DEFAULT),description,variantMatrix(DEFAULT),name,baseOptions(DEFAULT),baseProduct,availableForPickup,variantOptions(DEFAULT),code,url,price(DEFAULT),numberOfReviews,manufacturer,categories(BASIC),priceRange,multidimensional,configuratorType,configurable,tags"/>
<entry key="FULL"
value="summary,productReferences(FULL),classifications(FULL),averageRating,purchasable,volumePrices(FULL),variantType,stock(FULL),description,variantMatrix(FULL),name,baseOptions(FULL),baseProduct,availableForPickup,variantOptions(FULL),reviews(FULL),code,url,price(FULL),numberOfReviews,manufacturer,volumePricesFlag,futureStocks(FULL),images(FULL),categories(FULL),potentialPromotions(FULL),priceRange,multidimensional,configuratorType,configurable,tags,eProductForm,ePickledGroup"/>
</map>
</property>
</bean>
Below is the code I am calling Mapper.. While I debugged my code sourceresult is having product data of that custom attreibute. But I am not getting the eproductform in the WSDTO response.
final ProductSearchPageData<SearchStateData, ProductData> sourceResult = searchProducts(query, currentPage, pageSize, sort);
if (sourceResult instanceof ProductCategorySearchPageData)
{
return getDataMapper().map(sourceResult, ProductCategorySearchPageWsDTO.class, fields);
}
But in logs I see:
[EL Warning]: 2019-02-20 18:31:27.341--Ignoring attribute
[eProductForm] on class
[de.hybris.platform.commercewebservicescommons.dto.product.ProductWsDTO]
as no Property was generated for it.
As #Farrukh Chishti commented, the URL that you used probably used the DEFAULT level, which doesn't contain the attribute you added. For testing purposes, you can try to add the attribute to BASIC, DEFAULT, and FULL.
In the URL, you can specify the level, something like this:
https://localhost:9002/rest/v2/custom_site/stores?&fields=FULL
I have to say I always try to keep code simple and beautiful, mainly using design patterns when possible. Also, I am impressed I did not find anything related to this on the internet (except simple and very vague examples, mostly in javascript using json).
The scenario is: I have to parse/build concrete objects from a file, whose content may be XML, JSON and/or other formats. Heres an example:
Concrete object:
// Contains the common states for the entities
struct EntityModel
{
int hp;
int level;
int armor;
int speed;
// Other attributes...
};
class Entity
{
// Stuff (protected/public/private attributes and functions/methods)
private:
EntityModel* m_model; // Pointer to the model used (flyweight)
// Other attributes...
}
File (XML, in this case):
<entity name="Skeleton" class="Undead">
<attributes>
<hp value="150" />
<level value="10" />
<armor value="75" />
<speed value="15" />
<width value="32" />
<height value="32" />
<experience value="372" />
<texture value="skeleton.png" />
<intelligence value="skeleton.script" />
</attributes>
<restistances>
<resist type="Shock" value="30" />
<resist type="Fire" value="10" />
</resistances>
<attacks>
<spell name="Blizzard" mp="50" damage="130" distance="0" />
<spell name="Fireball" mp="30" damage="100" distance="0" />
</attacks>
<loot>
<drop item="Gold Coin" min="30" max="50" probability="1" />
<drop item="Ruby" min="0" max="2" probability="0.7" />
<drop item="Enchanted Sword" probability="0.25" />
</loot>
</entity>
This is the example of the relationship between an entity model and its file. There will also be other objects that have to be able to be parsed/built/created from their files.
Some may say that a design pattern is not really necessary in this case, as I have seen in a few implementations, although I do really believe there is one. The whole entity creation system involves the abstract factory, pool and flyweight patterns (a createEntity call is requested to the factory, which will see if a flyweight model has already been created and cached in the pool or create and cache the new model).
So, the question is: Are there any proper way to do that? Which one?
I'll be basing on the answer for this very case and adapt to the other object creations, as I have stated. In other words, I need a generic answer.
If this post is missing some information, or is in a wrong section, please forgive me as this is my first post here.
Thanks in advance.
Try the Boost Serialization Library. It has xml, binary, and text save formats. It's not too complicated and has good documentation.
I recommend a derivative of the Factory Design Pattern.
The pattern allows you to construct objects based on a criteria, such as a name or number. The traditional pattern creates objects based on a common base class.
Ok, I've searched everywhere for an answer to this. It is driving me nuts.
All I need to do is unmarshal a very simple webservice response. The only problem is, I am using a generated source file without the #XmlRootElement annotation. I am unable to edit this generated source file to add #XmlRootElement, either. I need to use it "as is".
This is the current code that I have, but it is resulting in an error shown at the bottom of this post. I have tried to use a JAXBElement wrapper but to no avail. Could somebody please give me the code I need? I have no idea how to use "QName"s etc.
This code below works great with classes that have #XmlRootElement:
MyGeneratedClass response = restTemplate.getForObject("url to webservice!"),
MyGeneratedClass.class);
return response
Sadly, it is producing this error in this case. Please help me to unmarshal the REST response!
Could not extract response: no suitable HttpMessageConverter found for response
type [MyGeneratedClass] and content type [application/xml;version=1]
I forgot about posting this many months ago and I should probably follow it up with the solution.
This solution also adds a cookie to the request headers, but you can ignore that.
In the case that a generated source file does not have #XmlRootElement annotation, you can unmarshal as follows:
// Cookie setting
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.set("Cookie", "myCookie=value");
HttpEntity<?> requestEntity = new HttpEntity(requestHeaders);
HttpEntity<String> response = restTemplate.exchange("web service url"),
HttpMethod.GET, requestEntity, String.class);
// Unmarshalling
JAXBElement<MyGeneratedClass> result =
(JAXBElement<MyGeneratedClass>) unmarshaller.unmarshal(
new StreamSource(new ByteArrayInputStream(response.getBody().getBytes())));
return result.getValue();
Spring's RestTemplate relies on HttpMessageConverter to unmarshal an object to XML. More specifically the Jaxb2RootElementHttpMessageConverter.canWrite method is responsible for the error you are seeing. Even if you were to override the canWrite method to not care whether the XmlRootElement annotation was present, JAXB would be unable to unmarshal the object.
One way around this limitation is to override Jaxb2RootElementHttpMessageConverter.canWrite to not check for the presence of the XmlRootElement annotation AND use EclipseLink's Moxy JAXB implementation with a mapping file. In the mapping file you can specify the equivalent of the XmlRootElement annotation, allowing you to use JAXB without using annotation's in your Java class.
Spring's RestTemplate is typically used together with org.springframework.oxm.jaxb.Jaxb2Marshaller. Unfortunately, that class has a property supportJaxbElementClass set to false by default :(
Spring nowhere documents this property, and numerous questions about RestTemplate/ JAXBELement on the Spring Forums have been unanswered :((((
Fortunately, you can configure Jaxb2Marshaller setting its property supportJaxbElementClass to true!
The following example configuration of RestTemplate will correctly marshall and unmarshall objects of type JAXBElement
<beans>
<bean id="httpClient" class="org.apache.http.impl.client.DefaultHttpClient">
<constructor-arg>
<bean class="org.apache.http.impl.conn.PoolingClientConnectionManager" />
</constructor-arg>
</bean>
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<constructor-arg>
<bean class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
<constructor-arg ref="httpClient" />
</bean>
</constructor-arg>
<!-- Configure the Rest template to translate between XML and JAXB -->
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
<property name="marshaller" ref="jaxbMarshaller" />
<property name="unmarshaller" ref="jaxbMarshaller" />
</bean>
<bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
</list>
</property>
</bean>
<bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="supportJaxbElementClass" value = "true"/>
<property name="packagesToScan">
<list>
<value>com.myorg.path.to.JAXB.classes</value>
</list>
</property>
</bean>
</beans>
I am using Apache ODE to write some simple BPEL's to connect 2 web services.
One of the WSDL files of my two services contains this complex type:
<types>
<t:schema targetNamespace="http://ws.panos.com/" version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<t:complexType name="myObject">
<t:sequence>
<t:element minOccurs="0" name="str" type="t:string" />
</t:sequence>
</t:complexType>
</t:schema>
How do I make a copy from a service return message (which is just a xsd:string) to the input of a message (inside "str" of type "myObject"?
I have tried to do this, but doesnt seem to work:
<assign name="assign_2">
<copy>
<from variable="wsA_output" part="return"/>
<to variable="wsC_input" part="arg0" query="/arg0/str"/>
</copy>
I always get a null string transfered. Help much appreciated.
The to-spec <to variable="..." part="..." query="..."/> is not valid in BPEL 1.1 nor BPEL 2.0. The correct equivalent expression is: <to>$wsC_input.arg0/arg0/str</to> or <to variable="wsC_input" part="arg0"><query>/arg0/str</query></to>. Please make also sure that you initialize the variable before assigning values to nested structures.
Just found the mistake. You are right, we need to query in order to find the field like this:
<assign name="assign_2">
<copy>
<from variable="wsA_output" part="return"/>
<to>$wsC_input.message/arg0/str</to>
</copy>
</assign>
Also, we need to initialize the variable like this:
<assign name="assign_init">
<copy>
<from>
<literal><arg0><str xmlns="">nothing</str></arg0></literal>
</from>
<to variable="wsC_input" part="arg0"></to>
</copy>
</assign>
The xmlns="" is needed when the default namespace in your bpel is different that the namespace in the receiving web service.
I am just writing these down for future reference :)
Again, thanks for you your answer.
Some links that could also help other people:
http://ode.apache.org/faq.html
http://jee-bpel-soa.blogspot.com/2009/08/manipulating-ws-bpel-variables-and.html
I have xml that part of structure looks like this:
<IDList>
<ValuesList ID="1">
<Value>1</Value>
<Value>2</Value>
<Value>3</Value>
</ValuesList>
<ValuesList ID="2">
<Value>1</Value>
<Value>2</Value>
<Value>3</Value>
</ValuesList>
</IDList>
What should be model classes for xmlserializer, so I could deserialize it properly?
On the level of IDList it's quite easy:
[XmlArray("IDList")]
[XmlArrayItem("ValuesList")]
public List<CValuesList> idList = new List<CValuesList>();
but how can I do it when the array element has extra xml attribute?
I tried to do ot in the way shown here:
http://www.codemeit.com/xml/c-xmlserializer-add-an-attribute-to-an-array-element.html
but it didn't worked for me. The elements of the array haven't been deserialized.
There is no simple way to do that.
A good solution would be to create an object that contains a list and your properties and inherit/implements IXmlSerializable.
I've seen some kind of quick and dirty way on this site: http://funcakes.posterous.com/adding-elements-to-lists-in-the-xmlserializer. Since the object doesn't inherit from ISerializable, it won't be serialized as a list by the serializer.