My spring version is 1.5.2, spring-mybatis-start version is 1.3.2,
I set mybatis.configuration.map-underscore-to-camel-case=true in properties.
But the MAP I returned was not converted to Camel named
Here is my configuration
mybatis.configuration.map-underscore-to-camel-case=true
The problem has been sovled,the plan is as follows
public class CustomWrapper extends MapWrapper{
public CustomWrapper(MetaObject metaObject, Map<String, Object> map) {
super(metaObject, map);
}
// useCamelCaseMapping is map-underscore-to-camel-case field
#Override
public String findProperty(String name, boolean useCamelCaseMapping) {
if(useCamelCaseMapping){
return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL,name);
}
return name;
}
}
public class MapWrapperFactory implements ObjectWrapperFactory {
#Override
public boolean hasWrapperFor(Object object) {
return object != null && object instanceof Map;
}
#Override
public ObjectWrapper getWrapperFor(MetaObject metaObject, Object object) {
return new CustomWrapper(metaObject,(Map)object);
}
}
#Configuration
public class MybatisConfig {
#Bean
public ConfigurationCustomizer mybatisConfigurationCustomizer(){
return new ConfigurationCustomizer() {
#Override
public void customize(org.apache.ibatis.session.Configuration configuration) {
configuration.setObjectWrapperFactory(new MapWrapperFactory());
}
};
}
}
Related
I configure first_cache and it works fine.
But when I want add second_cache in FirstCasheResolver CacheOperationInvocationContext has only one cache while RedisCacheManager has two caches.
Also SecondCacheResolver even not triggered.
Please help me.
Here is my CacheConfiguration class
#EnableCaching
#Configuration
public class CacheConfiguration {
public static final String FIRST_CACHE_NAME = "first_cache";
public static final String SECOND_CACHE_NAME = "second_cache";
private int defaultTokenExpirationTime = 1000;
#Bean
public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(getDefaultRedisCacheConfiguration())
.withCacheConfiguration(FIRST_CACHE_NAME, getCustomRedisCacheConfiguration())
.withCacheConfiguration(SECOND_CACHE_NAME, getCustomRedisCacheConfiguration())
.build();
}
private RedisCacheConfiguration getDefaultRedisCacheConfiguration() {
return RedisCacheConfiguration.defaultCacheConfig().disableCachingNullValues();
}
private RedisCacheConfiguration getCustomRedisCacheConfiguration() {
return RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(defaultTokenExpirationTime));
}
#Bean("firstCacheResolver")
public CacheResolver firstCacheResolver(RedisCacheManager redisCacheManager) {
return new FirstCacheResolver(redisCacheManager);
}
#Bean("secondCacheResolver")
public CacheResolver secondCacheResolver(RedisCacheManager redisCacheManager) {
return new SecondCacheResolver(redisCacheManager);
}
}
Here is my FirstCacheResolver class
public class FirstCacheResolver extends SimpleCacheResolver {
public FirstCacheResolver(CacheManager cacheManager) {
super(cacheManager);
}
#Override
public Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context) {
return super.resolveCaches(context).stream().toList();
}
}
here super.resolveCaches(context) returns list only one first_cache but CacheManager has first_cache and second_cache
Here is my SecondCacheResolver class
public class SecondCacheResolver extends SimpleCacheResolver {
public SecondCacheResolver(CacheManager cacheManager) {
super(cacheManager);
}
#Override
public Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context) {
return super.resolveCaches(context).stream().toList();
}
}
this resolveCaches() method even not triggered
here is usage of both caches. They
public class FirstClass {
#Cacheable(
cacheNames = {CacheConfiguration.FIRST_CACHE_NAME},
key = "#params.get('first').get(0)",
cacheResolver = "firstCacheResolver"
)
public int getFirst(MultiValueMap<String, Object> params) {
// some logic
}
}
public class SecondClass {
#Cacheable(
cacheNames = {CacheConfiguration.SECOND_CACHE_NAME},
key = "#params.get('second').get(0)",
cacheResolver = "secondCacheResolver"
)
public int getSecond(MultiValueMap<String, Object> params) {
// some logic
}
}
cacheManager in debug
I try implement two caches with custom CacheResolvers.
Background
I learned Factory pattern, and the power of generics and I'm attempting to piece them together.
Here are my efforts
Without generic input parameter - No warnings
public abstract class ArtifactCreator {
public abstract void setArtifacts(String workflowInput);
}
public class FooArtifactCreator extends ArtifactCreator {
#Override
public void setArtifacts(String input) {
return null;
}
}
public class BarArtifactCreator extends ArtifactCreator {
#Override
public void setArtifacts(String input) {
return null;
}
}
public class Factory {
public ArtifactCreator getArtifactCreator(String domain) {
if (domain == "foo") {
return new FooArtifactCreator()
} else if (domain == "bar") {
return new BarArtifactCreator()
}
return null;
}
}
My whole problem is the workflowInput is relegated to the type String. But I want it to be some generic POJO.
With generics - I get warnings in Factory.java and Store.java that I want to get rid of correctly. (I want to be using generics for my use-case the right way).
Raw use of parameterized class 'ArtifactCreator' on both the files in Store.java and Factory.java
Unchecked call to 'setArtifacts(T)' as a member of raw type 'ArtifactCreator' in Store.java
public abstract class ArtifactCreator {
public abstract void setArtifacts(T workflowInput);
}
public class FooArtifactCreator extends ArtifactCreator<FooInput> {
#Override
public void setArtifacts(FooInput input) {
return null;
}
}
public class BarArtifactCreator extends ArtifactCreator<BarInput> {
#Override
public void setArtifacts(BarInput input) {
return null;
}
}
public class Factory {
public ArtifactCreator getArtifactCreator(String domain) {
if (domain == "foo") {
return new FooArtifactCreator()
} else if (domain == "bar") {
return new BarArtifactCreator()
}
return null;
}
}
public class Input {
private String domain;
private String otherInput;
}
public class Store {
private final Factory factory;
public Store(Factory factory) {
this.factory = factory;
}
public ArtifactCreator getCaseClosureArtifactFactory(Input req) {
ArtifactCreator artifactCreator = factory.setArtifacts(req.getDomain());
//In reality - Create either FooInput or BarInput depending on
//`otherInput` field in `Input` POJO. Assume that there will be another
//factory/HashMap to return the input needed
FooInput input = new FooInput();
artifactCreator.setArtifacts(input);
}
}
One way I can think of solving my problems is do something like:
public class WorkflowInput {
private FooInput input;
private BarInput input;
}
public abstract class ArtifactCreator {
public abstract void setArtifacts(WorkflowInput workflowInput);
}
public class FooArtifactCreator extends ArtifactCreator {
#Override
public void setArtifacts(WorkflowInput input) {
FooInput input = input.getFooInput(); //Extract specific input
}
}
public class BarArtifactCreator extends ArtifactCreator {
#Override
public void setArtifacts(WorkflowInput input) {
BarInput input = input.getBarInput(); //Extract specific input
}
}
This feels a bit unecessary to keep some fields in WorkflowInput null.
I use javax validation. and I don't use springframework.
I wrote my specific annotation and specific ConstraintValidator
public class MyConstraintValidator implements ConstraintValidator<Myconstraints, String> {
#Override
public void initialize(...){
...
}
#Override
public boolean isValid(String value, ConstraintValidatorContext context) {
System.out.println("value=" + value + ", context=" + context);
return false;
}
}
and i need to use some outer 'service' for checking value in 'isValid' method.
Could I do it without springframework DI ?
I would like get something like this:
...
MyService service;
#Override
public boolean isValid(String value, ConstraintValidatorContext context) {
System.out.println("value=" + value + ", context=" + context);
if (service.check(value)) {
return true;
} else {
return false;
}
}
My solution (thanks the post https://marcin-chwedczuk.github.io/hello-hibernate-validator for an idea ):
class MyService {
public String getProp(){
return "something";
}
}
class MyConstraintValidatorFactory implements ConstraintValidatorFactory {
private MyService service;
public MyConstraintValidatorFactory(MyService service) {
this.service = service;
}
#Override
public <T extends ConstraintValidator<?, ?>> T getInstance(Class<T> key) {
if (MyConstraintValidator.class.equals(key)) {
MyConstraintValidator validator = new MyConstraintValidator(this.service);
return (T) validator;
}
if (key.getPackage().getName().startsWith("javax.validation") ||
key.getPackage().getName().startsWith("org.hibernate.validator"))
{
try {
return key.newInstance();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
return null;
}
#Override
public void releaseInstance(ConstraintValidator<?, ?> instance) {
}
}
So, after this question where I basically exploits reflection for passing primitive references to modify the primitive itself, like:
_begin("Another Window", ::showAnotherWindow)
I was looking for something to make something similar possible also from java, where at the moment I am using plains primitive arrays:
private boolean[] showAnotherWindow = {false};
imgui.begin("Another Window", showAnotherWindow);
#hotkey suggested me the possibility to create a class implementing the KMutableProperty0 interface and that automatically gets and sets the corresponding variable
Example:
KMutableProperty0<Boolean> prop =
PropUtils.javaProp(this, t -> t.showAnotherWindow, (t, r) -> { t.showAnotherWindow = r; });
_begin("Another Window", prop);
So, I wanted to give it a try and implemented the following in java.
Getter:
#FunctionalInterface
public interface Getter<T> {
T get();
}
Setter:
#FunctionalInterface
public interface Setter<T> {
void set(T type);
}
And then the class itself (I just wrote the constructor, all the methods are those requested by the interface and automatically implemented by the IDE) :
public class JavaProp <T> implements KMutableProperty0<T> {
private imgui.Getter<T> getter;
private imgui.Setter<T> setter;
public JavaProp(imgui.Getter<T> getter, imgui.Setter<T> setter) {
this.getter = getter;
this.setter = setter;
}
#Override
public void set(T t) {
setter.set(t);
}
#NotNull
#Override
public Setter<T> getSetter() {
return null;
}
#Override
public T get() {
return getter.get();
}
#Nullable
#Override
public Object getDelegate() {
return null;
}
#NotNull
#Override
public Getter<T> getGetter() {
return null;
}
#Override
public T invoke() {
return null;
}
#Override
public boolean isLateinit() {
return false;
}
#Override
public boolean isConst() {
return false;
}
#NotNull
#Override
public String getName() {
return null;
}
#NotNull
#Override
public List<KParameter> getParameters() {
return null;
}
#NotNull
#Override
public KType getReturnType() {
return null;
}
#NotNull
#Override
public List<KTypeParameter> getTypeParameters() {
return null;
}
#Override
public T call(Object... objects) {
return null;
}
#Override
public T callBy(Map<KParameter, ?> map) {
return null;
}
#Nullable
#Override
public KVisibility getVisibility() {
return null;
}
#Override
public boolean isFinal() {
return false;
}
#Override
public boolean isOpen() {
return false;
}
#Override
public boolean isAbstract() {
return false;
}
#NotNull
#Override
public List<Annotation> getAnnotations() {
return null;
}
}
But whenever I try to run that, I get the following:
Error:(45, 12) java: reference to Getter is ambiguous
both interface kotlin.reflect.KProperty0.Getter in kotlin.reflect.KProperty0 and interface kotlin.reflect.KProperty.Getter in kotlin.reflect.KProperty match
The problematic function is this one:
#NotNull
#Override
public Getter<T> getGetter() {
return null;
}
And the relevant file is kotlin.reflect.KProperty.tk, you can find it here
Any idea how could I solve it?
Just specify which interface you mean:
public KProperty0.Getter<T> getGetter()
But I would prefer to implement the class in Kotlin and only consume it from Java.
For some reason pulling a cached object back from the cache in Robospice is always null. Is there something I'm doing wrong?
getSpiceManager().execute(cardRequest, Card.class.getName(),
DurationInMillis.ONE_DAY, new CardRequestListener());
Is how it's executed. The spice manager is created as follows:
mSpiceManager = new SpiceManager(JacksonGoogleHttpClientSpiceService.class);
And the card class is as follows:
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"iosThumbHighRes",
"iosThumb",
"iosLargeHiRes",
"iosLargeHighRes",
"iosLarge"
})
public class Card {
#JsonProperty("iosThumbHighRes")
private String iosThumbHighRes;
#JsonProperty("iosThumb")
private String iosThumb;
#JsonProperty("iosLargeHiRes")
private String iosLargeHiRes;
#JsonProperty("iosLargeHighRes")
private String iosLargeHighRes;
#JsonProperty("iosLarge")
private String iosLarge;
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
#JsonProperty("iosThumbHighRes")
public String getIosThumbHighRes() {
return iosThumbHighRes;
}
#JsonProperty("iosThumbHighRes")
public void setIosThumbHighRes(String iosThumbHighRes) {
this.iosThumbHighRes = iosThumbHighRes;
}
#JsonProperty("iosThumb")
public String getIosThumb() {
return iosThumb;
}
#JsonProperty("iosThumb")
public void setIosThumb(String iosThumb) {
this.iosThumb = iosThumb;
}
#JsonProperty("iosLargeHiRes")
public String getIosLargeHiRes() {
return iosLargeHiRes;
}
#JsonProperty("iosLargeHiRes")
public void setIosLargeHiRes(String iosLargeHiRes) {
this.iosLargeHiRes = iosLargeHiRes;
}
#JsonProperty("iosLargeHighRes")
public String getIosLargeHighRes() {
return iosLargeHighRes;
}
#JsonProperty("iosLargeHighRes")
public void setIosLargeHighRes(String iosLargeHighRes) {
this.iosLargeHighRes = iosLargeHighRes;
}
#JsonProperty("iosLarge")
public String getIosLarge() {
return iosLarge;
}
#JsonProperty("iosLarge")
public void setIosLarge(String iosLarge) {
this.iosLarge = iosLarge;
}
#Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
#Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
#Override
public boolean equals(Object other) {
return EqualsBuilder.reflectionEquals(this, other);
}
#JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
#JsonAnySetter
public void setAdditionalProperties(String name, Object value) {
this.additionalProperties.put(name, value);
}
}
Is there something else I need to set?
Thanks, Graeme
The Google Http Client uses the #Key annotation. You are using Jackson annotation which is not supported by Googe Http Java Client, as it provides an abstraction layer over all serialisation solutions (gson/jackson).