I am storing Person POJOs (4 string fields - id, name, lastUpdate, Data) on RIAK, then trying to fetch these objects with MapReduce.
I am doing it very similar to Basho documentation:
BucketMapReduce m = riakClient.mapReduce("person");
m.addMapPhase(new NamedJSFunction("Riak.mapByFields"), true);
MapReduceResult result = m.execute();
Collection<Person> tmp = result.getResult(Person.class);
the Person's String constructor is invoked:
public Person(String str){}
(I must have this constructor, otherwise I get an exception for it is missing)
In there I get the object as a String - the Object's fields in one string with a strange delimiter.
why am I not getting the object automatically converted to my POJO? do I really need to go over the string and deserialize it? am i doing something wrong?s
The JS function you're using doesn't do what you think it does :) It selects objects based on a field with a specific value you have to supply as an argument to the phase.
I think what you're looking for is mapValuesJson which will do what you seem to be wanting to do.
Also, you don't need a constructor at all in your POJO.
The code below should point you in the right direction (obviously this is super-simple with all public fields in the POJO and no annotations):
public class App {
public static void main( String[] args ) throws IOException, RiakException
{
IRiakClient client = RiakFactory.httpClient();
Bucket b = client.fetchBucket("test_mr").execute();
b.store("myobject", new Person()).execute();
IRiakObject o = b.fetch("myobject").execute();
System.out.println(o.getValueAsString());
BucketMapReduce m = client.mapReduce("test_mr");
m.addMapPhase(new NamedJSFunction("Riak.mapValuesJson"), true);
MapReduceResult result = m.execute();
System.out.println(result.getResultRaw());
Collection<Person> tmp = result.getResult(Person.class);
for (Person p : tmp)
{
System.out.println(p.data);
}
client.shutdown();
}
}
class Person
{
public String id = "12345";
public String name = "my name";
public String lastUpdate = "some time";
public String data = "some data";
}
Related
How to print any class instance in Java? Similar to JSON.stringify() in Javascript. Not necessary JSON, any format of output will do.
public class User {
public String name, password;
public int age;
public ArrayList<String> phones;
public static void login() {
//do something
}
}
User X = new User;
X.name = "john connor";
X.password = "skynet";
X.age = "33";
X.phones.add("1234567");
X.phones.add("7654321");
System.out.println(printClass(X))
Should output something like:
{ name:"john connor", password: "skynet", age: "33", phones:
["1234567", "7654321"], login: void function() }
You can use Apache's commons-lang's ToStringBuilder.reflectionToString
Of course, reflection is slow, so only do this with your test code. for normal use, please use eclipse's "Source" menu -> generate toString() (or intellij's generate toString()) which gives you a decent string.
There could be many ways to achieve what you need. Though i would be interested in why you need.
Override the toString() method.
see: http://www.javapractices.com/topic/TopicAction.do?Id=55
If the generation algorithm gets too long, then consider a separate class say UserPrettyPrinter.
public interface UserPrettyPrinter {
string print(User);
}
public class PrintUserInJSON implements UserPrettyPrinter {
string print(User user) {
//implement the algo here
}
}
you can also implement:
public class PrintUserInXML implements UserPrettyPrinter {
string print(User user) {
//implement the algo here
}
}
Either in conjugation to number-2 or as a standalone class, you can write
public class PrintObjectBasicAlgo {
String print(Object obj) {
/* i write pseudo code here. just ask if you cannot implement this
this would help: http://docs.oracle.com/javase/tutorial/reflect/class/classMembers.html
Class class = Obj.getClass();
Filed[] allVariables = class.getAllFieldsByReflection();
ArrayList<String> keys = new ArrayList<String>;
ArrayList<String> values = new ArrayList<String>;
for(Field field : allVariables) {
Object value = reflectionGetValueOfField( field, obj );
keys.add( field.getName());
values.add(value.toString());
}
now that you have the keys and values, you can generate a string in anyway you like
*/
}
}
You may see Visitor Pattern. it might be helpful.
You have two options here. The simple one is just to override the toString function for your class. I dont see why you dont do this really. In this case its as simple as
String toString(){
return "{ name:\""+name+", password: \""+passowrd....
}
The second option is to use reflection. This would be slightly (though not really) better if you had some sorta external class used for "printing classes". The pseudo code for that would be
StringBuilder s = new StringBuidler();
for(Field f : fields){
s.append(f.getName() + "\" :\"" + f.get()+ "\"");
}
return s.toString();
However this would be costly as reflection always is. Also if you just properly override the toString functions in the first place your printClass function could literally just be
String printClass(Object o){ return o.toString();}
Which of course again begs the question of why do you need a printClass function?
One option is to use Google Gson.
import java.util.ArrayList;
import java.util.List;
import com.google.gson.Gson;
class Project {
private int year = 1987;
private String name = "ROBOCOP-1";
private boolean active = false;
private List<String> list = new ArrayList<String>() {
{
add("PROTECT THE INNOCENT");
add("UPHOLD THE LAW");
add("SERVE THE PUBLIC TRUST");
add("CLASSIFIED");
}
};
}
public class GsonExample {
public static void main(String[] args) {
Project obj = new Project();
Gson gson = new Gson();
String json = gson.toJson(obj);
System.out.println(gson.toJson(obj));
}
}
I'm writing testcases using BDD. I have a scenario where I'm stuck
I'm generating random data using below step
When generate random data for registration form
There is Bean class which have some fields like fname, lname, email, pass while i call above step it generates random data and filled in that bean class
Now it returns that bean class object and I'm storing that in formdata variable
And store into 'formdata'
Now i want to send that to my username field like below
And enter firstname as '${formdata}'
code step for same :
#QAFTestStep(stepName = "enterFirstName", description = "enter firstname as {0}")
public void enterFirstName(Map<String, Object> data) {
sendKeys(data.get("firstname").toString(), element);
}
Its working fine but suppose in some case i have to send only string as below
And enter firstname as 'Narendra'
Step would be :
#QAFTestStep(stepName = "enterFirstName", description = "enter firstname as {0}")
public void enterFirstName(String fname) {
sendKeys(fname, element);
}
Then how do i manage these 2 code as single method ?
I had a similar need for generating random strings for a broader input coverage. I would suggest forming a logic based on delimiters.
Example:
public static void main(String[] arg) {
enterFirstName("iamkenos");
enterFirstName("${formdata}");
}
public static void enterFirstName(String fname) {
System.out.println(transformData(fname));
}
public static String transformData(String data) {
Pattern pattern = Pattern.compile("^\\$\\{.+}$");
Matcher matcher = pattern.matcher(data);
if (matcher.matches()) {
//do some logic on your data;
data = "my new data 123";
}
return data;
}
This will however require you to:
call the transformData(arg) every time
stick to a fixed delimeter e.g. ${}
Output:
iamkenos
my new data 123
I tried below solution which helped me to do the same as i expecting:
#QAFTestStep(stepName = "enterFirstName", description = "enter firstname as {0}")
public void enterFirstName(Object obj) {
if (obj instanceof LinkedTreeMap) {
Map<String, Object> map = (Map<String, Object>) obj;
sendKeys(map.get("firstname").toString(), "regpage.firstname.textbox");
} else if (obj instanceof String) {
sendKeys(obj.toString(), "regpage.firstname.textbox");
} else if (obj instanceof RandomRegisterDataGenerator) {
RandomRegisterDataGenerator data = (RandomRegisterDataGenerator) obj;
sendKeys(data.getFirstname(), "regpage.firstname.textbox");
}
}
Have you looked into form-data-bean? It is preferred, where you can populate bean with one filed or all field and it will fill UI accordingly.
You can have step to populate bean and fill UI inside your bean class like below:
//Object obj: argument can be string or map or json string or xml key
#QAFTestStep( description = "fill registration form using {data}")
public void fillRegistrationFormWithData(Object obj) {
this.fillData(obj);
this.fillUiElements();
}
#QAFTestStep( description = "fill registration form with random data")
public void fillRegistrationFormWithRandomData() {
this.fillRandomData();
this.fillUiElements();
}
I would like to know if there is a way I can access examples table row data within a step method without passing it in as an argument?
Story file:
Given I am logged in
When I create a trade
Then a trade should be created
Examples:
|data1|data2|
|11111|22222|
|33333|44444|
Step file:
#When("I create a trade")
public void createTrade(#Named("data1") String data1, #Named("data2") String data2){
//code to create trade using data1 and data2
}
Above works fine, but I would like a way to access the data row from the examples table within the method. (The reason I would like to do this is because all columns may not be present in the examples table in every story, and I have found that if I have say 3 * #Named as parameters in the step method, but one of these are missing from the actual examples table then it fails to run.)
#When("I create a trade")
public void createTrade(){
//check if there is a data1 column, if so get value and do something
//check if there is a data2 column, if so get value and do something
}
Thanks for your help
You can implement a new parameter converter, and then pass the table as an object.
for example, in our project we built ExamplesTableConverter (note: there is an our of the box JBehave converter that we didn't test):
public class ExamplesTableConverter extends ParameterConverters.ExamplesTableConverter {
private final ExamplesTableFactory factory;
private static final String ROW_SEPARATOR = "\n";
private static final String FIELD_SEPARATOR = "|";
public ExamplesTableConverter(){
this(new ExamplesTableFactory());
}
public ExamplesTableConverter(ExamplesTableFactory factory){
this.factory = factory;
}
#Override
public boolean accept(Type type) {
if (type instanceof Class<?>){
return ExamplesTable.class.isAssignableFrom((Class<?>) type);
}
return false; //To change body of implemented methods use File | Settings | File Templates.
}
#Override
public Object convertValue(String tableAsString, Type type) {
System.out.println(tableAsString);
String[] rows = tableAsString.split(ROW_SEPARATOR);
StringBuffer resultString = new StringBuffer();
resultString.append(rows[0]);
resultString.append(ROW_SEPARATOR);
for(int i=1; i<rows.length; i++){
String originRow = rows[i];
List<String> rowValues = TableUtils.parseRow(originRow, FIELD_SEPARATOR, true);
String translatedRow = translateRow(rowValues);
resultString.append(translatedRow);
resultString.append(ROW_SEPARATOR);
}
System.out.println(resultString.toString());
Object table = factory.createExamplesTable(resultString.toString());
return table;
//return null;
}
private String translateRow(List<String> rowValues) {
StringBuffer result = new StringBuffer(FIELD_SEPARATOR);
for(String field : rowValues){
try{
result.append(translate(field));
result.append(FIELD_SEPARATOR);}
catch (LocalizationException e){
e.printStackTrace();
//Need do something here to handle exception
}
}
return result.toString();
}
}
then you need to add that converter to your configuration:
configuration.parameterConverters().addConverters(new ExamplesTableConverter());
create a method that use it
#When("create parameters of type $param1 from the next table: $table")
public void doThis(#Named("param1") String param1, #Named("table") ExamplesTable table)
and last, use it in a story:
When create parameters of type type1 from the next table:
|FirstName|LastName|
|Donald|Duck|
this would allow you to iterate the table.
following blog post can also help you
Simpler JBehave Examples Table Processing
Scenario:-
Given data insert in DemoSheet
|demoNumber|demoName|
|101|Demo1|
|102|Demo2|
|103|Demo3|
|104|Demo4|
|105|Demo5|
java class to fetch value from scenario:-
#Given("data insert in DemoSheet $parameterTable")
public void setDataToSheet(ExamplesTable parametersTable)
throws RowsExceededException, WriteException, IOException {
List<String> demonum = new ArrayList<String>();
List<String> demoname = new ArrayList<String>();
for (Map<String, String> row : parametersTable.getRows()) {
Iterator it = row.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pairs = (Map.Entry) it.next();
if (pairs.getKey().equals("demoNumber")) {
demonum.add((String) pairs.getValue());
} else if (pairs.getKey().equals("demoName")) {
demoname.add((String) pairs.getValue());
}
}
}
for(String s:demonum)
{
System.out.println(s.getDemonum);
System.out.println(s.getDemoname);
}
}
We can fetch the multiple row using the Example table parameter here i am passing multiple row from scenario to java class..
I want to create a String using a format, replacing some tokens in the format with properties from a bean. Is there a library that supports this or am I going to have to create my own implementation?
Let me demonstate with an example. Say I have a bean Person;
public class Person {
private String id;
private String name;
private String age;
//getters and setters
}
I want to be able to specify format strings something like;
"{name} is {age} years old."
"Person id {id} is called {name}."
and automatically populate the format placeholders with values from the bean, something like;
String format = "{name} is {age} old."
Person p = new Person(1, "Fred", "32 years");
String formatted = doFormat(format, person); //returns "Fred is 32 years old."
I've had a look at MessageFormat but this only seems to allow me to pass numeric indexes, not bean properties.
Rolled my own, testing now. Comments welcome.
import java.lang.reflect.Field;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class BeanFormatter<E> {
private Matcher matcher;
private static final Pattern pattern = Pattern.compile("\\{(.+?)\\}");
public BeanFormatter(String formatString) {
this.matcher = pattern.matcher(formatString);
}
public String format(E bean) throws Exception {
StringBuffer buffer = new StringBuffer();
try {
matcher.reset();
while (matcher.find()) {
String token = matcher.group(1);
String value = getProperty(bean, token);
matcher.appendReplacement(buffer, value);
}
matcher.appendTail(buffer);
} catch (Exception ex) {
throw new Exception("Error formatting bean " + bean.getClass() + " with format " + matcher.pattern().toString(), ex);
}
return buffer.toString();
}
private String getProperty(E bean, String token) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
Field field = bean.getClass().getDeclaredField(token);
field.setAccessible(true);
return String.valueOf(field.get(bean));
}
public static void main(String[] args) throws Exception {
String format = "{name} is {age} old.";
Person p = new Person("Fred", "32 years", 1);
BeanFormatter<Person> bf = new BeanFormatter<Person>(format);
String s = bf.format(p);
System.out.println(s);
}
}
Yes, it's possible using the Pojomatic library. Implement and plug in your own implementation of PojoFormatter. Pojomator#doToString(T) may be also interesting.
Don't really know how complex is the model you're up to consume but if you want to deal with object trees I would implement my own formatter using Jexl as expession language this way:
Initialize a singleton Jexl engine
Populate a MapContext with all the objects you want to consume when formatting strings
Parse your strings and create a Jexl expression per "${}" construct you have.
Evaluate the previous created expressions against the object context map.
The good thing about Jexl is that it will allow you to use method calls, not just properties.
Hope it helps.
Not quite close, but you can look at StringTemplate, your bean:
public static class User {
public int id; // template can directly access via u.id
private String name; // template can't access this
public User(int id, String name) { this.id = id; this.name = name; }
public boolean isManager() { return true; } // u.manager
public boolean hasParkingSpot() { return true; } // u.parkingSpot
public String getName() { return name; } // u.name
public String toString() { return id+":"+name; } // u
}
Then you can render it like this:
ST st = new ST("<b>$u.id$</b>: $u.name$", '$', '$');
st.add("u", new User(999, "parrt"));
String result = st.render(); // "<b>999</b>: parrt"
Code sample above taken from ST4 Introduction
Here is the basic code i'm trying to make work:
Field fields[] = SalesLetter.class.getDeclaredFields();
String fieldName;
for (int j = 0, m = fields.length; j < m; j++) {
fieldName = fields[j].getName(); //example fieldname [[headline]]
templateHTML = templateHTML.replace(fieldName, Letter.fieldName());
}
I believe I'm going about it wrong by trying to getDeclaredFields (which isn't even syntactically correct). When I finished my title, it came up with a few other stackoverflow questions which I read before writing this. They were:
Best way to replace tokens in a large text template
Replacing tokens in a string from an array
It gave me the idea of reading all legal [[tokens]] from a text file, putting them into a hash (err I mean map, this is java :D), then creating an object reference with the same name as that token.
I can't figure out how I would do such a thing in java specifically, or if that would work. Please assist.
Thanks in advance,
Cody Goodman
Note: I'm trying to make everything as flexible as possible, so maybe in the future I could add things such as "[[tokenname]]:this is token name, you need to really think about what the customer wants to come up with a good token name" in a text file, then those fields are generated on my form, and everything works :)
In order to read values from non-static fields of a type, you'll need a reference to an instance of the type:
public class ReflectFields {
static class Letter {
public int baz = 100;
}
static class SalesLetter extends Letter {
public String foo = "bar";
}
public static void main(String[] args) throws Exception {
// TODO: better exception handling, etc.
SalesLetter instance = new SalesLetter();
for (Field field : instance.getClass().getFields()) {
System.out.format("%s = %s%n", field.getName(), field.get(instance));
}
}
}
You'll also have to watch for private fields, etc. In general, this approach should be avoided as it breaks encapsulation by looking at class internals.
Consider using the JavaBean API.
public class BeanHelper {
private final Object bean;
private final Map<String, Method> getters = new TreeMap<String, Method>();
public BeanHelper(Object bean) {
this.bean = bean;
for (PropertyDescriptor pd : Introspector.getBeanInfo(bean.getClass(),
Object.class).getPropertyDescriptors()) {
getters.put(pd.getName(), pd.getReadMethod());
}
}
public Set<String> getProperties() { return getters.keySet(); }
public Object get(String propertyName) {
return getters.get(propertyName).invoke(bean);
}
public static void main(String[] args) {
BeanHelper helper = new BeanHelper(new MyBean());
for (String prop : helper.getProperties()) {
System.out.format("%s = %s%n", prop, helper.get(prop));
}
}
public static class MyBean {
private final String foo = "bar";
private final boolean baz = true;
public String getFoo() { return foo; }
public boolean isBaz() { return baz; }
}
}
Exception handling has been omitted for brevity, so you'll need to add some try/catch blocks (I suggest wrapping the caught exceptions in IllegalStateExceptions).
What about using a template engine like Freemarker, Velocity or StringTemplate:
replace [[ by ${ and ]] by }
create a model from a properties file containing the replacements
process templateHTML
Here an example with Freemarker (without Exception handling)
Configuration config = new Configuration();
StringTemplateLoader loader = new StringTemplateLoader();
config.setTeplateLoader(loader);
Map model = Properites.load(new FileInputStream("tokens.properties"));
loader.putTemplate("html.ftl", templateHTML);
Template template = config.getTemplate("html.ftl");
Writer out = new StringWriter();
template.process(root, out);
String result = out.toString();
StringTemplate may be more simple (replace [[ and ]] by $), but I am not fimilar with it:
Map model = Properites.load(new FileInputStream("tokens.properties"));
StringTemplate template = new StringTemplate(templateHTML);
template.setAttributes(model);
String result = template.toString();
The tokens.properties file looks like:
tokenname:this is token name