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

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.

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);

How do you abstract page session properties?

I was following this example
example code:
public class Global : HttpApplication
{
private Poster _posterDetails;
private Posting _postingDetails;
private Property _propertyDetails;
protected void Application_PostRequestHandlerExecute(object sender, EventArgs e)
{
if (HttpContext.Current.Session == null) return;
_posterDetails = HttpContext.Current.Session["Poster"] as Poster;
_postingDetails = HttpContext.Current.Session["Posting"] as Posting;
_propertyDetails = HttpContext.Current.Session["Property"] as Property;
}
}
these session variables are littered throughout the app and I need to abstract the retrieval of them. Say, later I get them from a db instead of the current session.
Session is baked into the Page or Context. How do I inject that dependency into the concrete implementation of a possible current property getter.
Create an abstraction around HttpContext:
public interface IHttpContextFactory
{
HttpContextBase Create();
}
public class HttpContextFactory
: IHttpContextFactory
{
public HttpContextBase Create()
{
return new HttpContextWrapper(HttpContext.Current);
}
}
Then inject it into a specialized service for these settings.
public interface ISettings
{
T GetValue<T>(string key);
void SetValue<T>(string key, T value);
}
public class ContextSettings
: ISettings
{
private readonly IHttpContextFactory httpContextFactory;
private HttpContextBase context;
public RequestCache(
IHttpContextFactory httpContextFactory
)
{
if (httpContextFactory == null)
throw new ArgumentNullException("httpContextFactory");
this.httpContextFactory = httpContextFactory;
}
protected HttpContextBase Context
{
get
{
if (this.context == null)
{
this.context = this.httpContextFactory.Create();
}
return context;
}
}
public virtual T GetValue<T>(string key)
{
if (this.Context.Session.Contains(key))
{
return (T)this.Context.Session[key];
}
return default(T);
}
public virtual void SetValue<T>(string key, T value)
{
this.Context.Session[key] = value;
}
}
It will later be possible to replace the service with another storage mechanism by implementing ISettings and providing different constructor dependencies. Note that changing the constructor signature does not require a different interface.
That said, you should provide another service (or perhaps more than one) that takes ISettings as a dependency so you can make explicit properties. You should aim to provide focused sets of related properties for specific purposes. Your application also shouldn't have to know the type of property in order to retrieve its value - it should just call a property that hides those details.
public class SomeSettingsService: ISomeSettingsService
{
private readonly ISettings settings;
public SomeSettingsService(ISettings settings)
{
if (settings == null)
throw new ArgumentNullException("settings");
this.settings = settings;
}
public Poster Poster
{
get { return this.settings.GetValue<Poster>("Poster"); }
set { this.settings.SetValue<Poster>("Poster", value); }
}
public Posting Posting
{
get { return this.settings.GetValue<Posting>("Posting"); }
set { this.settings.SetValue<Posting>("Posting", value); }
}
public Property Property
{
get { return this.settings.GetValue<Property>("Property"); }
set { this.settings.SetValue<Property>("Property", value); }
}
}
Not sure if this is what you are asking... What I often do is create a service:
public interface ISessionService
{
object Get(string key);
void Save(string key, object value);
}
And then I implement this, which calls HttpContext.Current.Session[key] and returns the value. It shouldn't be hard to create a Get<T>(string key) to return an object either. Break all of your dependencies to use this (which is the hard part).
There is no seamless way to break the dependency... it has to be through a manual change.

Using find method of org.apache.commons.collections4.CollectionUtils with Predicate

I was using org.apache.commons.collections.CollectionUtils and for this version using find method was like this:
BeanPropertyValueEqualsPredicate objIdEqualsPredicate = new BeanPropertyValueEqualsPredicate("objId", objId);
myObj = (MyClass) CollectionUtils.find(myObjSet, objIdEqualsPredicate);
But with org.apache.commons.collections4.CollectionUtils, I don't know how to make it work.
Here what I do now but if there is a clear way of it, I will be glad to learn:
Predicate<MyClass> objIdEqualsPredicate = new Predicate<MyClass>() {
#Override
public boolean evaluate(MyClass obj) {
return obj.getObjId().equals(objId);
}
};
myObj = CollectionUtils.find(myObjSet, objIdEqualsPredicate);
Is there a way to filter some objects according to the their fields' values. If possible I don't want to use anonymous class for this.
Thanks.
As the common-beanutils still have commons-collections as dependency, you must implement the Predicate interface.
For example you can take the source code of BeanPropertyValueEqualsPredicate and refactor it, so your version implements the org.apache.commons.collections4.Predicate interface.
Or you write your own version. I would prefer not to use anonymous inner classes, because of the possibility to write unit tests for the predicate and reuse it.
Quick Example (not nullsafe,..)
#Test
public class CollectionsTest {
#Test
void test() {
Collection<Bean> col = new ArrayList<>();
col.add(new Bean("Foo"));
col.add(new Bean("Bar"));
Predicate<Bean> p = new FooPredicate("Bar");
Bean find = CollectionUtils.find(col, p);
Assert.assertNotNull(find);
Assert.assertEquals(find.getFoo(), "Bar");
}
private static final class FooPredicate implements Predicate<CollectionsTest.Bean> {
private String fieldValue;
public FooPredicate(final String fieldValue) {
super();
this.fieldValue = fieldValue;
}
#Override
public boolean evaluate(final Bean object) {
// return true for a match - false otherwise
return object.getFoo().equals(fieldValue);
}
}
public static class Bean {
private final String foo;
Bean(final String foo) {
super();
this.foo = foo;
}
public String getFoo() {
return foo;
}
}
}

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

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.

xml serialization error on bool types

I am trying to find out how to solve the problem for serializing a type of bool from a camel case string.
I have the following xml
<Root>
<BoolElement>
False
</BoolElement>
</Root>
and the following class
[XmlRoot("Root")]
public class RootObj{
[XmlElement("BoolElement")]
public bool BoolElement{get;set;}
}
this will produce an error.
If I use the same class and rename the "False" to "false" it will work. The problem is that I can't edit the xml.
Does anyone know how can I solve this?
You could use a backing field to aid for the deserialization of this invalid XML (I say invalid because according to the xsd:boolean schema False is an invalid value):
[XmlRoot("Root")]
public class RootObj
{
[XmlElement("BoolElement")]
public string BackingBoolElement
{
set
{
BoolElement = bool.Parse(value.ToLower());
}
get
{
return BoolElement.ToString();
}
}
[XmlIgnore]
public bool BoolElement { get; set; }
}
False is not a valid value for an xsd:boolean (but as you note false and 0 are) - if you cannot change the source data, then you could have a separate property purely for XML serialisation:
[XmlRoot("Root")]
public class RootObj{
[XmlElement("BoolElement")]
public string BoolElementForSerialization
{
get
{
return (this.BoolElement ? "True" : "False");
}
set
{
this.BoolElement = (string.Compare(value, "false", StringComparison.OrdinalIgnoreCase) != 0);
}
}
[XmlIgnore]
public bool BoolElement{get;set;}
}
I created a new Boolean type that can deserialize from any string. It may not be perfect but it suited my needs at the time.
For the class you want to use simply change the data type from bool to SerializableBoolean:
[XmlRoot("Root")]
public class RootObj{
[XmlElement("BoolElement")]
public SerializableBoolean BoolElement{get;set;}
}
You can then use the BoolElement property like any normal bool data type:
RootObj myObj = new RootObj();
if (myObj.BoolElement) { ... }
Here is the code for the SerializableBoolean class, note this code only handles deserializing, serializing to xml wasn't required for my purposes and so not implemented.
[System.Diagnostics.DebuggerDisplay("{Value}")]
public struct SerializableBoolean: System.Xml.Serialization.IXmlSerializable
{
private bool Value { get; set; }
public override bool Equals(object obj)
{
if (obj is string stringBoolean)
{
bool.TryParse(stringBoolean, out bool boolean);
return Value == boolean;
}
else if (obj is bool boolean)
{
return Value == boolean;
}
else if (obj is SerializableBoolean serializableBoolean)
{
return Value == serializableBoolean.Value;
}
else
{
return Value == Convert.ToBoolean(obj);
}
}
public override int GetHashCode()
{
return -1937169414 + Value.GetHashCode();
}
public XmlSchema GetSchema()
{
throw new NotImplementedException();
}
public void ReadXml(XmlReader reader)
{
Value = Convert.ToBoolean(reader.ReadElementContentAsString());
}
public void WriteXml(XmlWriter writer)
{
throw new NotImplementedException();
}
public static bool operator ==(SerializableBoolean obj1, bool obj2)
{
return obj1.Value.Equals(obj2);
}
public static bool operator !=(SerializableBoolean obj1, bool obj2)
{
return !obj1.Value.Equals(obj2);
}
public static implicit operator SerializableBoolean(string value)
{
return new SerializableBoolean() { Value = Convert.ToBoolean(value) };
}
public static implicit operator SerializableBoolean(bool value)
{
return new SerializableBoolean() { Value = value };
}
public static implicit operator bool(SerializableBoolean b)
{
return b.Value;
}
}

Resources