Instantiate a field level HashMap in JCodeModel - jcodemodel

I want to declare and instantiate a HashMap in one go in JCodeModel.
I do:
jc.field(JMod.PRIVATE, HashMap.class, "initAttributes");
which declares it but doesn't instantiate it. How do I instantiate it?
Thanks

In the simplest case, you can just append the initialization directly to your creation of the field:
jc.field(JMod.PRIVATE, HashMap.class, "initAttributes")
.init(JExpr._new(codeModel.ref(HashMap.class)));
Some further hints:
Considering that you should usually program to an interface, it is a good practice to declare the variable using a type that is "as basic as possible". You should hardly ever declare a variable as
private HashMap map;
but basically always only as
private Map map;
because Map is the interface that is relevant here.
You can also add generics in JCodeModel. These usually involve some calls to narrow on certain types. It is a bit more effort, but it will generate code that can be compiled without causing warnings due to the raw types.
An example is shown here. (It uses String as the key type and Integer as the value type of the map. You may adjust this accordingly)
import java.util.HashMap;
import java.util.Map;
import com.sun.codemodel.CodeWriter;
import com.sun.codemodel.JClass;
import com.sun.codemodel.JCodeModel;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JExpr;
import com.sun.codemodel.JMod;
import com.sun.codemodel.writer.SingleStreamCodeWriter;
public class InitializeFieldInCodeModel
{
public static void main(String[] args) throws Exception
{
JCodeModel codeModel = new JCodeModel();
JDefinedClass definedClass = codeModel._class("com.example.Example");
JClass keyType = codeModel.ref(String.class);
JClass valueType = codeModel.ref(Integer.class);
JClass mapClass =
codeModel.ref(Map.class).narrow(keyType, valueType);
JClass hashMapClass =
codeModel.ref(HashMap.class).narrow(keyType, valueType);
definedClass.field(JMod.PRIVATE, mapClass, "initAttributes")
.init(JExpr._new(hashMapClass));
CodeWriter codeWriter = new SingleStreamCodeWriter(System.out);
codeModel.build(codeWriter);
}
}
The generated class looks as follows:
package com.example;
import java.util.HashMap;
import java.util.Map;
public class Example {
private Map<String, Integer> initAttributes = new HashMap<String, Integer>();
}

Related

Spring-Boot Properties with nested Map

I have a application.properties file that needs some dynamic keys, which allow at least one level of nesting. In technical terms, the application starts and I am able to read those values, but the metadata doesn't seem to work correctly, because IntelliJ Ultimate is giving me some errors:
Cannot resolve property 'foo' in java.util.Map
# Static property
com.company.version=1.0
# Dynamic property, starting after products
com.company.products.first.foo=firstFoo
com.company.products.first.bar=firstBar
com.company.products.second.foo=SecondFoo
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
#Configuration
#ConfigurationProperties(prefix = "com.company")
public class Properties {
private String version;
private Map<String, Map<String, ArrayList<String>>> products = new HashMap<>();
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public Map<String, Map<String, ArrayList<String>>> getProducts() {
return products;
}
public void setProducts(Map<String, Map<String, ArrayList<String>>> products) {
this.products = products;
}
}
In additional I would like to know what the best practice would be to read those values. For "normal" static properties I used the Environment that I autowire in the constructor, but that is – as far as I know – unable to read the products map. Thats why I autowire my Properties class and use the getProducts function.
Thanks a lot for your help!
Might this work?
# Dynamic property, starting after products
com.company.products.first[foo]=firstFoo
com.company.products.first[bar]=firstBar
com.company.products.second[foo]=SecondFoo
If you want more than item in your array list do:
com.company.products.first[foo]=firstFoo,secondFoo
However, I've come massively unstuck in the past using deeply nested maps of maps. Maybe if you can declare a concrete class instead?
Also, I'd suggest using interfaces rather than concrete collections (e.g. List rather than ArrayList, or maybe even a Set to prevent duplicates?)

How to serialize polymorphic list with element type names as xml element names in Jackson

I have a list of objects with common base class. I wish to serialize (and deserialize) this list so that each list element is serialized with its root element equal to the name of the type and not have the wrapping object around the element.
I tried using JsonTypeInfo with Id.Name and As.WRAPPER_OBJECT which produces an XML with proper element names but (obviously) with another layer of XML elements (from the list itself).
package zm.study.xmlserialize.jackson;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
public class JacksonListTest4 {
public static class L {
public List<A> as = new ArrayList<>();
}
#JsonTypeInfo(use = Id.NAME, include=As.WRAPPER_OBJECT)
#JsonSubTypes({
#JsonSubTypes.Type(value=B.class, name="b"),
#JsonSubTypes.Type(value=C.class, name="c"),
})
public static abstract class A {
}
public static class B extends A {
}
public static class C extends A {
}
#Test
public void test() throws Exception
{
L l = new L();
l.as.add(new B());
l.as.add(new C());
new XmlMapper().enable(SerializationFeature.INDENT_OUTPUT)
.writeValue(System.out, l);
}
}
I would like to get:
<L>
<as>
<b/>
<c/>
</as>
</L>
Instead I get:
<L>
<as>
<as>
<b/>
</as>
<as>
<c/>
</as>
</as>
</L>
If you know what you want it to look like you're better off writing an XSD and then using a tool like JAXB to create a serialization/deserialization Java object.

Spring + QueryDsl + Mockito: How to write a unit test case for a simple function

I have the following function in my service.
public boolean checkNameUnique(String name) {
QEntity qEntity = QEntity.entity;
BooleanExpression nameUniquePredicate = qEntity.name.eq(name);
long count = entityReadRepository.count(nameUniquePredicate);
return count == 0;
}
It just checks if the name already exists in db. That needs to be unique, so it returns true if does not already exist and false if it does.
Now how do I write a mockito unit test case for this? I am new to Mockito and writing unit test cases, hence the question.
My reading on Mockito has lead me to write something on the lines of
when(entityReadRepository.count(nameUniquePredicate)).thenReturn(1);
and then call the function to be tested. But that doesn't make any sense.
Entity is Hibernate entity which corresponds to a table in the DB
entityReadRepository extends JpaRepository and QueryDslPredicateExecutor. QEntity is the Q object generated by QueryDsl's plugin.
A unit test would normally mock out any external dependencies, in your case entityReadRepository. If you want to do actual db call it would be classed as integration test.
Your method should return two different values depending on the entityReadRepository response and this is what you would stub in order to unit test it. You were on a good path trying:
when(entityReadRepository.count(any(BooleanExpression.class))).thenReturn(1l);
The problem you have is that you have a lot of static calls and objects in your method and that can't be handled gracefully. One option is to use tools like Powermockito where you can mock behaviour of static methods. If you prefer to stick with mockito you could extract static piece of code to a separate method and create a spy of your class under test:
package com.slavpilus;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
#RunWith(MockitoJUnitRunner.class)
public class TPresenterTest {
#InjectMocks
#Spy
private ClassUnderTest target = new ClassUnderTest();
#Before
public void setUp() {
doReturn(null).when(target).getUniqueNamePredicate();
}
#Mock
private YourRepositoryDependency entityReadRepository;
#Test
public void checkNameUniqueShouldBeTrueIfNameNotInDatabase() {
when(entityReadRepository.count(any())).thenReturn(0l);
boolean isUnique = target.checkNameUnique("anyName");
Assert.assertTrue(isUnique);
}
#Test
public void checkNameUniqueShouldBeFalseIfNameFoundInDatabase() {
when(entityReadRepository.count(any())).thenReturn(1l);
boolean isUnique = target.checkNameUnique("anyName");
Assert.assertFalse(isUnique);
}
}
and your production code would look something like that:
public boolean checkNameUnique(String name) {
BooleanExpression nameUniquePredicate = getUniqueNamePredicate();
long count = entityReadRepository.count(nameUniquePredicate);
return count == 0;
}
protected BooleanExpression getUniqueNamePredicate() {
QEntity qEntity = QEntity.entity;
return qEntity.name.eq(name);
}
This approach however leaves you with some code untested as getUniqueNamePredicate method is skipped entirely during the test execution.

Error in code at -> when(list.size()).thenReturn(10) while running Unit Test

The errors are as follows:
The method thenReturn(Dimension) in the type OngoingStubbing is not applicable for the arguments (int)
The method size() from the type Component is deprecated
#Test
public void Test() {
List list = mock(List.class);
when(list.size()).thenReturn(10);
assertEquals(10, list.size());
}
Maybe you are importing import java.awt.List; instead of import java.util.List;

Where does the filter for Ehcache 3 simple web page caching call the cache?

I am trying to cache a simple web page in Ehcache. Thanks to some help from another SO post I discovered that I need to implement my own filter based on Ehcache 2 code. When I look at the filter I don't understand it. Where does it ever call the cache to return a value? Here is my implementation (quite possibly wrong):
package com.sentiment360.pulse.cache;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.bind.Element;
import org.ehcache.Cache;
import org.ehcache.CacheManager;
import org.ehcache.config.Configuration;
import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManager;
import org.ehcache.core.Ehcache;
import org.ehcache.event.CacheEvent;
import org.ehcache.event.CacheEventListener;
import org.ehcache.xml.XmlConfiguration;
import javax.servlet.http.HttpServletRequest;
public class SimplePageCachingFilter implements CachingFilter {
public static final String DEFAULT_CACHE_NAME = "SimplePageCachingFilter";
private Logger LOG = Logger.getLogger(this.getClass().getName());
private String cacheName="basicCache";
protected String getCacheName() {
if (cacheName != null && cacheName.length() > 0) {
LOG.log(Level.INFO,"Using configured cacheName of {}.", cacheName);
return cacheName;
} else {
LOG.log(Level.INFO,"No cacheName configured. Using default of {}.", DEFAULT_CACHE_NAME);
return DEFAULT_CACHE_NAME;
}
}
protected CacheManager getCacheManager() {
return CacheManager.getInstance();
}
protected String calculateKey(HttpServletRequest httpRequest) {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append(httpRequest.getMethod()).append(httpRequest.getRequestURI()).append(httpRequest.getQueryString());
String key = stringBuffer.toString();
return key;
}
}
See in the super class.
But you do implements CachingFilter ?! Where is that interface? It does look like you were trying to "copy" the previous Ehcache's SimplePageCachingFilter, right? You would also need to port that abstract super class (and maybe read a little about javax.servlet.Filter, in case these aren't entirely clear...)
Now, you may also want to ping the dev team on the Ehcache Dev Google group about this. They should be able to provide pointers and then help with the implementation. Looks like a good idea for a future pull request! :)

Resources