Auto data-binding Java object without Spring MVC - java

I am developing a Java web project and not applying Spring MVC, Spring web-flow to it (because it is quite simple). I have a small problem when attaching value from HTTP request to Java object. Is there any standalone library or utility support us to bind data from client request to a server object automatically (matched by property name) without using Spring? Assume that parameters in client request had already built to a map.
When I work with Grails (a web framework for Groovy), it has a very awesome way to fill data in request parameter to object by using: object.properties=parameters, but I do not know that in Java, do we have a similar mechanism to implement it?
Thank you so much.

Apache Commons might help with BeanUtilsBean. It has cool methods like getProperty() and setProperty(), which might help if you wanna try to code it by hand using reflection. There's also the populate(Object bean, Map properties) method, which, i believe, is the closest to what you want.
Dozer is a java library specialized in mapping stuff from one structure to other. It might help.
This guy posted a similar question on coderanch and, after some discussion, he came up with the following:
public static <T extends Object> T setFromMap(Class<T> beanClazz, HashMap<String, String> propValues) throws Exception
{
T bean = (T) beanClazz.newInstance();
Object obj = new Object();
PropertyDescriptor[] pdescriptors = null;
BeanInfo beanInfo = Introspector.getBeanInfo(beanClazz);
pdescriptors = beanInfo.getPropertyDescriptors();
for(int i=0; i<pdescriptors.length; i++)
{
String descriptorName = pdescriptors[i].getName();
if(!(descriptorName.equals("class")))
{
String propName = descriptorName;
String value = (String) propValues.get(propName);
if(value != null)
{
Object[] objArray = new Object[1];
objArray[0] = value;
Method writeMethod = pdescriptors[i].getWriteMethod();
writeMethod.invoke(bean, objArray);
}
}
}
return bean;
}

Related

How to build dynamic queries with Spring Data Redis Repositories?

I'm testing Redis with spring-data-redis using repositories like this:
public interface CreditCardRepository extends CrudRepository<CreditCard, String>{
List<CreditCard> findByIssuer(String issuer);
List<CreditCard> findByCreditNetwork(String creditNetwork);
List<CreditCard> findByCreditNetworkAndIssuer(String creditNetwork, String issuer);
}
Above methods will query over Redis structures like:
creditcard:creditNetwork:mastercard
creditcard:creditNetwork:visa
creditcard:issuer:company1
creditcard:issuer:company2
Right now my CreditCard object contains two attributes (issuer, network and the id), so it's easy to search objects like this:
private List<CreditCard> searchCardFromCache(CreditCardGetReq req) {
if (req.getIssuer() != null && req.getNetwork() != null) {
return ccRepository.findByIssuerAndCreditNetwork(req.getIssuer(), req.getNetwork().name());
}
if (req.getIssuer() != null) {
return ccRepository.findByIssuer(req.getIssuer());
}
if (req.getNetwork() != null) {
return ccRepository.findByCreditNetwork(req.getNetwork().name());
}
return null;
}
However, I don't like this code since I will have to create a combination of all the properties and will be very messy. In the future, I plan to have 15 properties so the 'if' chain is not possible.
I would like to ask you how can I create dynamic queries using spring-data-redis, so Redis can return the intersection based on the object properties in a better way than checking each property?
Have tried using MethodHandle by hardcoding (I previously deleted from the repository findByIssuerAndCreditNetwork) a method name that would be dynamic generated like this:
MethodType methodType = MethodType.methodType(cardList.getClass(), String.class, String.class);
// Dynamic create 'findByIssuerAndCreditNetwork'
MethodHandle methodHandle = MethodHandles.lookup().findVirtual(CreditCardRepository.class, "findByIssuerAndCreditNetwork", methodType);
But seems MethodHandle does not work since I got below error:
java.lang.NoSuchMethodException: no such method: com.creditcard.dao.CreditCardRepository.findByIssuerAndCreditNetwork(String,String)ArrayList/invokeInterface
Right now, there's no support to create dynamic queries. It sounds a bit as if Query by Example could be the thing you're looking for. Spring Data MongoDB and Spring Data JPA already implement Query by Example.
A query is created by the data store module to match an example domain object:
Person person = new Person();
person.setFirstname("Dave");
Example<Person> example = Example.of(person);
MongoRepository repo = …
List<Person> result = repo.findAll(example); // returns all objects that with Dave in firstname
Query by Example is not supported by Spring Data Redis right now but it should be possible to provide basic support.
I created a ticket DATAREDIS-605 to track the progress of this feature.

Refactor Legacy SOA system to use non-blocking async microservices

I've just started trying to get my head around RxJava so that I can use project reactor refactor Legacy SOA system to use non-blocking async microservices.
At the moment I'm do a feasibility study and looking at using something like spoon to transform the legacy service code (that has nothing to do with this question however)
I would like to know how I would use reactor-bus Request/Reply syntax to replace this synchronous service code. Or even if I should be using a completely different reactor construct.
Here is example of a legacy soa service, it is contrived so it might not make perfect sense, but basically each services is dependant on the results of the last.
public static Map<String, Object> createAccount(DispatchContext dctx, Map<String, Object> context) {
LocalDispatcher dispatcher = dctx.getDispatcher();
String accountPartyId = (String) context.get("partyId");
Map<String, Object> input = UtilMisc.toMap("groupName", context.get("accountName"), "groupNameLocal", context.get("groupNameLocal"), "officeSiteName", context.get("officeSiteName"), "description", context.get("description"), "partyId", accountPartyId);
Map<String, Object> serviceResults1 = dispatcher.runSync("createPartyGroup", input);
Map<String, Object> serviceResults2 = dispatcher.runSync("createPartyRole", UtilMisc.toMap("partyId", (String) serviceResults1.get("partyId"), "roleTypeId", "ACCOUNT"));
String dataSourceId = (String) context.get("dataSourceId");
Map<String, Object> serviceResults3 = null;
if (dataSourceId != null) {
serviceResults3 = dispatcher.runSync("crmsfa.addAccountDataSource", UtilMisc.toMap("partyId", (String) serviceResults2.get("partyId"), "dataSourceId", dataSourceId));
}
String marketingCampaignId = (String) context.get("marketingCampaignId");
Map<String, Object> serviceResults4 = null;
if (marketingCampaignId != null) {
serviceResults4 = dispatcher.runSync("crmsfa.addAccountMarketingCampaign", UtilMisc.toMap("partyId", (String) serviceResults3.get("partyId"), "marketingCampaignId", marketingCampaignId));
}
String initialTeamPartyId = (String) context.get("initialTeamPartyId");
Map<String, Object> serviceResults5 = null;
if (initialTeamPartyId != null) {
serviceResults5 = dispatcher.runSync("crmsfa.assignTeamToAccount", UtilMisc.toMap("accountPartyId", (String) serviceResults4.get("partyId"), "teamPartyId", initialTeamPartyId, "userLogin", userLogin));
}
Map<String, Object> results = ServiceUtil.returnSuccess();
results.put("groupId", (String) serviceResults1.get("groupId"));
results.put("roleId", (String) serviceResults2.get("roleId"));
results.put("dataSourceId", (String) serviceResults3.get("dataSourceId"));
results.put("marketingCampaignId", (String) serviceResults4.get("marketingCampaignId"));
results.put("teamPartyId", (String) serviceResults5.get("teamPartyId"));
return results;
}
Basically this is a service that calls other services using dispatcher.runSync ... I'm just looking for a starting point for my research into how to possibly use reactor or even another library to transform this type of syntax into asynchronous non-blocking code.
At this point I'm thinking in very vague terms of callbacks/some sort of Promise type structure.
Like the first call to another service is
Map<String, Object> serviceResults = dispatcher.runSync("createPartyGroup", input);
If this instead returned a Promise object that contained the serviceResults map then the rest of the method could be moved into the Promise onComplete block and the result would be a deeply nested bunch of onComplete code blocks making up this service method.
Promise p = task {
// createPartyGroup service call
}
p.onComplete { result ->
Promise p2 = task {
// createPartyRole sevice call
}
p2.onComplete { result ->
//next service call
}
}
}
Or looking at reactor-bus documentation something like the following which doesn't make sense on many levels and I just don't know enough about reactor to know why it doesn't make sense or what to learn next for me to understand why it doesn't make sense
bus.send("service.createPartyGroup", Event.wrap(input, "reply.service.createPartyGroup"));
bus.receive($("reply.service.createPartyGroup"), ev -> {
Map<?> input2 = UtilMisc.toMap("partyId", (String) ev.get("partyId"), "roleTypeId", "ACCOUNT")
bus.send("service.createPartyRole", Event.wrap(input2, "reply.service.createPartyRole"));
});
I realise it is a rather odd place to start researching the reactive programming paradigm. But replacing this synchronous service code is my ultimate objective and if I understood at least the syntax I can work backwards from that.
You just need to use Observable, where in your flow one emitted item is passed through the stream.
Check the documentation https://github.com/ReactiveX/RxJava
This will be a sequential flow
Observable.just(methodThatCallFirstServiceAndReturnObservable(params))
.flatMap(resul1 -> methodThatCallSecondAndReturnObservable(resul1))
.flatMap(resul2 -> methodThatCallThirdAndReturnObservable(resul2))
.subscribe(result3->"Last value emmited here:");
You can run the three service call in parallel and get all the values together using Observable.zip or merge. But I believe is not what you need here.

Trying to see content of map

Hi I'm trying to see the content of a map with the following code:
#RequestMapping(value = "/demos", method = RequestMethod.GET,headers="Accept=application/json")
public #ResponseBody String getPartnerIdClusters(Model model) {
Map<Integer, List<Cluster>> partnerIdClusterMap = partnerService.getPartnerIdClusterMap(true, true);
return "partnerIdClusterMap: " + partnerIdClusterMap;
}
Which gave me the following output in the browser:
partnerIdClusterMap: {2=nl.irp.globetrotting.model.Cluster#7499394a}
After that I had tried this code:
String line = "test: /n";
for (Object entry : partnerIdClusterMap.values().toArray()) {
line += entry;
line += "/n";
}
return "partnerIdClusterMap " + line;
But that didn't work either because it has given me the following output:
partnerIdClusterMap test: /nnl.irp.globetrotting.model.Cluster#63769066/n
I already know that it is the Cluster with id 3. Here is a screenshot of it:
link: http://i.imgur.com/pKLu6gf.png
Here is how the getPartnerIdClusterMap() method looks like (in case you want to know):
#Override
public Map<Integer, List<Cluster>> getPartnerIdClusterMap(boolean minorOnly, boolean foreignCountriesOnly) {
BooleanBuilder predicate = new BooleanBuilder();
if (minorOnly) {
predicate.and(qCluster.type.eq(ClusterType.MINOR));
}
if (foreignCountriesOnly) {
predicate.and(qPartner.country.code2.ne("nl"));
}
return from(qCluster)
.innerJoin(qCluster.partner, qPartner)
.where(predicate)
.where(qPartner.country.code2.ne("nl"))
.map(qPartner.id, GroupBy.list(qCluster));
}
This is what I gladly want to know:
So I gladly want to see the Clusterwith all the values from the row.
Spring MVC should be able to convert maps to JSON, with the help of a message converter. Using Spring Boot, just returning maps works for me - a MappingJackson2HttpMessageConverter is automatically configured. As I recall, before using Spring Boot, I just had to configure an ObjectMapper, and then returning the map was working. So, in summary, I think that
Using Spring Boot, returning a map should work.
If not using Spring Boot, an ObjectMapper (and maybe also a MappingJackson2HttpMessageConverter) might be needed to be configured.
If the returned map holds things that the ObjectMapper can't convert by default, it might need you to supply some converting customization. Help material on Jackson (now called fasterxml) ObjectMapper will have more details.
partnerIdClusterMap: {2=nl.irp.globetrotting.model.Cluster#7499394a}
Basically you are printing the values that you specified. In this case you are printing the integer and then the list object populated with Cluster Objects.
Consider to iterate partnerIdClusterMap in your weblogic and extract the values with the methods provided by it or override the toString method of the object to get a full line with details.

Dynamically build response entity json

I have rest end point which has set of attributes. The user can select attributes need by them. As per the user selection i need to generate the reports.
I use the restTemplate to get the data from end point and populate my response object.
Is there a way I can generate the response object dynamically.
Like if user select
A
B
C
D
restTemplate.exchange(uri, HttpMethod.GET, null, response.class);
In this case my response object should look like
#JsonIgnoreProperties(ignoreUnknown = true)
public class Response {
#JsonProperty("A")
public String A;
#JsonProperty("B")
public String B;
#JsonProperty("C")
public Integer c;
#JsonProperty("D")
public String D;
}
Currently I am statically define the response class, can we dynamically define the response class as per the attributes required by user. please let me know how it can be done.
Map<String, Object> map = new HashMap<>();
map.put("A", "hello");
map.put("B", 2);
String s = objectMapper.writer().writeValueAsString(map);
System.out.println("s = " + s);
Output is
s = {"A":"hello","B":2}
One possible solution could be the creation of a dynamic filter.
Jackson has a built-in filter mechanism which works on simple property filtering.
The default implementation is pretty basic. It allows filtering on simple properties.
The idea would be to dynamically create the string array of properties to filter (include and exclude) with the input request and build the response accordingly.
If you want a more sofisticated filter you could try an addon library I just pushed on github.
Even if you dont need this kind of advanced filtering i think the Usage part of my readme can give you already some hints about the filtering approach.
https://github.com/Antibrumm/jackson-antpathfilter

javaReflection return a list of classes that implement specific interface

I have a package which contains an interface and several classes,some classes in this package implement that interface ,In one class that does not implement that interface,I want to write a method that returns an object of all classes which implement that interface,I dont know the name of classes which implement that interface,how can I write this method?
Generally such functionality is missing in java reflection API. but your can probably implement it yourself pretty easily.
Shortly you can use systemp property java.class.path to get all classpath elements. Split it using property path.separator. Then iterate over the resulted array, read each jar file using JAR API, instantiate each Class and check if your interface isAssignableFrom(theClass).
Here is the code snippet that looks for all BSF engines available in your classpath. I wrote it for my blog post I am working on this days. This code has limitation: it works with jar files only. I believe it is enough to explain the idea.
private static Map<String, Boolean> getEngines() throws Exception {
Map<String, Boolean> result = new HashMap<String, Boolean>();
String[] pathElements = System.getProperty("java.class.path").split(System.getProperty("path.separator"));
for (String pathElement : pathElements) {
File resource = new File(pathElement);
if (!resource.isFile()) {
continue;
}
JarFile jar = new JarFile(resource);
for (Enumeration<JarEntry> e = jar.entries(); e.hasMoreElements();) {
JarEntry entry = e.nextElement();
if(entry.isDirectory()) {
continue;
}
if(!entry.getName().endsWith("Engine.class")) {
continue;
}
String className = entry.getName().replaceFirst("\\.class$", "").replace('/', '.');
try {
if(BSFEngine.class.getName().equals(className)) {
continue;
}
Class<?> clazz = Class.forName(className);
if(BSFEngine.class.isAssignableFrom(clazz) && !clazz.equals(BSFEngine.class)) {
result.put(className, true);
}
} catch (NoClassDefFoundError ex) {
// ignore...
result.put(className, false);
}
}
}
return result;
}
The method returns Map where engine class name is used as a key and boolean value indicates whether the engine is available. Engine is unavailable if it requires additional classes in classpath.
There is no straightforward solution for this problem but I suggest you to use reflections library.
Once you have it, you can just do:
Reflections reflections = new Reflections("my.project.prefix");
Set<Class<? extends SomeClassOrInterface>> subTypes =
reflections.getSubTypesOf(SomeClassOrInterface.class);
If I understand your question correctly, you need a way to check, whether particular class from the list implements some specific interface. You may use Class.getInterfaces() method for that.
If you have troubles with listing all classes from particular package, you may take a look, for example, at this question and at further links there.

Categories