How to Add entity to Dictionary Object Initializer? - c#-4.0

I need to pass html attributes.
It is possible to pack into one expression code some like this?
var tempDictionary = new Dictionary<string, object> {
{ "class", "ui-btn-test" },
{ "data-icon", "gear" }
}.Add("class", "selected");
or
new Dictionary<string, object> ().Add("class", "selected").Add("diabled", "diabled");
?

What you are referring to is known as method chaining. A good example of this is the StringBuilder's Append method.
StringBuilder b = new StringBuilder();
b.Append("test").Append("test");
This is possible because the Append method returns a StringBuilder object
public unsafe StringBuilder Append(string value)
But, in your case, the Add method of Dictionary<TKey, TValue> is marked void
public void Add(TKey key, TValue value)
Therefore, method chaining is not supported. However, if you really wanted to use method chaining when adding new items, you could always roll your own:
public static Dictionary<TKey, TValue> AddChain<TKey, TValue>(this Dictionary<TKey, TValue> d, TKey key, TValue value)
{
d.Add(key, value);
return d;
}
Then you could write the following code:
Dictionary<string, string> dict = new Dictionary<string, string>()
.AddChain("test1", "test1")
.AddChain("test2", "test2");

Related

Method inside "When" actually being called

When I am testing a class A (TestNG) which uses some methods from some other class Helper Class
I am mocking the helper class(Mockito) for testing class A.
but when(helper.methodUsedByClassA(value)).thenReturn(new HashMap>())
this line of code is actually calling helper.methodUsedByClassA and a null pointer exception is thrown (because of data I am using for testing is not valid)
why is this happening? Why would the method name inside mockito "when" actually be called ?
class ATest{
#Mock
private Helper helper;
private A target;
#BeforeTest
public void setUp() {
MockitoAnnotations.initMocks(this);
this.target = new UpdateDigicatKdpAsinUtil(helper);
}
#Test(dataProvider = "data")
public void testMethod(List<String> value) {
when(helper.methodUsedByClassA(value)).thenReturn(new HashMap<String, List<String>>({{put("test", new ArrayList<>())}}));
}
#DataProvider
public Object[][] data(){
List<String> list = new ArrayList<>();
return new Object[][]
{
{list}
}
}
class Helper{
public Map<String, List<String>> methoUsedByClassA(int value) {
//This method is being executed because it is mentioned inside "when"
}
}
I guess you get an NPE because helper is NULL.
The problem is that the #Mock annotation isn't processed and because of that, the variable helper isn't initialized.
You have to annotate the test class with #RunWith(MockitoJUnitRunner.class). MockitoJUnitRunner will process the #Mock annotation and create the mock.

broadleaf override controller method

I'm new on broadleaf.
I have problem, I wanted to obscure the method that removes my order in admin:
I create controller :
public class NewOrderController extends AdminBasicEntityController {
private static final Logger LOGGER = Logger.getLogger(NewOrderController.class);
protected static final String SECTION_KEY = "order";
#Override
protected String getSectionKey(Map<String, String> pathVars) {
if (super.getSectionKey(pathVars) != null) {
return super.getSectionKey(pathVars);
}
return SECTION_KEY;
}
#Override
#RequestMapping(
value = {"/{id}/delete"},
method = {RequestMethod.POST}
)
public String removeEntity(HttpServletRequest request, HttpServletResponse response, Model model, Map<String, String> pathVars, String id, EntityForm entityForm, BindingResult result, RedirectAttributes ra) throws Exception {
LOGGER.info("wywołanie nadpisane metody: " + NewOrderController.class.toString());
return "String";
}
}
in applicationContext-admin.xml
add :
All the time it calls me the not overwritten method.
When you create a controller, the bean must be in the servlet context, not in the root context. If you are modifying applicationContext-admin.xml then you are actually adding the bean to the root context.
Add your bean to applicationContext-servlet-admin.xml or add a new <component-scan> entry into applicationContext-servlet-admin.xml to scan your new bean.
One more thing: you likely do not want to override the entire AdminBasicEntityController and it looks like you just want to override /order/* methods. In that case, you should annotate your controller with #Controller and add an #RequestMapping for your section key like this:
#Controller
#RequestMapping("/" + SECTION_KEY)
public class NewOrderController extends AdminBasicEntityController {
private static final Logger LOGGER = Logger.getLogger(NewOrderController.class);
protected static final String SECTION_KEY = "order";
#Override
protected String getSectionKey(Map<String, String> pathVars) {
if (super.getSectionKey(pathVars) != null) {
return super.getSectionKey(pathVars);
}
return SECTION_KEY;
}
#Override
#RequestMapping(
value = {"/{id}/delete"},
method = {RequestMethod.POST}
)
public String removeEntity(HttpServletRequest request, HttpServletResponse response, Model model, Map<String, String> pathVars, String id, EntityForm entityForm, BindingResult result, RedirectAttributes ra) throws Exception {
LOGGER.info("wywołanie nadpisane metody: " + NewOrderController.class.toString());
return "String";
}
}

Cannot set readonly property: class for class in groovy when initializing with map

I am trying to create a class and initialize all the values with a default value. So i have this pojo in groovy, and i have created initializeWithDefaults method to initialize all the values. I am trying to pass map in the constructor
class MDS {
String id
String mdsName
String name
String mdsType
String mdsContext
String mdsDateTime
String mdsDomain
public static void initializeWithDefaults() {
MDS dataSegmentIdDef = new MDS()
Map<String, Object> prop = dataSegmentIdDef.properties
prop.each { Map.Entry entry->
entry.value = "default-${entry.key}"
}
MDS dataSegmentId = new MDS(prop)
}
}
but i keep getting the error
in thread "main" groovy.lang.ReadOnlyPropertyException: Cannot set readonly property: class for class: com.ambuj.domain.MDS
You are getting the error, as you are trying to override a class propery of a *HashMap which is provided as a getClass() and of course not writeable.
You should take care, what properties you are trying to copy. A simple experiment in Groovy console looked like (pay attention to !prop.synthetic):
class MDS {
// your props
#Override
String toString() {
"$id:$mdsName:$mdsDomain"
}
static void initializeWithDefaults() {
MDS mds = MDS.class.declaredFields.inject( new MDS() ){ MDS mds, prop ->
if( !prop.synthetic ) mds[ prop.name ] = "default.$prop.name"
mds
}
println mds
}
}
MDS.initializeWithDefaults()
and the output:
Result: default.id:default.mdsName:default.mdsDomain
One quick fix is to filter out the properties that already have a value using the findAll method.
public static void initializeWithDefaults() {
MDS dataSegmentIdDef = new MDS()
Map<String, Object> prop = dataSegmentIdDef.properties.findAll { !it.value }
prop.each { Map.Entry entry->
entry.value = "default-${entry.key}"
}
MDS dataSegmentId = new MDS(prop)
}
I'd also recommend replacing the each with a collectEntries
Map<String, Object> prop = dataSegmentIdDef.properties
.findAll { !it.value }
.collectEntries { key, noValue -> [key, "default-$key"] }

HashMap is empty after deserialization with Jersey and Jackson

I have a REST web service using Jersey 1.17.1 and Jackson 1.9.2.
The API looks like this:
public class PlayerRequest {
private String language;
private String playerId;
private Map<String, String> params;
}
When this service is called by other component, the params map is received empty:
PlayerRequest [language=null, playerId=100036343, params={}]
Original request from other component:
PlayerRequest [language=null, playerId=100036343, params={context=mobile, countrycode=SE, partnerskin=8, locale=en_GB, ipaddress=62.209.186.13}]
Why is the HashMap empty after the deserialization?
In your PlayerRequest class, create a method annotated with #JsonAnySetter, as following:
#JsonAnySetter
public void set(String key, String value) {
params.put(key, value);
}
This method works as a fallback handler for all unrecognized properties found in the JSON content.
To use the above mentioned approach, ensure the params field is being initialized:
private Map<String, String> params = new HashMap<String, String>();
So, your PlayerRequest class would be like:
public class PlayerRequest {
private String language;
private String playerId;
private Map<String, String> params = new HashMap<String, String>();
public PlayerRequest() { }
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public String getPlayerId() {
return playerId;
}
public void setPlayerId(String playerId) {
this.playerId = playerId;
}
public Map<String, String> getParams() {
return params;
}
public void setParams(Map<String, String> params) {
this.params = params;
}
#JsonAnySetter
public void set(String key, String value) {
params.put(key, value);
}
}
Fixed by implementing and adaptor(javax.xml.bind.annotation.adapters.XmlAdapter) and annotated the map in api with #XmlJavaTypeAdapter

#XmlPath(".") conflicts with #XmlAdapter

having this Jaxb Xml definition, i try to remove the Map Elements Wrapper by adding #XmlPath(".") but it cause exception during the unmarchaling
#XmlRootElement
public abstract class ViewElement{
#XmlJavaTypeAdapter(value=EventAdapter.class)
public Map<Event, String> getEvents() {
}
private transient Class entityType;
public Class getEntityType() {
return entityType;
}
}
And the EventAdapter is
public class EventAdapter extends XmlAdapter<EventAdapter.AdaptedMap, Map<Event, String>> {
public static class AdaptedMap {
#XmlVariableNode("key")
List<AdaptedEntry> entries = new ArrayList<AdaptedEntry>();
}
public static class AdaptedEntry {
#XmlTransient
public String key;
#XmlValue
public String value;
}
.....
}
my output was
<element>
<events>
<onCellEdit>do some thing<onCellEdit>
</events>
<entityType>com.agitech.erp.model.erp.ErpFolder</entityType>
<element>
I try to remove the <events> tag by adding #XmlPath(".")
#XmlPath(".")
#XmlJavaTypeAdapter(value=EventAdapter.class)
public Map<Event, String> getEvents() {
}
The output is good
<element>
<onCellEdit>do some thing<onCellEdit>
<entityType>com.agitech.erp.model.erp.ErpFolder</entityType>
<element>
but the unmarchaling faileds
Caused by: Exception [EclipseLink-3002] (Eclipse Persistence Services - 2.6.0.v20140809-296a69f): org.eclipse.persistence.exceptions.ConversionException
Exception Description: The object [], of class [class java.lang.String], from mapping [org.eclipse.persistence.oxm.mappings.XMLDirectMapping[entityType-->view.entityType/text()]] with descriptor [XMLDescriptor(com.agitech.erp.view.BeanView --> [DatabaseTable(view), DatabaseTable(viewFrame), DatabaseTable(viewElement)])], could not be converted to [class java.lang.Class].
Internal Exception: java.lang.ClassNotFoundException:
at org.eclipse.persistence.exceptions.ConversionException.couldNotBeConvertedToClass(ConversionException.java:95)
at org.eclipse.persistence.internal.helper.ConversionManager.convertObjectToClass(ConversionManager.java:446)
Debuging Jaxb bring me to the line
org.eclipse.persistence.internal.oxm.XMLDirectMappingNodeValue
public void endElement(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord) {
...
line 205 unmarshalRecord.setAttributeValue(convertedValue, xmlDirectMapping);
}
During the unmarchaling of entityType value, the UnmarshalRecordImpl.currentObj contains the EventAdapter instead of the parent element
I modify org.eclipse.persistence.internal.oxm.record.UnmarshalRecordImpl
public XPathNode getNonAttributeXPathNode(String namespaceURI, String localName, String qName, Attributes attributes) {
....
if(null == resultNode && null == nonPredicateNode) {
// ANY MAPPING
resultNode = xPathNode.getAnyNode();
// by default it return the EventAdapter, changing it to NULL fix my problem
}
....
}
Not a safe solution
I have been able to reproduce the issue that you are seeing, but haven't yet worked out the cause. You can use the following bug to track the progress on this issue:
http://bugs.eclipse.org/457169
After trying a lot of things, I was able to find a workaround for this issue. I thought of posting here the same so it can be helpful to someone else in the future. The lead has confirmed the issue around 5 years ago but seems like they have not fixed it and I was facing a similar issue.
Basically, we can use the beforeMarshal and afterUnmarshal methods to change the values in the fields.
You need to create a field List<Object> with #XmlAnyElement(lax=true) along with Map<String,Object>.
Remove the #XmlPath(".") and the XMLAdapter class.
Mark the field Map<String, Object> with #XmlTransient.
Now within the beforeMarshal and afterMarshal fields, you can exchange the data. During the unmarshal in beforeunmarshal, all the unknown field values will be present within the List<Object> loop over it and add it to the Map<String, Object>.
Similarly during the marshaling, you can move the values Map<String, Object> to List<Object> by creating the DOM elements.
Marshaling all values are added to root as DOM Elements are present and during Unmarshaling known values are read first and then-unknown values are stored within List<Object> due to #XmlAnyElement.
I have created an example using the Customer class, you can modify it accordingly for your need.
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, visible = true, property = "isA")
#JsonInclude(Include.NON_NULL)
#JsonIgnoreProperties(ignoreUnknown = true)
#XmlRootElement(name = "Customer")
#XmlType(name = "Customer", propOrder = {"name", "age", "otherElements"})
#XmlAccessorType(XmlAccessType.FIELD)
#Getter
#Setter
#AllArgsConstructor
#ToString
#NoArgsConstructor
public class Customer {
#XmlTransient
private String isA;
private String name;
private String age;
#XmlAnyElement(lax = true)
#JsonIgnore
private List<Object> otherElements = new ArrayList<>();
#JsonIgnore
#XmlTransient
private Map<String, Object> userExtensions = new HashMap<>();
#JsonAnyGetter
#JsonSerialize(using = CustomExtensionsSerializer.class)
public Map<String, Object> getUserExtensions() {
return userExtensions;
}
#JsonAnySetter
public void setUserExtensions(String key, Object value) {
userExtensions.put(key, value);
}
private void beforeMarshal(Marshaller m) throws ParserConfigurationException {
System.out.println("Before Marshalling User Extension: " + userExtensions);
ExtensionsModifier extensionsModifier = new ExtensionsModifier();
otherElements = extensionsModifier.Marshalling(userExtensions);
System.out.println("Before Marshalling Final Other Elements " + otherElements);
userExtensions = new HashMap<>();
}
private void afterUnmarshal(Unmarshaller m, Object parent) throws ParserConfigurationException {
System.out.println("After Unmarshalling : " + otherElements);
ExtensionsModifier extensionsModifier = new ExtensionsModifier();
userExtensions = extensionsModifier.Unmarshalling(otherElements);
otherElements = new ArrayList();
}
}
You can refer the creation of DOM ELEMENTS here:https://stackoverflow.com/a/24239105/7584240
You can refer my complete answer here: https://stackoverflow.com/a/67923216/7584240

Resources