Iterate hashmap's mongodb result in Freemarker - java

I am new at java and mongodb, and i dont see how to solve this, i have a collection:
{
"_id" : "20minutos",
"active" : true,
"group" : "20 Minutos",
"domains" : [
"20minutos.com",
"20minutos.es",
"20minutos.tv"
]
}
java code:
get("/pages/:page", (request, response) -> {
String page = request.params(":page");
if(page.equals("forms")){
UserDAO userDao = new UserDAO(Connection.getInstance().getDataStore());
HashMap<String,Object> map = new HashMap<String,Object>();
map.put("users", userDao.AllUsers());
return new ModelAndView(map, page+".ftl");
}else{
return new ModelAndView(null, page+".ftl");
}
}, new FreeMarkerEngine());
my AllUsers() function
public List<User> AllUsers() throws Exception{
return this.find().asList();
}
the pojo clas, the domains
public List<String> getDomains() {
return domains;
}
and the freemarker code
<#list users as data>
<tr class="odd gradeX">
<td>${data._id}</td>
<td>${data.active?string('yes', 'no')}</td>
<td>${data.group}</td>
<#assign x = ''>
<#assign keys = data?keys>
<#list keys as key>
<#assign x = x+','+key>
</#list>
<td>${x}</td>
</tr>
the problem is that i cant acces the values of Domains
i hope u someone can help me
thank you in advance

If you want to list user domains you can use join:
<td>${data.domains?join(",")}</td>

Related

Freemarker InvalidReferenceException

I am trying to pass a collection to Freemarker:
My Recipient inner class:
#Data
private class Recipient {
private String phone;
private String languageValue;
}
My template:
<#list recipients as recipient>
{
"address": "${recipient.phone}",
"language": "en"
}
</#list>
My Java code:
List <Recipient> recipientList = new ArrayList <> ();
Recipient r = new Recipient();
r.setPhone("123");
recipientList.add(r);
Template template = new Template("name", new StringReader(myTemplate), new Configuration());
Writer out = new StringWriter();
Map<String, Object> dataModel = new HashMap<>();
dataModel.put("recipients", recipientList);
template.process(dataModel, out);
But I am getting this error:
[pool-1-thread-7] freemarker.runtime: Error executing FreeMarker template freemarker.core.InvalidReferenceException: The following has evaluated to null or missing:==> recipient.phone [in template "name" at line 1, column 220]
What's wrong? Please help. Thanks.

Remove duplicate from object and merge in array

Code sample:-
public List<UserDto> getUserCandidates(String taskId) {
List<UserCandidates> listResponse;
ResponseEntity<String> response=restTemplate.getForEntity(configProperties.getUrl()+"/task/"+taskId+"/identity-links",
String.class);
listResponse =new Gson().fromJson(response.getBody(), new TypeToken<ArrayList<UserCandidates>>(){}.getType());
listResponse.forEach(result->{
if(!StringUtils.isEmpty(result.getUserId())){
ResponseEntity<UserRefer> userResponse=restTemplate.getForEntity(configProperties.getUrl()+"/user/"+result.getUserId()+"/profile", UserRefer.class);
userDtoList.add(new UserDto(result.getUserId(), Arrays.asList(result.getGroupId()), Arrays.asList(result.getType()), userResponse.getBody().getFirstName(),
userResponse.getBody().getLastName(), userResponse.getBody().getEmail()));
}
else if(!StringUtils.isEmpty(result.getGroupId())) {
ResponseEntity<String> responseGroup=restTemplate.getForEntity(configProperties.getUrl()+"/user"+"?memberOfGroup="+result.getGroupId(), String.class);
List<UserResponse> listGroup=new Gson().fromJson(responseGroup.getBody(), new TypeToken<ArrayList<UserResponse>>(){}.getType());
listGroup.forEach(resultGroup->{
userDtoList.add(new UserDto(resultGroup.getId(),Arrays.asList(result.getGroupId()),
Arrays.asList(result.getType()),resultGroup.getFirstName(),resultGroup.getLastName(),resultGroup.getEmail()));
});
}
});
return userDtoList;
}
So in if condition the response from API I'm getting is
UserRefer(id=demo, firstName=Demo, lastName=Demo, email=demo#camunda.org) - userResponse object
And from listResponse object data is [UserCandidates(userId=null, groupId=accounting, type=candidate), UserCandidates(userId=null, groupId=sales, type=candidate), UserCandidates(userId=demo, groupId=null, type=assignee)]
next in else if condition the response for listGroup is [UserResponse(status=null, id=demo, firstName=Demo, lastName=Demo, email=demo#camunda.org), UserResponse(status=null, id=mary, firstName=Mary, lastName=Anne, email=mary#camunda.org)]
So now you can see the data is duplicate. The output i want is for when userId is not empty from the data it should take type and merge the array
else if grouped not empty the data it should take for groupType and merge in the array removing duplicte and merging in same object
Output :-
[
{
"userId": "demo",
"name": "Demo Demo",
"type": [
"candidate",
"assignee"
],
"email": "demo#camunda.org",
"groupId": [
"accounting",
"sales"
]
},
{
"userId": "mary",
"name": "Mary Anne",
"type": [
"candidate"
],
"email": "mary#camunda.org",
"groupId": [
"accounting",
"sales"
]
}
]
You need some fundamental changes in your code.
1- instead of using ResponseEntity<String> use ResponseEntity<UserCandidates[]> response by this changing you don't need use Gson() dependency.
2- You don't need to use StringUtils to check to be empty. there is same method for both string and list objects.
3- For the duplicate date I define a Map<String,UserDto> with id as key and userDto object as a value. and where the userDto data is created I store it in the map with the id. as you see for storing userDto object in the map I used merge method that for the duplicate key(id) it has a merge function.
Tip: for readability would be nice to separate the restTemplate call in other class may you reuse it too.
mergeFunction is somthing like this:
private UserDto mergeFunction(UserDto u1,UserDto u2){
u1.getType().addAll(u2.getType());
u1.getGroupId().addAll(u2.getGroupId());
return u1;
}
and complete code is:
public List<UserDto> getUserCandidates(String taskId) {
Map<String, UserDto> userDtoMap = new HashMap<>();
Map<String, String> params = new HashMap<>();
ResponseEntity<UserCandidates[]> response = restTemplate
.getForEntity(configProperties.getUrl() + "/task/" + taskId + "/identity-links",
UserCandidates[].class, params);
Arrays.asList(response.getBody()).forEach(result -> {
if (!result.getUserId().isEmpty()) {
ResponseEntity<UserRefer> userResponse = restTemplate
.getForEntity(configProperties.getUrl() + "/**", UserRefer.class);
userDtoMap.merge(result.getUserId(), new UserDto(result.getUserId(),
new ArrayList<>(Arrays.asList(result.getGroupId())), Arrays.asList(result.getType()),
userResponse.getBody().getFirstName(),
userResponse.getBody().getLastName(),
userResponse.getBody().getEmail()), (u1, u2) -> mergeFunction(u1,u2));
} else if (!result.getGroupId().isEmpty()) {
String requestUri = configProperties.getUrl() + "/user" +
"?memberOfGroup={memberOfGroup}";
Map<String, String> userResParam = new HashMap<>();
userResParam.put("memberOfGroup", result.getGroupId());
ResponseEntity<UserResponse[]> responseGroup = restTemplate
.getForEntity(requestUri, UserResponse[].class, userResParam);
Arrays.asList(responseGroup.getBody()).forEach(resultGroup -> {
userDtoMap.merge(resultGroup.getId(), new UserDto(resultGroup.getId(),
Arrays.asList(result.getGroupId()),
Arrays.asList(result.getType()), resultGroup.getFirstName(),
resultGroup.getLastName(),
resultGroup.getEmail()), (u1, u2) -> mergeFunction(u1,u2));
});
}
});
return new ArrayList<>(userDtoMap.values());
}

How to create a nested json using collections in java

I am creating a Json format for my nav bar menu and menu items.. i have put some effort and have done some work for one loop but what i want is to be nested json
My database has Data like This
What i want is to create a Json format from this table like this
var data = {
"India":
[
{ "Submenu": "delhi", "link" : "https://www.google.com" },
{ "Submenu": "mumbai", "link" : "https://www.google.com" }
],
"USA":
[
{ "Submenu": "NY", "link" : "https://www.google.com" },
{ "Submenu": "california", "link" : "https://www.google.com" }
],
"England":
[
{ "Submenu": "London", "link" : "https://www.google.com" },
{ "Submenu": "Menchester", "link" : "https://www.google.com" }
],
"logout":
[]
};
Till now i have tried this
LinkedHashMap<Object, Object> lhm = null;
List<Map<Object, Object>> list = new ArrayList<Map<Object, Object>>();
String sql="select menu,submenu and link from table_name";
String name,link;
String str = null;
Gson gson = new Gson();
try {
resultSet = statement.executeQuery(sql);
while(resultSet.next()){
lhm= new LinkedHashMap<Object, Object>();
name= resultSet.getString("submenu");
link= resultSet.getString("link");
lhm.put("submenu", name);
lhm.put("link", link);
list.add(lhm);
str = gson.toJson(list);
}
System.out.println(str);
from this i am getting result like this
[{"submenu":"Delhi","link":"https://www.google.com"},{"submenu":"mumbai","link":"https://www.google.com"},{"submenu":"NY","link":"https://www.google.com"},{"submenu":"California","link":"https://www.google.com"},{"submenu":"London","link":"https://www.google.com"},{"submenu":"Mencherter","link":"https://www.google.com"}]
now i have got the sub menus and there link .. i am facing trouble on linking the submenus to there respective menus .. i am facing issue in looping the data acc to my requirement if anyone of you have any suggestion and idea please help me out
First retrieve required dat from DB:
select menu, sub-menu, link from table_name;
Then create a Map to hold a menu content:
Map<String, List<Map<String, String>> map = new LinkedHashMap<>();
Then read result sets and fill a map, using menu name as a key:
while(rs.next()) {
map.compute(rs.getString("menu"), (menu, subMenus) -> {
Map<String, String> mapSubMenu = new LinkedHashMap<>();
mapSubMenu.put("Submenu", rs.getString("sub-menu"));
mapSubMenu.put("link", rs.getString("link"));
subMenus = subMenus != null ? subMenus : new ArrayList<>();
subMenus.add(mapSubMenu);
return subMenus;
});
}
Try Using Map<String,List<Map<Object, Object>>> instead of List<Map<Object, Object>> so that you can give menu name to your main menu.
LinkedHashMap<Object, Object> lhm; //initiaze
Map<String,List<Map<Object, Object>>> map;
List<Map<Object, Object>> list;
while(rs.next())
{
String menu = rs.getString("menu");
String subMenu = rs.getString("sub-menu");
String link = rs.getString("link");
lhm.put("submenu", name);
lhm.put("link", link);
if (map.containsKey(menu)) //check if mainmenu already present
{
map.get(menu).add(lhm);
}
else
{
//initialize list here
list.add(lhm);
map.put(menu,list);
}
}
str = gson.toJson(list);
Follow idea only and customize code as your need

Rendering a List on Freemarker template from Spark web Framework

I have the following method that renders a list of users on the template, but I got a 500 Internal Error when firing up Spark in IntelliJ.
private void renderTemplate() throws IOException, TemplateException {
List<String> users = new ArrayList<>();
users.add("John Doe");
users.add("Tony Doe");
get("/admin", (request, response) -> {
return new ModelAndView(users, "spark/template/freemarker/admin_template.ftl");
}, new FreeMarkerEngine());
}
The content of my admin_template.ftl is:
<html>
<head>
<title>Administration</title>
</head>
<body>
<h1>My Admin</h1>
<#list users as user>
<h2>$user</h2>
</#list>
</body>
</html>
Does anyone know how to render the list on freemarker template? thanks for replies!
To render the list change
<#list users as user>
<h2>$user</h2>
</#list>
to
<#list users as user>
<h2>${user}</h2>
</#list>
in admin_template.ftl and alter renderTemplate to read as follows:
private void renderTemplate() throws IOException, TemplateException {
List<String> users = new ArrayList<>();
users.add("John Doe");
users.add("Tony Doe");
Map<String, Object> attributes = new HashMap<>();
attributes.put("users", users);
get("/admin", (request, response) -> {
return new ModelAndView(attributes, "spark/template/freemarker/admin_template.ftl");
}, new FreeMarkerEngine());
}
If this does not resolve the problem there may be a separate issue with FreeMarkerEngine that is causing the error messages "500 Internal Error", namely, that your FreeMarkerEngine object fails to find the template file admin_template.ftl at runtime. See the answer to FileNotFoundException when loading freemarker template in java for details on how to deal with that.

How to populate rows of jQuery datatable with JSON object sent back from Spring MVC?

I have a Java (Spring MVC) backend that returns POJOs as JSON objects as follows:
#RequestMapping(value = "/getWidgetsByType", method = RequestMethod.POST)
public #ResponseBody List<WidgetVO> getWidgetsByType(#RequestParam("type") String type)
{
return widgetDAO.getWidgetsByType(token);
}
public class WidgetVO {
private String type;
private String name;
private boolean isAwesome;
// Getters and setters, etc.
}
In the frontend I'm trying to call /getWidgetsByType from inside a jQuery $.getJSON call, and then use the JSON results coming back from that to populate a datatable. Specifically, I want the datatable to appear inside a <div> tag that is currently empty at page load as follows:
<div id="#table-to-display"></div>
var t = getTypeFromDOM();
$.getJSON(
url: "/getWidgetsByType",
data: {
type: t
},
success: function() {
// How do I extract the JSON version of the List<WidgetVO>'s coming
// back from the server and use them to populate the table?
$("#table-to-display").datatable();
}
);
I would like the datatable to contain the same columns as the fields of the WidgetVO (type, name, isAwesome), all as String values (no renderers, etc.).
Thanks in advance for any help here!
1.Controller
#RequestMapping(value = "/json", method = RequestMethod.GET)
public
#ResponseBody
String listUsersJson(ModelMap model) throws JSONException {
int no=1;
JSONArray userArray = new JSONArray();
for (TileType tT: tD.getAll()){
String n=Integer.toString(no);
String id=Integer.toString(tT.getTileTypeId());
String[] value =
{n,
tT.getTileTypeName(),
tT.getTileTypeDensity()
};
userArray.put(value);
no++;
}
String x=userArray.toString();
String replace1=x.replace("{", "[");
String replace2=replace1.replace("}","]");
String replace3=replace2.replace(":",",");
return ("{\"aaData\":"+replace3+"}");
}
2.Dao
#Override
public List<TileType> getAll() {
Session session=HibernateUtil.getSessionFactory().openSession();
List<TileType>list=new ArrayList<TileType>();
try{
Query query=session.createQuery("from TileType T order by T.tileTypeId DESC");
list=query.list();
}
catch(HibernateException he){}
return list;
}
3.Javascript
var table = $('#example').dataTable({
"sPaginationType": "full_numbers",
"sAjaxSource": "/data/tipeTile/json",
"sDom": "<'row'<'col-xs-6'l><'col-xs-6'f>r>t<'row'<'col-xs-6'i><'col-xs-6'p>>",
"sPaginationType": "bootstrap",
"oLanguage": {
"sLengthMenu": "_MENU_ records per page",
"sSearch": ""
}
});
4.Html
<table cellpadding="0" cellspacing="0" border="0" class="table table-striped table-bordered" id="example">
<thead>
<tr>
<th style="width: 50px">No</th>
<th>Name</th>
<th>Density</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
Hope this Help
Example from the datatable site gives you all the details required.
Example JS code
$(document).ready(function() {
$('#example').dataTable( {
"bProcessing": true,
"bServerSide": true,
"sAjaxSource": "scripts/server_processing.php" // for you it will be - /getWidgetsByType
} );
} );
Your json should be something like this
{
"sEcho": 1,
"iTotalRecords": "57",
"iTotalDisplayRecords": "57",
"aaData": [
[],[],[],...
]
}
Here's example showing to set the column names on the fly.
Cheers!!
The easiest way to get the appropriate JSON data from Spring to DataTable is that instead of returning a list of your entity, return a map like this:
#RequestMapping(value = "/getWidgetsByType", method = RequestMethod.POST)
public #ResponseBody Map<String, WidgetVO> getWidgetsByType(#RequestParam("type") String type) {
Map<String, WidgetVO> result = new HashMap<>();
result.put("WidgetVO", widgetDAO.getWidgetsByType(token));
return result;
}
That's it and now you can have access to your objects:
$(document).ready(function() {
$('#example').dataTable( {
"ajax": "data/objects.txt",
"dataSrc": "WidgetVO",
"columns": [
{ "data": "type" },
{ "data": "name" },
{ "data": "isAwesome" }
]
});
});

Categories

Resources