lombok #NonNull on Field not readable using getAnnotations - reflection

Example:
#Value
#Builder(toBuilder = true)
#AllArgsConstructor(access = AccessLevel.PUBLIC)
public class A {
//
// RecordRootable fields
//
#NonNull
private UUID a;
}
Looking at the class file the #NonNull annotation seems to be present if the IntelliJ decompiler is not lying.
Now we want to read the annotation from the Field using Field.getAnnotations or something similar at runtime but nothing is found.
Is there any particular method I can use to read this annotation?
Is there anything extra I need to add to the annotation to be able to read it?

It seems the Annotation has
#Retention(RetentionPolicy.CLASS)
instead of
#Retention(RetentionPolicy.RUNTIME)
so they can't be read reflectively

Related

Mapping Java Optional with DynamoDBMapper annotations

Is there a clean way to map Optional fields with DynamoDBMapper, for both basic types and arbitrary/custom objects?
I believe one option would be to implement DynamoDBTypeConverter for optionals of basic types (Optional<String>, Optional<Integer>, etc). But, in addition to being a bit dirty, this would not work for custom objects.
I am looking for some sort of "chaining" behaviour of converters, where the default converter is applied first and the result wrapped in case of optional fields.
Is there a way to specify this behaviour?
#DynamoDBTable
public class MyModel {
#DynamoDBAttribute
private Optional<String> someStringField;
#DynamoDBAttribute
private Optional<AnotherModel> someAnotherModelField;
...
}
#DynamoDBDocument
public class AnotherModel {
}
For what you want to do, I believe the custom converters is the proper way.
Create a class for example:
class SomeAnotherModelOptionalConverter implements DynamoDBTypeConverter<String, Optional<AnotherModel>> {
#Override
public String convert(Optional<AnotherModel> optional) {
// your conversion from Optional attribute to String DynamoDB attribute
}
#Override
public Optional<AnotherModel> unconvert(String s) {
// your conversion from String DynamoDB attribute to Optional
}
}
Then on your attribute, you add the following tag:
#DynamoDBAttribute
#DynamoDBTypeConverted(converter = SomeAnotherModelOptionalConverter.class)
private Optional<AnotherModel> someAnotherModelField;
Anyways, I would not use an Optional as a field in a class. Instead I would create a getter that has and Optional as a return.
private AnotherModel someAnotherModelField
...
Optional<AnotherModel> getSomeAnotherModelField(){
return Optional.ofNullable(someAnotherModelField);
}
Let me know if that works for you!

Spring Data Elasticsearch #Document indexName defined at runtime

Is it possible to specify dynamically (at runtime) the indexName for each #Document, for example, via a configuration file? Or is it possible to make #Document Spring environment (dev, prod) dependant?
Thank you!
The #Document annotation does not permit to pass the indexname in parameter directly. However I found a work around.
In my configuration class I created a Bean returning a string. In this string I injected the name of the index with #Value :
#Value("${etrali.indexname}")
private String indexName;
#Bean
public String indexName(){
return indexName;
}
Afterward it is possible to inject the index into the #Documentation annotation like this :
#Document(indexName="#{#indexName}",type = "syslog_watcher")
It works for me, I hope it will help you.
Best regards
The solution from Bruno probably works but the "I created a Bean returning a string" part is a bit confusing.
Here is how I do it :
Have the "index.name" key valued in an application.properties file loaded by "<context:property-placeholder location="classpath:application.properties" />"
Create a bean named ConfigBean annotated with #Named or #Component
#Named
public class ConfigBean {
#Value("${index.name}")
private String indexName;
public String getIndexName() {
return indexName;
}
public void setIndexName(String indexName) {
this.indexName = indexName;
}
}
Inject the value of configBean.getIndexName() into the "#Document" annotation using Spring EL : #Document(indexName = "#{ configBean.indexName }", type = "myType")
P.S. : You may achieve the same result directly using the implicit bean "systemProperties" (something like #{ systemProperties['index.name'] }) but it didn't work for me and it's pretty hard to debug since u can't resolve systemProperties in a programmatic context (https://jira.spring.io/browse/SPR-6651)
The Bruno's solution works but there is no need to create a new Bean in this way. What I do is:
create a bean annotated with #org.springframework.stereotype.Service where the index name is loaded from the database:
#Service
public class ElasticsearchIndexConfigService {
private String elasticsearchIndexName;
// some code to update the elasticsearchIndexName variable
public String getIndexName() {
return elasticsearchIndexName;
}
}
call the getIndexName() method from the bean in the #Document annotation using the SpEL:
#Document(indexName = "#{#elasticsearchIndexConfigService.getIndexName()}", createIndex = false)
public class MyEntity {
}
The crucial part is to use # - #{elasticsearchIndexConfigService.getIndexName()} won't work. I lost some time to figure this out.

spring-mvc swagger how to hide model property in swagger ui?

We are using SwaggerSpringMvcPlugin to generate swagger documentation as shown below.
#Bean
public SwaggerSpringMvcPlugin swaggerSpringMvcPlugin(SpringSwaggerConfig springSwaggerConfig) {
log.debug("Starting Swagger");
StopWatch watch = new StopWatch();
watch.start();
SwaggerSpringMvcPlugin swaggerSpringMvcPlugin = new SwaggerSpringMvcPlugin(springSwaggerConfig)
.apiInfo(apiInfo())
.genericModelSubstitutes(ResponseEntity.class)
.includePatterns(DEFAULT_INCLUDE_PATTERN);
swaggerSpringMvcPlugin.build();
watch.stop();
log.debug("Started Swagger in {} ms", watch.getTotalTimeMillis());
return swaggerSpringMvcPlugin;
}
I need to exclude some of the model properties as shown below. I tried using #ApiModelProperty(access="hidden", hidden=true), but they are not excluded. Note that all the propeties of MyModel are displayed including status field. Any help appreciated.
public class MyModel implements Serializable {
....
#ApiModelProperty(access="hidden", hidden=true)
#Column(name = "status")
private String status;
...
}
You can simply use
public class MyModel implements Serializable {
#ApiModelProperty(hidden=true)
private String status;
}
Assuming that you dont want to show this property or allow it to be editable via serialization, I'd say just adding the
#JsonIgnore
Jackson2 annotation on your bean property will tell the model generation to excluded the property from being generated.
Also, keep in mind that, the annotation needs to be placed on the beans on getters or fields depending on how the ObjectMapper serialization/deserialization is configured.
If you merely want to hide the field from the swagger ui and allow modification/serialization of that field, then its not currently possible. However in the next version of the library, we plan to make this possible

Finding all Classes beloning to a superclass using Java 7

I'm looking for a way in java to find all classes that belongs to a certain superclass, and within that class refer to a static string with a known name (using reflection?);
public class Bar
extends ObjectInstance
{
public final static String Name = "Foo";
// more
}
From the example; there are n-occurences of classes that extend from ObjectInstance, and from all, i need the value of Name. The classes i am refering to are generated so i know for sure that there is a Name element that i can refer to, but i have no access to the generation sourcedata.
Perhaps the same question as How do you find all subclasses of a given class in Java?
This backs up my initial feeling that this can only be done like IDEs do it: by scanning everything down the tree, building your relationships as you go.
No Way.
One failing solution:
publc abstract class ObjectInstance {
public abstring String name();
private static Map<String, Class<? extends ObjectInstance> klasses =
new HashMap<>();
protected ObjectInstance() {
classes.put(name(), getClass());
}
Only collects instantiated classes! So fails.
With the idea to have the name provided by a function with return "foo";.
Collecting the class.
There are two unsatisfactory solutions:
The other way around: use the name as a factory pattern:
enum Name {
FOO(Bar.class),
BAZ(Baz.class),
QUX(Qux.class),
BAR(Foo.class);
public final Class<ObjectInstance> klass;
private Name(Class<ObjectInstance> klass) {
this.klass = klass;
}
}
Maybe as factory to create instances too.
Using a class annotation, and have a compile time scanning:
#ObjectInstanceName("foo")
public class Bar extends ObjectInstance {
}
How to apply this to your case: experiment.
There would be a more fitting solution of using your own ClassLoader, but that is far too over-engineered.

Setting IgnoreSerializableAttribute Globally in Json.net

I'm working on a ASP.NET WebApi (Release Candidate) project where I'm consuming several DTOs that are marked with the [Serializable] attribute. These DTOs are outside of my control so I'm not able to modify them in any way. When I return any of these from a get method the resulting JSON contains a bunch of k__BackingFields like this:
<Name>k__BackingField=Bobby
<DateCreated>k__BackingField=2012-06-19T12:35:18.6762652-05:00
Based on the searching I've done this seems like a problem with JSON.NET's IgnoreSerializableAttribute setting and to resolve my issue I just need to set it globally as the article suggests. How do I change this setting globally in a ASP.NET Web api project?
I found easy way to get rid of k__BackingField in the names.
This fragment should be somewhere in the Application_Start() in Global.asax.cs:
JsonSerializerSettings jSettings = new Newtonsoft.Json.JsonSerializerSettings();
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = jSettings;
Looks like the default setting takes care of it.
Since the library does not expose a static setter for the DefaultContractResolver, I suggest you create a static wrapper over JsonConvert and it's Serialize*/Deserialize* methods (at least the ones you use).
In your static wrapper you can define a static contract resolver:
private static readonly DefaultContractResolver Resolver = new DefaultContractResolver
{
IgnoreSerializableAttribute = true
};
This you can pass to each serialization method in the JsonSerializerSettings, inside your wrapper.
Then you call your class throughout your project.
The alternative would be to get the JSON.NET source code and adjust it yourself to use that attribute by default.
For me, the following fixed the issue with circular references and k__BackingField.
In your WebApiConfig add the following to the Register() method:
JsonSerializerSettings jSettings = new Newtonsoft.Json.JsonSerializerSettings {
ContractResolver = new DefaultContractResolver {
IgnoreSerializableAttribute = true
},
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = jSettings;
Friends, don't declare properties like this:
public String DiscretionCode { get; set; }
But, create auxiliar vars, like old....
private String discretionCode;
public String DiscretionCode
{
get { return discretionCode;}
set { discretionCode = value; }
}

Resources