Question

I have been working with a small project recently which involves Struts 2 and Spring 3 and my colleague had written very BAD code:

We have to implement two modules of similar functionalities: the both needs to list/add/show/update/delete Java Bean object, and those two Java Bean object has many fields in common, they all have id/content/image_url/created_time/user, the only difference is one bean has 2 fields to store offsets in created_time and the other has to store start_time and end_time.

So my colleague decided to implement one of them in one struts Action class and copy the code and made some small changes then he had another Action class in place.

I am struggling to fix his mistake, what design pattern or practice can solve my problem?

ADD:

I have tried to make those two Action classes extend the same base class, unfortunately, Struts 2 seem to ignore setters/getters of parent classes, and you can't use generic types either because again, Struts 2 won't know which class to instantiate and give to the setters in Action classes.

I want to reduce the repeated code, but because of those 2 problems stated above, I ended up making even more repeated code and much too complicated class structure which is on the edge of being broken.

ADD 2:

I tested the following code using stuts2-json-plugin(because it's easier to observe data in JSON format):

struts.xml:

<package name="inherit" namespace="/inherit" extends="json-default">
        <action name="base" method="doStuff" class="com.carllee.exp.BaseAction">
            <result type="json">
                <param name="excludeNullProperties">true</param>
            </result>
        </action>
        <action name="extended" method="doStuff" class="com.carllee.exp.ExtendedAction">
            <result type="json">
                <param name="excludeNullProperties">true</param>
            </result>
        </action>
</package>

the Java code

package com.carllee.exp;

import com.carllee.exp.bean.Message;
import com.opensymphony.xwork2.ActionSupport;

public class BaseAction extends ActionSupport {

    private Message message; // and getter/setter
    private String text;     // and getter/setter

    public String doStuff() {
        return SUCCESS;
    }

}

child class:

package com.carllee.exp;

public class ExtendedAction extends BaseAction {

}

if I run this test and go to http://localhost:8080/struts2-exp/inherit/base?message.content=hello, the result would be:

{"message" : {"content":"hello"}}

if I go to http://localhost:8080/struts2-exp/inherit/extended?message.content=hello, the result would be:

{}

and there would be warnings in the console

This is why I say Struts 2 ignores setters/getters in parent class.

Was it helpful?

Solution

  • Subclass the action and add the other properties?
  • Use the same action but different views?
  • Make one bean with all three fields, different views, default when not used?
  • Use ModelDriven and decide which model to instantiate based on a single action's "method" configuration?
  • Etc...

Lots of options. Which is "best" depends on details we don't have.

If that's the extend of BAD code you have to deal with, consider yourself lucky--this sounds trivial to refactor. What's the actual struggle?

OTHER TIPS

I suggest to create an abstract action class with the common part, and two subclasses (actions that will be called). The abstract class cannot be called directly.

In your application, the subclasses can use all the code in the parent abstract class.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top