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);
Related
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.
How to fetch data from corda Custom tables?
my sample code is as follows :-
Api layer -- getIous() method
{
Field attributeValue=IOUSchemaV1.PersistentIOU.class.getDeclaredField("value");
CriteriaExpression currencyIndex = Builder.equal(attributeValue, "12");
QueryCriteria.VaultCustomQueryCriteria criteria = new
QueryCriteria.VaultCustomQueryCriteria(currencyIndex);
vaultStates = services.vaultQueryByCriteria(criteria,IOUState.class);
}
In ExamplePlugin I added below code for schema registration
public class ExamplePlugin extends CordaPluginRegistry implements
WebServerPluginRegistry
{
#NotNull
#Override
public Set<MappedSchema> getRequiredSchemas()
{
Set<MappedSchema> requiredSchemas = new HashSet<>();
requiredSchemas.add(new IOUSchemaV1());
return requiredSchemas;
}
}
My Schema classes are ---
public final class IOUSchema {
}
#CordaSerializable
public class IOUSchemaV1 extends MappedSchema
{
public IOUSchemaV1() {
super(IOUSchema.class, 1, ImmutableList.of(PersistentIOU.class));
}
#Entity
#Table(name = "iou_states")
public static class PersistentIOU extends PersistentState {
#Column(name = "sender_name") private final String senderName;
#Column(name = "recipient_name") private final String recipientName;
#Column(name = "value") private final int value;
public PersistentIOU(String senderName, String recipientName, int value) {
this.senderName = senderName;
this.recipientName = recipientName;
this.value = value;
}
public String getSenderName() {
return senderName;
}
public String getRecipientName() {
return recipientName;
}
public int getValue() {
return value;
}
}
}
my state has :-
public class IOUState implements LinearState, QueryableState
{
--- some code goes here and below methods as well.---
#Override
public PersistentState generateMappedObject(MappedSchema schema) {
if (schema instanceof IOUSchemaV1) {
return new IOUSchemaV1.PersistentIOU(
this.sender.getName().toString(),
this.recipient.getName().toString(),
this.iou.getValue());
} else {
throw new IllegalArgumentException("Unrecognised schema $schema");
}
}
#Override
public Iterable<MappedSchema> supportedSchemas() {
return ImmutableList.of(new IOUSchemaV1());
}
}
But all the time i am getting below exception.
Caused by: net.corda.core.node.services.VaultQueryException:
Please register the entity 'com.example.schema.IOUSchemaV1' class in your CorDapp's CordaPluginRegistry configuration (requiredSchemas attribute)
and ensure you have declared (in supportedSchemas()) and mapped (in generateMappedObject())
the schema in the associated contract state's QueryableState interface implementation.
Can anyone please help to resolve this.
Try deleting implements WebServerPluginRegistry from your plugin declaration.
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;
}
}
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.
I want to update a log file(txt) everytime when methods in a an interface class are called?
Is there any way to do this other than writing code in every method to create log?
Here's my 30 mins. you'll have to implement the logging code somewhere so you have to create another abstraction for your code. thus an abstract class is needed. i think. this is very quick and dirty.
public interface IService<T>
{
List<T> GetAll();
bool Add(T obj);
}
then you'll need the abstract class where you'll need to implement your logging routine
public abstract class Service<T> : IService<T>
{
private void log()
{
/// TODO : do log routine here
}
public bool Add(T obj)
{
try
{
log();
return AddWithLogging(obj);
}
finally
{
log();
}
}
public List<T> GetAll()
{
try
{
log();
return GetAllWithLog();
}
finally
{
log();
}
}
protected abstract List<T> GetAllWithLog();
protected abstract bool AddWithLogging(T obj);
}
as for your concrete classes
public class EmployeeService : Service<Employee>
{
protected override List<Employee> GetAllWithLog()
{
return new List<Employee>() { new Employee() { Id = 0, Name = "test" } };
}
protected override bool AddWithLogging(Employee obj)
{
/// TODO : do add logic here
return true;
}
}
public class CompanyService : Service<Company>
{
protected override List<Company> GetAllWithLog()
{
return new List<Company>() { new Company() { Id = 0, Name = "test" } };
}
protected override bool AddWithLogging(Company obj)
{
/// TODO : do add logic here
return true;
}
}
public class Employee
{
public int Id {get;set;}
public string Name { get; set;}
}
public class Company
{
public int Id { get; set; }
public string Name { get; set; }
}
then on your implementation you can just..
static void Main(string[] args)
{
IService<Employee> employee = new EmployeeService();
List<Employee> employees = employee.GetAll();
foreach (var item in employees)
{
Console.WriteLine(item.Name);
}
IService<Company> company = new CompanyService();
List<Company> companies = company.GetAll();
foreach (var item in companies)
{
Console.WriteLine(item.Name);
}
Console.ReadLine();
}
hope this helps!
I think you would have to use Aspect Oriented Programming to achieve that. Read http://www.sharpcrafters.com/aop.net
I think you meant class (instead of interface)
Two options I can think of:
Implementing INotifyPropertyChanged which is in lines of writing code in every method
or
to adopt on of the AOP frameworks in the article http://www.codeproject.com/KB/cs/AOP_Frameworks_Rating.aspx if that is not a major leap