I have two controller classes extending basecontroller. I have a common functionality to be implemented and implementation is in basecontroller.
public class BaseController{
protected void populateWidget(List li, int zipcode){
//implementation for child A
populate only 10 employee records
//implementation specific to child B
populate 100 student records
}
}
public class ChildA extends BaseController{
List<Employees> li = ...
populateWidget(li, 90034)
}
public class ChildB extends BaseController{
List<Students> li = ...
populateWidget(li, 90034)
}
I have written setChildB method and working on it. like below
public class BaseController{
protected boolean childB;
protected void setIsChildB(boolean childB){ this.childB = childB;}
protect boolean isChildB(){ return childB; }
protected void populateWidget(List li, int zipcode){
//implementation for child A
if(!isChildB())
populate only 10 employee records
else
//implementation specific to child B
populate 100 student records
}
}
public class ChildA extends BaseController{
List<Employees> li = ...
populateWidget(li, 90034)
}
public class ChildB extends BaseController{
List<Students> li = ...
setChildB(true); //setting as child B call
populateWidget(li, 90034)
}
Please advice the best way to do it.
I recommend implementing a Template Method Pattern. You could have your base controller like this:
public class BaseController {
protected abstract void getPeople(List li, int zipcode);
protected void populateWidget(List li, int zipcode) {
//Do generic logic here
//Refer to child
getPeople(List li, int zipcode)
//Do some more generic stuff
}
}
And then each of your children like this:
public class ChildA extends BaseController {
#Override
protected void getPeople(List li, int zipcode) {
//Specific Logic here
}
}
The children each override the getPeople() method to do their own thing.
That way if you need a ChildC, you can simply extend the parent without changing it.
Update: Based on the comments, here is an alternative way of doing this.
I would not do it as a setter, rather I would make a constructor argument on the base class that takes the type of child as an argument. This makes sure that the compiler enforces that you will always have a value set
You could use a boolean but I recommend strongly using an Enum, String constant or int constant.
The above two points are mostly because I always anticipate that I might have to do a ChildC when some requirements change comes along and at that point you won't have to do changes to the base class. It also falls into the set of patterns that other programmers I work with would expect and therefore makes the code easier readable and maintainable by others.
Sample base class:
public class BaseController {
private int childType;
protected static final int CHILD_A = 1;
protected static final int CHILD_B = 2;
public BaseController(int aChildType) {
childType = aChildType;
}
protected void populateWidget(List li, int zipcode) {
switch (childType) {
case CHILD_A:
//Handle Child A
case CHILD_B:
//Handle Child B
}
}
}
The child implementation would look like this:
public class ChildA extends BaseController {
public ChildA () {
super(CHILD_A);
}
//The rest of your code goes here...
}
Note, that in the above example I am using integer constants for the sake of brevity. In the 21s century Java creating an Enum would be the preferred way to go.
Related
I have an abstract domain class containing a uid field, looking as below:
public abstract class GraphEntityWithUid extends GraphEntity {
private String uid = CommonUtils.newUid();
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
}
And, an abstract repository for it:
public abstract interface GraphEntityWithUidRepository<T extends GraphEntityWithUid> extends GraphRepository<T> {
public T findByUid(String uid);
}
I have a concrete domain class that inherits the uid, looking as below:
#NodeEntity
public class Attachment extends GraphEntityWithUid {
...
}
And, its repository looks as below:
public interface AttachmentRepository extends GraphEntityWithUidRepository<Attachment> {
}
Now, when I use the findByUid method as below:
// returns null
attachmentRepository.findByUid(uid);
it always returns null. However, if I re-declare the method in the AttachmentRepository as below, it works properly:
public interface AttachmentRepository extends GraphEntityWithUidRepository<Attachment> {
// Shouldn't this be automatically inherited??
public Attachment findByUid(String uid);
}
Why should I need to re-declare findByUid method in AttachmentRepository? Shouldn't it be automatically inherited from GraphEntityWithUidRepository?
Anyone already get to work with a AbstractIterationElementProcessor derived class in a spring project which uses Thymeleaf? I am trying use this to implement this kind of tag:
<form:form ...>
...
</form:form>
The element is iterated based on a List which should be generated inside the processor class, based on the array with the list of field of the class from model class passed to the view (named command).
In each iteration, one element of the list is processed by a switch-like structure inside the tag and a inner element is chosen (form:input, form:select, etc).
Right now, I have this code:
public class FormProcessor extends AbstractIterationElementProcessor {
public FormProcessor() {
super("form");
}
#Override
public void processClonedHostIterationElement(Arguments arguments, Element iteratedChild) {
//
}
#Override
public String getIteratedElementName(Arguments arguments, Element element) {
return "form";
}
#Override
public boolean removeHostIterationElement(Arguments arguments, Element element) {
return false;
}
#Override
public AbstractIterationElementProcessor.IterationSpec getIterationSpec(Arguments arguments, Element element) {
return null;
}
#Override
public int getPrecedence() {
return 1000;
}
}
But I am have some trouble to understand what implement in each method. Anyone can give a hint on how to do that?
I often want to refine posted data before use it, for example
public class Song() {
public String[] tags;
public String csvTags;
public void setTagsWithCsv() {
// this one should be more complicated for handling real data
this.tags = csvTags.split(",");
}
}
In this case, I have to call setTagsWithCsv method inside the method of the controller class.
#RequestMapping(value = "/song/create", method = POST)
public String createSong(Song song) {
song.setTagsWithCsv();
songService.create(song); // some code like this will come here
...
}
Is there any way to call the method with an annotation like '#PostConstruct'? The method should be called after a post request.
Maybe you just provided a bad example, but If your Song is in a form of POJO, you do it on a call to setCsvTags
public class Song {
private String[] tags;
private String csvTags;
public void setCsvTags(String csvTags) {
this.csvTags = csvTags;
this.tags = csvTags.split(",");
}
public void setTags(String[] tags) {
this.tags == tags;
String newCsvTags = Arrays.toString(tags);
this.csvTags = newCsvTags.substring(1, newCsvTags.length() - 1); // get rid of []
}
}
or make a method, without keeping explicit tags array
public class Song {
private String csvTags;
public void getTags() {
return csvTags.split(",");
}
}
Otherwise, there is no standard way of doing this, you can play with request interception before reaching your Controller, but I think it would be just a waste of time.
I have:
public FooPage( ... ) {
this.setDefaultModel( new CompoundPropertyModel(new GenericIdLDM( Foo.class, 1)) );
add(new Label("title"));
I'd like to have $subj.
I've found this solution from 2007 (point below) : http://www.mail-archive.com/wicket-user#lists.sourceforge.net/msg29603.html
However, it wouldn't work for CPM as it needs the constructor with model.
How could I make it work with CPM?
public class DefaultTextModel extends AbstractReadOnlyModel<String> {
private final IModel<String> delegate;
private final String def;
public DefaultTextModel(String def, IModel delegate) {
this.def = def;
this.delegate = delegate;
}
public String getObject() {
String s = delegate.getObject();
return (Strings.isEmpty(s)) ? def : s;
}
public void detach() {
delegate.detach();
}
}
You could have a custom Converter for your label. I think the better reflects your intentions as well. See for example https://cwiki.apache.org/WICKET/using-custom-converters.html#Usingcustomconverters-InWicket1.4
Other option could be JavaScript, check if the span is empty and then provide the default value.
I can override Label#initModel():
protected IModel<?> initModel() {
return new DefaultTextModel(defaultModel, super.initModel());
}
A simpler solution is to override Label#onComponentTagBody() and just apply the default text there.
(Sven Meier replied on the mailing list)
i have a class and want to create,delete and edit sessions on it
but have error:"object null reference" when i want to add data to my session.
if i remove inheritance from controller how can i handle it?
my data is string value like "name"
why this syntax: Session[name]=value; works fine in controller but not works in my class and give me null reference error?
public class StateManager : Controller
{
public void RemoveFromApplication(string name)
{
Session.Remove(name);
}
public void AddToApplication(string name, object value)
{
//value like "name"
Session[name]=value;
}
}
It probably doesn't work because the controller isn't instantiated the same way by MVC, when it doesn't matches the current route.
You could instead create a static class like this:
public static class SessionManager
{
public static void RemoveFromApplication(string name)
{
HttpContext.Current.Session.Remove(name);
}
public static void AddToApplication(string name, object value)
{
HttpContext.Current.Session[name] = value;
}
}
You could also pass the session in the the methods as a parameter:
public static class SessionManager
{
public static void RemoveFromApplication(string name, HttpSessionStateBase session)
{
session.Remove(name);
}
public static void AddToApplication(string name, object value, HttpSessionStateBase session)
{
session[name] = value;
}
}
The class and methods doesn't need to be static, if you don't want it to be.