Convert a property file to abstract class - maven

I Have a property file sqlqueries.properties.
I want an abstract class to be generated during the build/packaging in spring boot application.
sqlqueries.properties
SELECT_QUERY=SELECT * from EMPLOYEE
SqlQueries.java
public abstract class SqlQueries {
public static final String SELECT_QUERY;
static {
SELECT_QUERY="SELECT * from EMPLOYEE";
}
}
I came across the similar implementation in one of the source code with the comment
/** Generated by maven-utils-plugin:convertProperties */
Am not able to figure it out , how to do the same kind for my project

Related

Equivalent of generic NUnit.Framework.TestFixture in xUnit

In NUnit, we can create a generic test fixture.
[TestFixture(typeof(double))]
[TestFixture(typeof(float))]
public class ServiceTests<T>
{
private readonly MyService<T> myService = new();
/* ... */
}
Has xUnit any equivalent of this?
I'm trying to test a generic service and now I need to create separate classes to test it for many generic types.
public abstract class DoubleServiceTests : ServiceTests<double>
{}
public abstract class FloatServiceTests : ServiceTests<float>
{}
public abstract class ServiceTests<T>
{
private readonly MyService<T> myService = new();
/* ... */
}
This is a solution that I'm currently using.
Maybe usage of Theory attribute will help.
Theory allows injection of test data inside a test. So some test from ServiceTests may look like this:
[Theory]
[InlineData(typeof(float))]
[InlineData(typeof(double))]
public void SomeTestMethod(Type t)
{
// make use of type t
}
More [info] on Theory related attributes in xunit.

How can I create propirty file for sql queries in spring boot?

I have some sql queries in my java code. Now I want to move it to property file. But I want create another property file for storing my sql queries. I have tried create:
sample.properties
And write in this file:
sql.getCallDetail = //sql query
Then in java class:
PropertySource(value = "sample.properties")
public class ImeiBuilderDefault implements ImeiBuilder {
#Value("${sql.getCallDetail}")
private String getCallDetail;
But my project not build.
Please go through below
** sql.properties **
queries.ex1="select * from ex1"
queries.ex2="select * from ex2"
#PropertySource(value="classpath:sql.properties")
#Configuration
#ConfigurationProperties
public class SqlQueries {
private Map<String,String> queries;
//getters and setters
}
**TEST CLASS **
#Component
public class TestSQLQueries {
#Autowired
private SqlQueries queries;
#PostConstruct
public void init(){
queries.getQueries().entrySet().stream().forEach(entry->{
System.out.println(entry.getKey()+" "+entry.getValue());
});
}
}
please find the demo project https://github.com/BarathArivazhagan/Spring-Task-Sample/tree/master/Spring-SQLQueries-props

Deserialise JSON fields based on user role

I have some fields in a model that I only want to be returned when the logged in user has the role ROLE_ADMIN. I can use #JsonIgnore but that hides it for everyone. How can I make it hide dynamically?
You should use Jackson Json Views technology to acheive it - it allows to choose a different set of fields to be serialized programatically. It is also supported by Spring
Consider you have a class Model with two properties: commonField which should be available for everyone and secretField which should be available only for certain users. You should create an hierarchy of views (any classes would work) and specify which field is available in which view using #JsonView annotation
package com.stackoverflow.jsonview;
import com.fasterxml.jackson.annotation.JsonView;
public class Model {
public static class Public {}
public static class Secret extends Public {}
#JsonView(Public.class)
private String commonField;
#JsonView(Secret.class)
private String secretField;
public Model() {
}
public Model(String commonField, String secretField) {
this.commonField = commonField;
this.secretField = secretField;
}
public String getCommonField() {
return commonField;
}
public void setCommonField(String commonField) {
this.commonField = commonField;
}
public String getSecretField() {
return secretField;
}
public void setSecretField(String secretField) {
this.secretField = secretField;
}
}
Now you can specify the view you want to use in concrete ObjectMapper
package com.stackoverflow.jsonview;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Test;
import static org.junit.Assert.*;
/**
*/
public class ModelTest {
#Test
public void testSecretField() throws JsonProcessingException {
Model model = new Model("commonField","secretField");
assertEquals("{\"commonField\":\"commonField\",\"secretField\":\"secretField\"}", new ObjectMapper().writerWithView(Model.Secret.class).writeValueAsString(model));
assertEquals("{\"commonField\":\"commonField\"}", new ObjectMapper().writerWithView(Model.Public.class).writeValueAsString(model));
}
}
I am not sure if you can use declaratie approach to make spring choose the right view based on user role out of the box, so probably you will have to write some code like this:
#RequestMapping("/data")
public String getData(HttpServletRequest request) {
Model model = service.getModel();
ObjectMapper objectMapper = new ObjectMapper();
objectMapper = request.isUserInRole("ROLE_ADMIN") ? objectMapper.writerWithView(Model.Secret.class) : objectMapper.writerWithView(Model.Public.class);
return objectMapper.writeValueAsString(model);
}
I solved this after literally a full month of trying various things. I'm working with Spring 4.3.1 and boot, with data being returned in Hal using a pagedrepository.
extend RepositoryRestMvcConfiguration as MyRepositoryRestMvcConfiguration and add #Configuration to the class, make sure your starter class has #EnableWebMvc
add this to MyRepositoryRestMvcConfiguration- extend TypeConstrainedMappingJackson2HttpMessageConverter as MyResourceSupportHttpMessageConverter
add this to MyRepositoryRestMvcConfiguration
#Override
#Bean
public TypeConstrainedMappingJackson2HttpMessageConverter halJacksonHttpMessageConverter() {
ArrayList<MediaType> mediaTypes = new ArrayList<MediaType>();
mediaTypes.add(MediaTypes.HAL_JSON);
if (config().useHalAsDefaultJsonMediaType()) {
mediaTypes.add(MediaType.APPLICATION_JSON);
}
int order = config().useHalAsDefaultJsonMediaType() ? Ordered.LOWEST_PRECEDENCE - 10
: Ordered.LOWEST_PRECEDENCE - 1;
TypeConstrainedMappingJackson2HttpMessageConverter converter = new MyResourceSupportHttpMessageConverter(
order);
converter.setObjectMapper(halObjectMapper());
converter.setSupportedMediaTypes(mediaTypes);
converter.getObjectMapper().addMixIn(Object.class, MyFilteringMixin.class);
final FilterProvider myRestrictionFilterProvider = new SimpleFilterProvider()
.addFilter("MyFilteringMixin", new MyPropertyFilter()).setFailOnUnknownId(false);
converter.getObjectMapper().setFilterProvider(myRestrictionFilterProvider);
return converter;
}
Create an empty Mixin
package filters;
import com.fasterxml.jackson.annotation.JsonFilter;
#JsonFilter("MyFilteringMixin")
public class MyFilteringMixin {}
Create an empty Mixin
create class MyPropertyFilter extending SimpleBeanPropertyFilter and override adapt this method
serializeAsField(Object, JsonGenerator, SerializerProvider, PropertyWriter)you need to call either super.serializeAsField(pPojo, pJgen, pProvider, pWriter) or pWriter.serializeAsOmittedField(pPojo, pJgen, pProvider) depending on whether you wish to include or discard this particular field.
I added an annotation to the particular fields I wanted to alter and interrogated that annotation when deciding which of these two to call. I injected the security role and stored permitted roles in the annotation.
This alters what Hal shares out to the caller, not what Hal is holding in its repository. Thus you can morph it depending on who the caller is.

Using #ExceptionHandler or some other annotation that would work like a Spring 4.1 AsyncUncaughtExceptionHandler

I would like to configure and use a Spring 4.1 AsyncUncaughtExceptionHandler. According to the Spring team (see relevant comment here) one will be able to configure an AsyncUncaughtExceptionHandler either by with the <task:annotation-driven> or by implementing AsyncConfigurer as shown here:
#Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new SimpleAsyncUncaughtExceptionHandler() ;
}
Now my question is as follows: Is there another web-layer annotation similar to #ExceptionHandler that would work like a AsyncUncaughtExceptionHandler?
As stated in the comment, here's an approach I've taken:
It's about async data imports so all classes are called Import...
What I did not do (yet) is the uncaught exception handling, but reading your post made me think about it and it should be straight forward with Spring-AOP wrapping the Importer.process() methods. This will not be global solution but it would be adaptable for a complete application by using a more generalized Result object.
The Controller uses the ImportRequests to get processing (or done) messages. The Importer itself is not removing the results from the map but this is delegated to the controller instead (A user is clicking delete). We also have a #Scheduled task which cleans up done results after 1 hour to ensure there are not left-overs.
So here's part of the code that the Controller is able to get import results during processing:
#Service
public class ImportRequests {
private final Map<User, ImportResult> importRequests = new ConcurrentHashMap<>();
/** Add, remove, get methods for current user omitted */
}
public class ImportResult {
/** The done. */
private Future<Boolean> done;
/** The error messages. */
private List<String> messages = Collections.synchronizedList(new ArrayList<String>());;
}
#Service
public class ImportService {
#Autowired
private ImportRequests importRequests;
#Autowired
private Importer importer;
public ImportResult doImport(final ImportForm importForm) {
ImportResult result = new ImportResult();
importRequests.addImportResultForCurrentUser(result);
/* This is the actual Async call (process) */
result.setDone(importer.process(result));
return result;
}
}
#Service
public class ImporterImpl implements Importer {
/**
* doProcess will import the *big* file and update the result object with the necessary messages
*/
#Async
public Future<Boolean> process(ImportResult result) {
Boolean done = doProcess(result);
return new AsyncResult<Boolean>(done);
}
}
Hope this helps.
Original Text:
One possibility that I have used is the "#ControllerAdvice" on a class scanned by the servletcontext.
You simply create a method with the exception as a parameter and annotate that method with "#ExceptionHandler". You can even have multiple handlers for specific exception types.
The result of these methods are again handled by the DispatcherServlet, so you can render a view the same way as with request mappings.

Freemarker - access static variables of an object

I have a simple class:
public class MyClass {
public final static long MAIN = 1;
#Setter #Getter
protected int id;
}
(#Setter #Getter are lombok annotations for Setter and Getter methods.)
In Freemarker template I would like to create a condition like:
<#if myClassInstance.id == myClassInstance.MAIN>
But the right hand side of the if expression is according to FreeMarker undefined. Is there a way to do this? Thanks!
The template language is not aware of Java classes. But you can expose static members through the data-model (template context). See: http://freemarker.org/docs/pgui_misc_beanwrapper.html#autoid_55
I know that this question already have an accepted answer but I am still writing piece of code that can be help full for some one else.
Use below piece of code in java
BeansWrapper w = new BeansWrapper();
TemplateModel statics = w.getStaticModels();
map.put("statics", statics); // map is java.util.Map
template.process(map, out); // template is freemarker.template.Template
Then access constant in ftl
${statics["com.model.to.gen.Common"].FLAG_YES}
here com.model.to.gen.Common is a class and FLAG_YES is a static constant.
You can use expose fields option. So you can use data models without accessors (getters/setters).
BeansWrapperBuilder wrapperBuilder = new BeansWrapperBuilder(Configuration.VERSION_2_3_23);
wrapperBuilder.setExposeFields(true);
Template template = freemarkerConfiguration.getTemplate("mytemplatefile.ftl");
StringWriter stringWriter = new StringWriter();
template.process(model, stringWriter, wrapperBuilder.build());
System.out.println(stringWriter.toString());
I have another similar but effective way.
First, we can create a util class like this:
/**
* FreeMarker Utils.
*
* #author Eric Chan
*/
public abstract class FreeMarkerUtils {
/**
* init for static classes and fields.
*
* #param model model
*/
public static void initStatics(final Model model) {
// you can also create the Version like: new Version("2.3.27");
BeansWrapper wrapper = new BeansWrapper(new Version(2, 3, 27));
TemplateModel statics = wrapper.getStaticModels();
model.addAttribute("statics", statics);
}
}
And next, invoke it in your Controller:
FreeMarkerUtils.initStatics(model);
That's all, now you can access static variables in your .ftl like this:
${statics["com.springboot.constants.TestConstants"].NAME}

Resources