Why use terminal to start jar and idea to start are inconsistent - intellij-14

Using idea to start the springboot program cannot get the value of the automatic configuration class
For example, the following code,PassConfig.getKey() is null:
private static final String encryptionFormat = String.format("to_base64(aes_encrypt(?,'%s'))", PassConfig.getKey());
#Component
#ConfigurationProperties(prefix = "mybatis.key")
public class PassConfig {
private static String key;
public static String getKey() {
return key;
}
public void setKey(String key) {
PassConfig.key = key;
}
}
At present, it can be solved by org.springframework.beans.factory.annotation.Value annotations.
#Value("${mybatiskey}")
public void setKey(String key) {
PassConfig.key = key;
}

In PassConfig you specified the prefix to be "mybatis.key" and the String as key
According to this, in application.properties your property is expected to be mybatis.key.key (prefix.variablename)
in setKey you specified the #Value to take mybatiskey from application.properties
property names should be consistent. It is null because most probably you don't have the propery mybatis.key.key in your application.properties file.

Related

How to see arguments when creating a new class?

When creating a new class or method I used to be able to see the parameters needed. But, now they don't come up anymore. How do I view parameters when creating a class?
Running the latest windows version.
public class Main {
public static void main(String args[]) {
Case theCase = new Case("Default", "Corsair", "500W");
}
}
public class Case {
private String model;
private String manufacturer;
private String powerSupply;
public Case(String model, String manufacturer, String powerSupply,) {
this.model = model;
this.manufacturer = manufacturer;
this.powerSupply = powerSupply;
}
public void pressPowerButton() {
System.out.println("Power button pressed");
}
public String getModel() {
return model;
}
public String getManufacturer() {
return manufacturer;
}
public String getPowerSupply() {
return powerSupply;
}
}
When making theCase I can't see what my parameters are and have to move to the "Case" class back and forth
You can explicitly call Parameter Info action which is usually mapped to Ctrl/(Cmd) - p.
Nevermind in order to see the parameters as you type you must type them while in the editor without moving your cursor.

Immutables wrapper as string in Jackson

How can I jackson serialize a wrapper type to and from a string?
I merged the following from two different examples their website. But the HostName type is serialized/deserialized as
{ "name" : "my.host.name.com" }
when I want it to be simply the string
"my.host.name.com"
Note that I have a lot of XName types, hence the use of the Immutables wrapper. So I would prefer a solution that keeps the amount of boiler plate down.
#Value.Immutable #AbstractName.Wrapper
public abstract class _HostName extends AbstractName { }
...
public abstract class AbstractName {
#JsonSerialize
#JsonDeserialize
#Value.Style(
// Detect names starting with underscore
typeAbstract = "_*",
// Generate without any suffix, just raw detected name
typeImmutable = "*",
// Make generated public, leave underscored as package private
visibility = Value.Style.ImplementationVisibility.PUBLIC,
// Seems unnecessary to have builder or superfluous copy method
defaults = #Value.Immutable(builder = false, copy = false))
public #interface Wrapper {}
#Value.Parameter
public abstract String name();
#Override
public String toString() { return name(); }
}
I've got this to work like below. There's an extra annotation on my name types. It's not my favorite, but it works.
#JsonDeserialize(as=HostName.class)
#Value.Immutable #AbstractName.Wrapper
public abstract class _HostName extends AbstractName { }
...
public abstract class AbstractName {
#Value.Style(
// Detect names starting with underscore
typeAbstract = "_*",
// Generate without any suffix, just raw detected name
typeImmutable = "*",
// Make generated public, leave underscored as package private
visibility = Value.Style.ImplementationVisibility.PUBLIC,
// Seems unnecessary to have builder or superfluous copy method
defaults = #Value.Immutable(builder = false, copy = false))
public #interface Wrapper {}
#JsonValue
#Value.Parameter
public abstract String name();
#Override
public String toString() { return name(); }
}
Here's a little program to run it:
public static void main(String... args) throws IOException {
ObjectMapper json = new ObjectMapper();
String text = json.writeValueAsString(HostName.of("my.host.name.com"));
System.out.println(text);
HostName hostName = json.readValue(text, HostName.class);
System.out.println(hostName);
}

How organize and test this code?

I have a conceptual doubt about how to organize and test code like the following, where a call to an auxiliary method is the first instruction of all the public methods of the class. My idea is make the code clean and testable.
The code is an example to try to illustrate this by a class "cache". This class has an optional prefix will be applied to all keys in the cache if it is set.
import java.util.HashMap;
public class Cache {
private HashMap<String, Integer> inMemoryCache;
private String prefix;
public Cache() {
this.inMemoryCache = new HashMap<String, Integer>();
prefix = null;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public int getValue(String key) throws NullPointerException {
String prefixedKey = applyPrefixOrDefault(key);
return inMemoryCache.get(prefixedKey);
}
public void setValue(String key, int value) {
String prefixedKey = applyPrefixOrDefault(key);
inMemoryCache.put(prefixedKey, value);
}
public boolean isCached(String key) {
String prefixedKey = applyPrefixOrDefault(key);
return inMemoryCache.containsKey(prefixedKey);
}
private String applyPrefixOrDefault(String key) {
if (prefix == null) {
return key;
} else {
return prefix + key;
}
}
public static void main (String[] arg) {
Cache cache = new Cache();
cache.setPrefix("global:");
cache.setValue("id", 4);
int value = cache.getValue("id");
System.out.println(value);
}
}
This code poses two questions to me:
If I had many methods accessing the inner hash table, would it be right separate the behavior of the cache in one class and the behavior of the prefix in other?
What would be the cleanest way to test this? Test the getValue, setValue and isCached is simple if we do not consider the prefix. With the prefix we need to test two things, the correct internal behavior of the cache and we need test also that all methods call applyPrefixOrDefault before accessing the data.
This is a common use case and I'm sure there must be some design pattern to organize this. Any idea?
To my opinion, what we miss here is a constructor that let us set the state of the cache. So I would add one as follows:
public Cache() {
this(null, new HashMap<String, Integer>());
}
public Cache(String prefix, Map<String, Integer> cache) {
this.prefix = prefix;
this.inMemoryCache = cache;
}
With this new constructor, you should be able to write test-cases for every possible cache state. I would also change the visibility of the applyPrefixOrDefault method to protected or package so that test code can access it. For instance, to test the GetValue method, I would write:
public class EmptyCacheTests {
private final Map<String, Integer> memory;
private final String prefix;
private final Cache cache;
public EmptyCacheTests() {
this.memory = new HasMap<String, Integer>();
this.prefix = "foo";
this.cache = new Cache(prefix, memory);
}
public void testGetValue() {
String key = this.cache.applyPrefixOrDefault("bar")
this.memory.put(key, 50);
result = this.cache.getValue("bar");
assertEquals(50, result, "The value retrieved is wrong!");
}
}
The point here, it to allow the test to set up the internal state of the cache, so that we can then test against many different ones.

Can I refer to properties directly in entity constructor with EclipseLink?

EclipseLink version is 2.5.1
We've moved from GlassFish web-server to TomCat. This made us switch to static weaving because with TomCat dynamic weaving doesn't really work that easy.
Now that static weaving works, it seems to work quite a bit differently.
If I have an entity which sets some property directly in the constructor:
class Entity {
#Column
private String name;
public Entity() {
name = "something";
}
public String getName() {
return name;
}
}
Long story short this test will fail:
Entity e = new Entity();
assertEquals("something", e.getName()); // e.getName() returns null
This happens because getName(), after weaving, is not returning this.name anymore. Instead it calls a routing for initialization (if it's needed) and (I guess) gets the value of the property from some underlying HashMap.
But constructor is not being weaved, I even have looked into the sources of weaver and seems to be explicitly opting out of this:
/**
* Construct a MethodWeaver and allow it to process the method.
*/
#Override
public MethodVisitor visitMethod(int access, String methodName, String desc, String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, methodName, desc, signature, exceptions);
if (!alreadyWeaved) {
// skip constructors, they will not changed
if (!"<init>".equals(methodName) && !"<cinit>".equals(methodName)) {
// remaining modifications to the 'body' of the class are
// delegated to MethodWeaver
mv = new MethodWeaver(this, methodName, desc, mv);
}
}
return mv;
}
The question is, maybe I miss something here? Is it the actual reality with EclipseLink 2.5.1 that you can't use properties directly in entity's own ctor? (and it's not even mentioned anywhere, not googlable at least)
It turns out yes, we can.
But there was a problem that led us to the property being not visible to the getter.
We actually have MappedSuperclass inheritance here and we were shadowing this field in the child class. Essentially this:
class A {
#Column()
protected String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
class B extends A {
#Column()
protected String name;
// no #Override here
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
So we were just shadowing the property.

Morphia Interface for List of enum does not work (unmarshalling)

I have the following interface
#JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "className")
public interface InfoChartInformation {
public String name();
}
And the following implementation (enum):
public class InfoChartSummary {
public static enum Immobilien implements InfoChartInformation {
CITY, CONSTRUCTION_DATE;
}
public static enum Cars implements InfoChartInformation {
POWER, MILEAGE;
}
}
Then I use all of It in the following entity:
#Entity(noClassnameStored = true)
#Converters(InfoChartInformationMorphiaConverter.class)
public class TestEntity{
#Id
public ObjectId id;
#Embedded
public List<InfoChartInformation> order;
}
Jackson, in order to detect the type on the unmarshalling time, will add to every enum on the list the className.
I thought morphia would do the same, but there's no field className in the List of enum and the unmarshalling cannot be done correctly: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.ClassCastException: java.lang.String cannot be cast to com.mongodb
.DBObject
I guess the correct behavior should be to save all the enum route (package+name), not only the enum name. At least in that way the unmarshalling could be performed. There's a way morphia supports that by default or I need to create my own converter (similar to this) ?
I tried creating a Custom Converter:
public class InfoChartInformationMorphiaConverter extends TypeConverter{
public InfoChartInformationMorphiaConverter() {
super(InfoChartInformation.class);
}
#Override
public Object decode(Class targetClass, Object fromDBObject, MappedField optionalExtraInfo) {
if (fromDBObject == null) {
return null;
}
String clazz = fromDBObject.toString().substring(0, fromDBObject.toString().lastIndexOf("."));
String value = fromDBObject.toString().substring(fromDBObject.toString().lastIndexOf(".") + 1);
try {
return Enum.valueOf((Class)Class.forName(clazz), value);
} catch (ClassNotFoundException e) {
return null;
}
}
#Override
public Object encode(final Object value, final MappedField optionalExtraInfo) {
return value.getClass().getName() + "." + ((InfoChartInformation) value).name();
}
}
Then, I added the converter information to morphia morphia.getMapper().getConverters().addConverter(new InfoChartInformationMorphiaConverter());.
However, when serializing (or marshalling) the object to save it into the database, the custom converter is ignored and the Enum is saved using the default Morphia converter (only the enum name).
If I use in the TestEntity class only an attribute InfoChartInformation; instead of the List<>InfoChartInformation>, my customer converter will work. However I need support for List
Use:
public class InfoChartInformationMorphiaConverter extends TypeConverter implements SimpleValueConverter
It is a marker interface required to make your Convertor work.