Questions about non-primitive/String types.

542 views
Skip to first unread message

Gary Fleming

unread,
May 2, 2011, 2:19:48 PM5/2/11
to PODAM
Hello,

PODAM seems like an interesting project, and from what I've seen seems
like a decent way of populating object graphs for use in tests.

Looking at DataProviderStrategy, it seems to be a bit restrictive in
terms of what can be achieved in custom implementations. I have a few
questions:

1) Is there a way of supporting enums?
2) Are simple value-type objects that are not primitives/strings
supported, such as BigDecimal?
3) The examples seem to assume that the domain objects to be populated
are under the control of the user using PODAM and not, say, from
external libraries or even generated source; and hence can be
annotated etc. Is this the case?
4) Rather than providing a single way of populating a String field,
remembering that the source for the field may not be under control of
the PODAM user, is it possible to have different fields do different
things? i.e. a name field and a postcode/zipcode field would be quite
different.

My thought in all of this is that the strategy interface should be
presented with each class/field pair to be populated, and be able to
provide suitable data for population. This might be by using something
akin to the current random data provider (making DataProviderStrategy
a lower level strategy), or it might be by making a more intelligent
decision like knowing the Address object's postcode field must look a
certain way.

I also seem to recall a similar project (whose name escapes me for
now) that did something like this, and made use of common JSR-303
(bean validation) annotations to force constraints on generated data.

Reading back, this may sound like I'm being overly critical of your
project. That's not the case at all: I think it looks like a very
promising project, and wouldn't post at all if I didn't think so.

Regards,
Gary.

Marco Tedone

unread,
May 2, 2011, 3:06:53 PM5/2/11
to po...@googlegroups.com
Hi Gary,

Thank you for your email! Wow, that's a lot to go through :-) Let me try to
answer your questions where I can...I must say that you highlighted some
points I didn't even consider...

1) This is, strangely enough, one thing I didn't think of. Will add it as a
new requirement for next version 2.1.0.
http://www.jemos.eu/jira/browse/PDM-25 has been created for this.
2) All classes in the java/javax namespace (e.g. java.math.BigDecimal) are
supported provided they offer either a non-argument constructor or, if no
constructor are available, a static factory (with or without arguments). In
the case of BigDecimal, currently this is not supported because it has
public constructors but they accept arguments. I just spotted a "// TODO To
provide support for constructors with argument types" in the exact point in
the code which should have populated a BigDecimal. I will add this as the
next major bug fix. http://www.jemos.eu/jira/browse/PDM-24 has been created
for this. I tried adding a BigDecimal to one of the test POJOs and the
application didn't crash. Currently the workaround would be to have PODAM to
fill your POJO and then you could invoke the setter for BigDecimal (or other
non-supported class) manually on the returned POJO.
3) If one wants to customise numeric/string values through annotations the
assumption is that they have control of the source code, yes. I couldn't
think of a way of annotating classes? Have you got any ideas on how this
could be solved?
4) The @PodamStringValue annotation allows one to define exactly the value
to assign to a string attribute. So on a postcode one could write:
@PodamStringValue(strValue="W1ECP") and similarly on a zipcode another value
could be specified.

And for your next comment on "lowering" the strategy by providing a
class/field pair, I'm not sure I entirely understand what you have got in
mind. Would you be able to drill down a little and come back with a concrete
(yet simple) example?

JSR-303 seems very interesting. It would be nice if PODAM could provide
support for JSR-303, don't you think ;-) This seems like a big piece of
work. I have put it down as an Epic: http://www.jemos.eu/jira/browse/PDM-26.
Vote for it if you would like to see it implemented.

I hope I have answered all your questions. If you want to monitor the
progress on the issues I created above, please feel free to create an
account on Jemos JIRA at: http://www.jemos.eu/jira and watch the issues of
your interest. Better yet, feel free to fork PODAM from GitHub and
contribute the changes yourself ;-)

Regards,

Marco

Marco Tedone

unread,
May 2, 2011, 5:01:33 PM5/2/11
to po...@googlegroups.com
Hi Gary,

You will be pleased to know that I fixed
http://www.jemos.eu/jira/browse/PDM-24

I added a BigDecimal to the OneDimensionalTestPojo class and it returns
filled with values. I had to adopt an "adaptive" strategy: I try each public
constructor until I found one that works, or I return null. In case of
BigDecimal, the constructors which accepted a MathContext didn't work, but
PODAM chose the one which accepts a double and it worked fine.

Regards,

Marco

-----Original Message-----
From: po...@googlegroups.com [mailto:po...@googlegroups.com] On Behalf Of
Gary Fleming
Sent: 02 May 2011 19:20
To: PODAM
Subject: [PODAM - Google] Questions about non-primitive/String types.

Gary Fleming

unread,
May 3, 2011, 3:30:52 PM5/3/11
to PODAM
Hello Marco,

Thanks for the bugfix, that'll make it more usable (and demonstrates
an admirable responsiveness).

I think the general problem that the BigDecimal issue points out is
that there are lots of value-objects that users will want to populate
with test data, but not necessarily be able to do anything about.
Outside of the java/javax namespaces, there are a number of popular
libraries that should be supportable, such as joda-time, and that's
before you consider generated code, or other inaccessible 3rd party
code.

You're right in saying that there is no way to annotate a class for
which you do not have the source (like a class in a jar file). That
suggests that annotations are not the right tool for the job here. I'd
say they're probably worth keeping in, as a pretty good strategy for
when you can annotate your classes, but there probably need to be
alternatives.

What I was suggesting was that the top-level strategy should be
something like the following. Keep in mind that this is just a sketch,
I've not thought through all the possible corner cases, and I'm
ignoring generics for the moment. It's more for a little discussion:

interface DataStrategy {

public void populateField(Class classForField, Field
fieldToPopulate);

}

The core library would then traverse the object graph, and present
every combination of class/field to the chosen implementation of this
strategy. The strategy could then make whatever decision it needed to
in order to populate that field.

This could be simply putting in completely random data (as now); with
one implementation of DataStrategy using an instance of the current
DataProviderStrategy as a sub-strategy.

Or something much more complex could look at the annotations on the
field to see if it had any JSR-303 annotations that it could generate
more specific values for (while possibly still being somewhat random).

Or it could be some kind of hybrid approach: use random data for most
of the fields, but if it's say an Address class and a field called
postcode, then provide something that looks sensible (but may still be
random).

By decoupling the strategy from a limited number of field types, you
gain greater flexibility in what can be done intelligently.

Hope that makes sense!

Regards,
Gary


On May 2, 10:01 pm, Marco Tedone <marco.ted...@gmail.com> wrote:
> Hi Gary,
>
> You will be pleased to know that I fixedhttp://www.jemos.eu/jira/browse/PDM-24

Marco Tedone

unread,
May 3, 2011, 5:28:21 PM5/3/11
to po...@googlegroups.com
Hi Gary, first of all I wanted to let you know that now PODAM supports
enums. This has gone out with the code that I have just released:
2.1.0.RELEASE.

As for you points, I think annotations are the way to go, maybe with a bit
more flexibility. PODAM supports instantiation of any class (in the
java/javax namespace or not) with a public constructor (with or without
arguments). The fix I put there for BigDecimal fixed this. For those cases
when one wants full control, I was thinking of an annotation of this kind:

@PodamValue( dataProvider=AddressProviderStrategy.class)
private Address address;

public class AddressProviderStrategy implements PodamValueProviderStrategy {

public Object getValue() {
//Fill your Address object here
}
}

public interface PodamValueProviderStrategy {
public Object getValue();
}

Then at runtime, when PODAM found a @PodamValue annotation, it would create
an instance of AddressProviderStrategy like so:

PodamValueProviderStrategy strategy = new AddressProviderStrategy();//PODAM
would actually use introspection to do this
Address address = (Address) strategy.getValue();//PODAM would actually use
introspection to do this

JSR-303 is a bigger chunk of work. Although it would add immensely to the
market value of PODAM I want first to see a user base using it, then voting
for the JSR-303 Epic, and then I would implement it.

Thank you for your feedbacks and please keep them coming.

Gary Fleming

unread,
May 5, 2011, 3:20:45 PM5/5/11
to PODAM
Hello Marco,

I think PodamValueProviderStrategy is a good addition to the library,
and fits well with the rest of what is already there. One minor
suggestion: make use of generics to get a little more type-safety.

public interface PodamValueProviderStrategy<T> {
public T getValue();
}

I agree that the JSR-303 stuff is large, so probably should come
further down the line. However, I still think that there needs to be a
way of putting data into classes that the user does not control and
therefore cannot annotate (again, things like joda-time or generated
sources). It's worth doing this part sooner than later (or at least
thinking through a clear path to it), as it will restrict a number of
users.

Regards,
Gary

Marco Tedone

unread,
May 5, 2011, 3:34:44 PM5/5/11
to po...@googlegroups.com
Gary I'd be interested in your suggestions on how to allow PODAM to provide values for classes for which sources are not available.
Sent from my BlackBerry® wireless device

Gary Fleming

unread,
May 8, 2011, 11:30:57 AM5/8/11
to PODAM
Marco,

There are a few different ways of doing it, but each involve trade-
offs. The two main ways I can see are:

1) Attempt to call all setters in the object graph (traversing down
through non-value objects), and provide a default value as far as you
can; without knowing much about the actual objects. This is cheap and
simple, but can potentially create invalid domain objects by
populating, say, a String value with too many characters or a
LocalDate (joda-time) getting created with an invalid time String.
2) Allow for more mixing in more intelligent Object-level strategies,
in the way I outlined earlier. Here you're making the data provider
strategy more broad and flexible, which can be a positive (in that you
can create a strategy specifically for your domain objects) and a
negative (you've got a broader library, meaning a wider set of
problems)

I would probably tend towards the second, as I think that being able
to create valid randomly populated objects is crucially important,
even if that means making the library a little more complicated,
especially when that additional complexity can be hidden from those
that don't need it. Those who can use the annotations and current
strategy get to use that, and those who also need valid LocalDates,
for example, can mix-in that support.

Regards,
Gary

Marco Tedone

unread,
May 8, 2011, 12:42:13 PM5/8/11
to po...@googlegroups.com
Hi Gary,

A simple adjustment to the code allows now PODAM to do what you suggested at
1). I added a JodaTimePojo to the test suite. The POJO contains an instance
variable of type LocalDate. PODAM is able to create an instance (although
with random values for the LocalDate object, as one might guess). The "bug"
is referred in http://www.jemos.eu/jira/browse/PDM-27 and the code is
available in the latest SNAPSHOT, on GitHub. Tomorrow I will release
2.2.0.RELEASE, which contains this bug fix and also the possibility to fix
the value for numeric attributes (the String ones were already covered) with
a numValue attribute in each primitive type annotation.

Regards,

Marco

As for 2) I'd like to hear more concrete suggestions, otherwise I find
difficult to picture what you've got in mind. Please feel free to fork the
code and suggest pull requests.

Marco Tedone

unread,
May 8, 2011, 4:33:20 PM5/8/11
to PODAM
Gary, BTW I found a potential problem with the change I made. The
default strategy returns randon longs, and one of this random values
was not correct to create a LocalDate. However the problem can be
easily solved by providing a strategy which manufactures longs in the
correct range
> ...
>
> read more »

Marco Tedone

unread,
May 13, 2011, 12:49:05 AM5/13/11
to po...@googlegroups.com
Hi Gary,

The latest SNAPSHOT in GitHub contains now a @PodamStrategyValue annotation which can be used to define a strategy to populate single attributes. The same capabilities have been added to @PodamCollection for Collections, arrays and Maps. You can check how it works by visiting the documentation: http://www.jemos.eu/projects/podam.

I shall release all these changes in 2.3.0 going out this week-end.

Regards,

Marco

Alfonso Mateos Alarcón

unread,
Sep 9, 2014, 5:30:13 AM9/9/14
to po...@googlegroups.com
Hi Marco, 

Could you please tell me how to do that for a joda local date? I have exactly that problem: the random long is not a valid date and don't know how to face this... 
The rest of features are superb: it fills up really complex and composite DTO's like a charm. It's just that little detail...

By the way, I cannot put annotations in my code, it should be done without them... Don't know if I could set some static constants for longs so that they always give me the same valid value...
Any hint would be appreciated
Thanks in advance.

Marco Tedone

unread,
Sep 9, 2014, 9:26:19 AM9/9/14
to po...@googlegroups.com
Create a new strategy that fills the date as you wish
--
You received this message because you are subscribed to the Google Groups "PODAM" group.
To unsubscribe from this group and stop receiving emails from it, send an email to podam+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Alfonso Mateos Alarcón

unread,
Sep 12, 2014, 7:08:00 AM9/12/14
to po...@googlegroups.com
Hi Marco,

Correct me if I'm wrong, but I cannot solve it with a new strategy, because I must provide Joda LocalDate and Joda DateTime, and it seems that they require more than a long value to be created... and it must be in range.

I workarounded the problem creating a class like this:


public class DataPopulatorFactory {

    private final PodamFactory factory = new PodamFactoryImpl();

    public <T> T populatePojo(Class<T> pojoClass) {

        DataProviderStrategy strategy = factory.getStrategy();

        Random random = new Random();

        if (pojoClass.isAssignableFrom(LocalDate.class)) {

            return (T) new LocalDate(1950 + random.nextInt(100), 1 + random.nextInt(12), 1 + random.nextInt(29));

        } else if (pojoClass.isAssignableFrom(DateTime.class)) {

            long instant = 1000000 + random.nextInt(500000);

            return (T) new DateTime(instant);

        } else {

            return factory.manufacturePojo(pojoClass);

        }

    }

This code reminds me to the one that you have inside PodamFactoryImpl.fillCollection(...), where you also use "isAssignableFrom":

if (null != elementStrategy && ObjectStrategy.class.isAssignableFrom(elementStrategy.getClass())

Would you consider to enlarge the Strategy interface to support both Joda LocalDate and Joda DateTime, or you rather prefer to keep it with primitive types? If so, I could contribute to implement it.

Thanks for sharing your framework, it's been really valuable to me.


Alfonso Mateos Alarcón

unread,
Sep 12, 2014, 7:15:54 AM9/12/14
to po...@googlegroups.com
Marco, I correct my self... Maybe I could implement a new Strategy and implement this method and see if isAssignableFrom Joda LocalDate or DateTime and provide a random value for it?

@Override

public <T> Class<? extends T> getSpecificClass(

  Class<T> nonInstantiatableClass) {

       Class<? extends T> found = (Class<? extends T>) specificTypes.get(nonInstantiatableClass);

       if (found == null) {

          found = nonInstantiatableClass;

        }

        return found;

}

Marco Tedone

unread,
Sep 12, 2014, 1:31:09 PM9/12/14
to po...@googlegroups.com
I'm afraid I won't include any non-standard Java extensions in Podam but I'm pretty sure that by extending the default strategy with your own where you provide your own Joda values should work. On the website (www.jemos.co.uk/projects/podam) there are some examples of custom strategies (I guess in the walkthrough page).

Regards,
Reply all
Reply to author
Forward
0 new messages