I recently found about this pattern and tried to implement it into my project. It does what it suppose to do. However, tried to find a nice solution to update it. Came up with one solution and I would like to know if it is "acceptable".
Only one difference which I did is I created another constructor inside Builder class which takes calling object as parameter:
public Builder (User user) {
this.userID = user.getUserID();
this.userName = user.getUserName();
...
//and so on
and in main method
creating an object:
User user = new User.Builder("mandatory params")
.email("some email")
.build();
and update:
user = new User.Builder(user).phoneNumber("my number").build();
Is this approach acceptable?
This is good if you want to create a new user with fields copied from another user, with some changes:
anotherUser = new User.Builder(user).phoneNumber("my number").build();
But if you are assigning the new object back to the user variable, it suggests that you are updating the existing user. To update, you are creating a whole new object and copying fields, which is very inefficient. You should use setters.
you should you setter's and getter's once you have the object empty or partially filled doesn't matter.
Also In my opinion it's better to use jackson objectMapper compare to builder pattern it automatically handles new parameters without adding extra line of code in the builder pattern and also it's more clean code.
Related
I have a DTO class and some REST services that sometimes return (among other things) a List of those DTOs.
I cannot alter that DTO, as it's used in several places of the project.
However, only for one specific REST service, I need to exclude some of the fields of that DTO object.
Basically I need to be able to apply this solution only at a certain point.
I tried applying #JsonFilter("restrictionFilter") to my DTO class, but then I get an error if I don't use that filter with a mapper every time I marshall the object into a JSON, like this:
final String writeValueAsString = mapper.writer(
new SimpleFilterProvider()
.addFilter("restrictionFilter",
SimpleBeanPropertyFilter.filterOutAllExcept("name", "sizeInByte"))
).writeValueAsString(objectsList);
The error is Cannot resolve PropertyFilter with id 'restrictionFilter'; no FilterProvider configured...
This issue sounds like a perfect Decorator design pattern use.
Create a new DTO with a constructor that gets the original DTO and create which get methods you want or ignore whatever get methods you like.
For example:
public class NewDto {
OldDto oldDto;
public NewDto(OldDto oldDto){
this.oldDto = oldDto;
}
public String getName(){
return oldDto.getName();
}
}
Now you will only need to return the NewDto object, like so:
return new NewDto(oldDto)
i'm writing a cucumber test and i come up with some difficulty:
I have a step which creates dto and saves it using save client which returns dto back again i would need to use that returned dto for other step but don't know how to make it.
Here's how it looks in code :
commonExpenseCreationSteps.java
#Given("^new \"([^\"]*)\" expense with type \"([^"]*)\"$")
public ExpenseDTO newExpense(String description, String expenseType) throws Throwable {
ExpenseDTO expenseDTO = new ExpenseDTO();
expenseDTO.setDefaultPurpose(description);
expenseDTO.setExpenseType(expenseType);
return expenseSaveClient.save(expenseDTO);
}
expenseTransactionsSendSteps.java
#Given("^send expense for Approval$")
public void sendExpenseForApproval() throws InterruptedException {
expenseTransactionSendClient.sendToApproval(expenseDTO);
}
How it would be possible to store value returned by one Step and use it in other one in this case i return ExpenseDTO in newExpense method but i need to use it in sendExpenseForApproval but don't know how to do it !?
Create expenseDTO object outside of your glue code, probably in your stepdef class constructor.
ExpenseDTO expenseDTO = new ExpenseDTO();
The way to share state between steps in the same class is to use instance variables. Set the value in one step and use that value in a later step.
The way to share state between steps with two or more step classes is to use dependency injection.
I wrote a blog post that describes how it can be done using PicoContainer.
I have started using the Lombok library, and I am unable to figure out the difference between using a wither & a builder.
#Builder
#Wither
public class Sample {
private int x;
private int y;
}
Now I can create an object in 2 ways:
Sample s = new Sample().builder()
.x(10)
.y(15)
.build();
OR
Sample s = new Sample()
.withx(10)
.withy(10);
What is the difference between the two? Which one should I use?
#Builder is used to create mutable objects, #Wither for immutables.
Disclosure: I am a lombok developer.
Generally, the difference is when you build a object with builder(), you must call build() method at last, and before you call build(), all property values are saved in the internal builder object instead of the object your created with new. After you setted all properties and call build(), a new object will be created. See details here: https://projectlombok.org/features/Builder.html . I think the better way for builder pattern is:
Sample s = Sample.builder()
.x(10)
.y(15)
.build();
Because the first Sample object is redundant.
For withers, every time you called withXXX(xxx), a new object is returned, with XXX set to xxx, and all other properties cloned from the object you called wither on (if xxx is different from the original xxx. See details here: https://projectlombok.org/features/experimental/Wither.html). Choose which way, I think it's only depends on your personal habit and your project's code style.
Hope this could help you.
Recently I came across with a builder pattern that intrigued me.
So, I have an EntityBuilder which builds an Entity, but it doesn't return the entity. Here is the method signature:
public void build();
Instead, inside the build() method, it delivers the new object created, the Entity, to a CacheImplementation instance to store it.
Note: the CacheImpl is injected in the builder's constructor.
public void build(){
//create new entity
cacheImplementation.add(entity);
}
Does this sounds like best practice?
Later edit 0
public interface EntityBuilder {
void setProperty0(PropertyObject propertyObject0);
void setProperty1(PropertyObject propertyObject1);
void setProperty2(PropertyObject propertyObject2);
//...
void build();
}
public class EntityBuilderImpl implements EntityBuilder {
PropertyObject propertyObject0;
PropertyObject propertyObject1;
PropertyObject propertyObject2;
//...
// setters for all properties
#Override
public void build(){
//create new entity
cacheImplementation.add(entity);
}
}
The builder is used in the following way:
public class EntityProcessor{
private EntityBuilderFactory entityBuilderFactory;//initialized in constructor
void process(EntityDetails entityDetails){
EntityBuilder entityBuilder = this.entityBuilderFactory.getNewEntitytBuilder();
//..
// entityBuilder.set all properties from entityDetails
entityBuilder.build();
}
}
Note: the cacheImpl instance just stores the entities in a List<> which is accesses every N seconds.
Does this sounds like best practice?
The traditional builder pattern doesn't store the created object anywhere, it simply returns it.
I can imagine a variation where the builder also has a role of instance control to avoid creating duplicate objects, and managing a store of immutable objects.
The decision to not return an instance could be to make it clear that the method has a side effect. If the method returned the object, it might mislead to thinking that it's a traditional builder without side effects, when that's not the case here.
In any case, all this is just speculation, as we haven't seen the rest of the code where this is used and the way it is implemented and used. We don't have enough context to really judge.
There's nothing wrong with inventing new patterns, but it can be done well or badly.
I've seen similar void build() method in the JCodeModel class. As you can see it throws IOException because of the resources it manages:
public void build(File destDir,
PrintStream status)
throws IOException
You basically ask it to carry out the operation for you and if no error is present - you can continue with the workflow.
In general builder is used in following way:
Some class will use builder to create class. Simple
Now you have additional piece of complexity - caching. You can put caching inside Builder or one level higher inside Processor.
What are the implications of putting cache management inside builder:
Builder does not have single responsibility anymore.
It does not work how you would expect at first glance
You are unable to create object without putting it into cache
These problems will not occur if you put cache management to separate class.
I would say that it is not terrible solution, but it certainly will decrease maintainability of your code.
I am trying to generate documentation for existing services. Its a bunch of rest services. What I would like to do is to simply create a new tag in xdoclet, that new tag will have a parameter. something like
#JSONInputMessage("com.foo.bar.input")
#JSONOutputMessage("com.foo.bar.output")
the xdoclet will then go to that class, initialize it, dump it into Jackson to convert it to json, and then copy the resulting json into the javadoc.
All of this is simple enough. My problem is i need a way to take in an object, then walk the fields all the way down, initializing the objects so they actually show up in the json dump. Does anyone have an easy way to reflect thru an object and initialize all objects?
Podam initializes a java object tree with random data, but you may define a strategy or use attributes to decide the values that are set.
Simple example:
PodamFactory factory = new PodamFactoryImpl(); //This will use the default Random Data Provider Strategy
Pojo myPojo = factory.manufacturePojo(Pojo.class);
Or with a strategy:
DataProviderStrategy strategy = new MyDataProviderStrategy();
PodamFactory factory = new PodamFactoryImpl(strategy);
Pojo myPojo = factory.manufacturePojo(Pojo.class);
Or with attributes:
#PodamStrategyValue(PostCodeStrategy.class)
private String postCode;
and then you define the strategy class for that single attribute:
public class PostCodeStrategy implements AttributeStrategy<String> {
public String getValue() throws PodamMockeryException {
...
}
}
Would this work for you?