How to parse json data into different object dynamically by using Jackson in Spring3 MVC project - spring-mvc

I want to know if there is a way to parse json data dynamically into different object by using jackson feature in Spring3.
I have a parent class as below:
public class Recording {
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
And two children:
public class Child1Recording extends Recording {
private String program;
public String getProgram() {
return program;
}
public void setProgram(String program) {
this.program = program;
}
}
public class Child2Recording extends Recording {
private String time;
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
}
Controller like this:
#RequestMapping(value = "/init/postCheck.ajax", method = RequestMethod.POST)
public #ResponseBody
String postCheck(#RequestBody Recording recording) {
if (recording instanceof Child2Recording) {
return "\"child2 success\"";
} else if (recording instanceof Child1ecording) {
return "\"child1 success\"";
}
return "\"only parent Recording\"";
}
i have different scenarios to post different json data to the backend, i am wondering if there is a way to make controller works like i said above?
For now, if i send a Child2Recording data, an error occurs when parsing it. I can't get the correct object that i expect.

Related

RestController JSON Response object format

I am using Spring Boot to return data from a Repository. I would like to format my JSON so that it plays nicely with ExtJS' ajax handling. Essentially I would like to include properties to handle success/failure, count, and errorMsg along with a List of data from the repository.
I have tried by creating a ResponseDTO object that I'm returning from my Rest Controller.
#RestController
public class AdminController {
private static final Logger logger = LogManager.getLogger(AdminController.class);
#Autowired
private UserService userService;
#Autowired
private SecurityService securityService;
#Autowired
private UserValidator userValidator;
#GetMapping("/searchUsers")
public ResponseDTO searchUsers(String name, String active) {
int activeFlag;
List<User> users;
ResponseDTO resp;
if(active.equals("true")) {
activeFlag = 1;
} else activeFlag=0;
if(StringUtils.isEmpty(name)) {
users= userService.findAllUsers(activeFlag);
} else {
users= userService.findByUsernameActive(name, activeFlag);
}
return new ResponseDTO(users, true);
}
}
Here's my DTO that I use in the controller:
public class ResponseDTO {
private boolean success;
private int count = 0;
private List<?> values;
public boolean getSuccess() {
return this.success;
}
public void setState(boolean st) {
this.success=st;
}
public int getCount() {
return this.count;
}
public void setCount(int cnt) {
this.count=cnt;
}
public List<?>getValues() {
return this.values;
}
public void setValues(List<?> vals) {
this.values = vals;
}
public ResponseDTO(List<?> items, boolean state) {
this.success = state;
values = items;
this.count = items.size();
}
}
Here's what the JSON I get back looks like:
{
"ResponseDTO": {
"success":true,
"count":2,
"values":[{obj1 } , { obj2}]
}
}
what I would like to get is something more like:
{
"success" : true,
"count" : 2,
"values" [{obj1},{obj2}]
}
I'm using Spring Boot and Jackson annotations. I have used an annotation to ignore individual fields in the objects in the results array, but I can't find a way to unwrap the ResponseDTO object to not include the class name.
When you serialize ResponseDTO POJO, you should not get 'ResponseDTO' in the response by default. Because, the root wrap feature is disabled by default. See the doc here. If you have the below code, please remove it.
mapper.enable(SerializationFeature.WRAP_ROOT_VALUE);

Recognizing parameters and mapping to complex object

public class MyClass
{
public string empty;
public int number;
public AnotherClass Another;
}
public calss AnotherClass
{
int number1;
int number2;
}
method
[HttpGet]
[Route("check")]
public HttpResponseMessage Get([FromBody] MyClass request)
{
//
return new HttpResponseMessage() { StatusCode = HttpStatusCode.OK};
}
Is it possible to map request where user send all parameters in body like this
{
"empty":"test",
"number":"5",
"number1":"10",
"number2":"15"
}
I don't want to change JSON part.

Reflection issue: NoSuchMethodException <init> ...specification.SearchCriteria, [Ljava.lang.String;)

Well, NoSuchMethodException is normally well self-explaining. Unfortunately, in my case, I couldn't even guess why I am getting such error.
I am taking care a code from other developer and I must maintain it. It was designed with specification pattern in mind. In order to make the search engine very generic, basically, any string passed from client to rest service is split in order to build the search criteria.
When executing "clazzSpec.getDeclaredConstructor(SearchCriteria.class, String[].class).newInstance(param);" I get
java.lang.NoSuchMethodException: br.com.mycompany.specification.SomethingSpecification.<init>(br.com.mycompany.specification.SearchCriteria, [Ljava.lang.String;)
Looking the image bellow, I can't see what is missed
SearchCriteria:
public class SearchCriteria {
private String key;
private String operation;
private Object value;
public SearchCriteria(String key, String operation, Object value) {
this.key = key;
this.operation = operation;
this.value = value;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getOperation() {
return operation;
}
public void setOperation(String operation) {
this.operation = operation;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
}
SomethingSpecification
public class SomethingSpecification extends Specification<Something> {
public SomethingSpecification(SearchCriteria criteria) {
super(criteria);
}
#Override
public Predicate toPredicate(Root<Something> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
switch (criteria.getOperation()) {
case "=":
...
}
return super.toPredicate(root, query, builder);
}
}
The reflection code looks for a constructor with two arguments: SearchCriteria and a String[]. But the only constructor for SomethingSpecification only has one argument.

Is there a way to make Spring Thymeleaf process a string template?

I would like to write something like :
#Autowired
private SpringTemplateEngine engine;
....
// Thymeleaf Context
WebContext thymeleafContext = new WebContext(request, response, request.getServletContext(), locale);
// cached html of a thymeleaf template file
String cachedHtml=....
// process the cached html
String html=engine.process(cachedHtml, thymeleafContext);
By default, the [process] method can't do that. I can understand from the docs that I need a special Template Resolver :
In order to execute templates, the process(String, IContext) method will be used:
final String result = templateEngine.process("mytemplate", ctx);
The "mytemplate" String argument is the template name, and it will relate to the physical/logical location of the template itself in a way configured at the template resolver/s.
Does anyone know how to solve my problem ?
The goal is to cache the Thymeleaf templates (files) in strings and then process theses strings rather than the files.
The solution we ended up using consisted of a new IResourceResolver with a custom Context rather than a custom TemplateResolver. We chose this because we still wanted to use classpath scanning in most cases, but occasionally had dynamic content.
The following shows how we did it:
public class StringAndClassLoaderResourceResolver implements IResourceResolver {
public StringAndClassLoaderResourceResolver() {
super();
}
public String getName() {
return getClass().getName().toUpperCase();
}
public InputStream getResourceAsStream(final TemplateProcessingParameters params, final String resourceName) {
Validate.notNull(resourceName, "Resource name cannot be null");
if( StringContext.class.isAssignableFrom( params.getContext().getClass() ) ){
String content = ((StringContext)params.getContext()).getContent();
return IOUtils.toInputStream(content);
}
return ClassLoaderUtils.getClassLoader(ClassLoaderResourceResolver.class).getResourceAsStream(resourceName);
}
public static class StringContext extends Context{
private final String content;
public StringContext(String content) {
this.content = content;
}
public StringContext(String content, Locale locale) {
super(locale);
this.content = content;
}
public StringContext(String content, Locale locale, Map<String, ?> variables) {
super(locale, variables);
this.content = content;
}
public String getContent() {
return content;
}
}
Test Case
public class StringAndClassLoaderResourceResolverTest {
private static SpringTemplateEngine templateEngine;
#BeforeClass
public static void setup(){
TemplateResolver resolver = new TemplateResolver();
resolver.setResourceResolver(new StringAndClassLoaderResourceResolver());
resolver.setPrefix("mail/"); // src/test/resources/mail
resolver.setSuffix(".html");
resolver.setTemplateMode("LEGACYHTML5");
resolver.setCharacterEncoding(CharEncoding.UTF_8);
resolver.setOrder(1);
templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(resolver);
}
#Test
public void testStringResolution() {
String expected = "<div>dave</div>";
String input = "<div th:text=\"${userName}\">Some Username Here!</div>";
IContext context = new StringAndClassLoaderResourceResolver.StringContext(input);
context.getVariables().put("userName", "dave");
String actual = templateEngine.process("redundant", context);
assertEquals(expected, actual);
}
#Test
public void testClasspathResolution(){
IContext context = new Context();
context.getVariables().put("message", "Hello Thymeleaf!");
String actual = templateEngine.process("dummy", context);
String expected = "<h1>Hello Thymeleaf!</h1>";
assertEquals(expected, actual);
}
}
Dummy template file at src/main/resources/mail/dummy.html
<h1 th:text="${message}">A message will go here!</h1>
Note: We used Apache CommonsIO's IOUtils for converting the String to an InputStream
You can implement your own TemplateResolver and IResourceResolver to work with String.
for simple unit tests:
static class TestResourceResolver implements IResourceResolver {
public String content = "";
#Override
public String getName() {
return "TestTemplateResolver";
}
#Override
public InputStream getResourceAsStream(TemplateProcessingParameters templateProcessingParameters,
String resourceName) {
return new ByteArrayInputStream(content.getBytes());
}
}
or just use org.thymeleaf.templateresolver.StringTemplateResolver in Thymeleaf 3
Yep StringTemplateResolver is the way to go.
public class ReportTemplateEngine {
private static TemplateEngine instance;
private ReportTemplateEngine() {}
public static TemplateEngine getInstance() {
if(instance == null){
synchronized (ReportTemplateEngine.class) {
if(instance == null) {
instance = new TemplateEngine();
StringTemplateResolver templateResolver = new StringTemplateResolver();
templateResolver.setTemplateMode(TemplateMode.HTML);
instance.setTemplateResolver(templateResolver);
}
}
}
return instance;
}
}

ASP.NET MVC - Abstraction between Data and Object Layers

I am using ASP.NET EntityFramework MVC (All Latest) with Visual Studio 2013.
I am attempting to come up with a unifying means of standardizing the abstraction between my object and data layer.
I know that many people like to use the IRepository pattern with MVC. My biggest issue with this is that it forces you to create and maintain a second object type (The Repository) for each of the objects that you want to maintain. My solution has been to combing the IRepository method with a Static Factory pattern to make a Static Repository, for instance:
public class SiteDatabase : DbContext
{
// Singleton
private static SiteDatabase _Instance;
public static SiteDatabase Instance
{
get
{
if (_Instance == null)
{
_Instance = new SiteDatabase();
}
return _Instance;
}
}
public DbSet<User> Users { get; set; }
}
public class User : IUser
{
public static User Create(string UserName)
{
User item = new User();
item.UserName = UserName;
SiteDatabase.Instance.Users.Add(item);
return item;
}
public static User Find(string UserName)
{
return SiteDatabase.Instance.Users.SingleOrDefault(x => x.UserName == UserName);
}
public static User[] All()
{
return SiteDatabase.Instance.Users.ToArray();
}
public string Id { get; set; }
public string UserName { get; set; }
protected User()
{
Id = Guid.NewGuid().ToString();
}
public void Delete()
{
SiteDatabase.Instance.Users.Remove(this);
}
}
public class Page
{
public static Page Create(string PageName)
{
...
}
public static Page Find(string PageName)
{
...
}
public static Page[] All()
{
...
}
...
public void Delete()
{
...
}
}
My question is: will this pattern cause me to miss out on any built-in functionality that the normal repository pattern would allow me to capture?
The non-static methods could be handled with an interface, but what about the static methods? Is there any way to have a base class that ensures that static methods will exist in derived classes?

Resources