This is probably a very basic question but at the moment i'm practicing with spring and notice that the #autowire annotation creates a constructor without variables in the background and forces to use methods.
So now i have following question what is the difference between.
public class Example {
private String stuffA;
private String moreStuffB;
private User user ;
public Example(String stuffA, String moreStuffB, User user) {
this.stuffA = stuffA;
this.moreStuffB = moreStuffB;
this.user = user;
}
public String ShowUserName (){
return user.getFirstName();
}
public String ShowStuff(){
return stuffA + " " + moreStuffB;
}
}
And this :
public class Example {
public Example() {
}
public String ShowUserName (User user){
return user.getFirstName();
}
public String ShowStuff(String stuffA,String moreStuffB){
return stuffA + " " + moreStuffB;
}
}
What is the preferred way or does it depends on the situation?
And what are the pro's and con's between these 2 examples?
In the first case, you call example.showStuff().
In the second case, you call example.showStuff("stuff", "moreStuff").
The difference is whether the caller needs to be able to provide the values for these two objects or they are part of the object instance.
Real-life example for a combination of both:
dateFormatter.format(yesterday)
Here the caller provides the date to format, but the dateFormatter knows what formatting pattern should be used.
In this program I have three numbers the user enters in and I am trying to get the second number in the set to display by being pulled from the DTO so that I can confirm that everything is working fine. But something is going wrong as you'll see by the output...
User Enters: 858508321,858509491,858510385
//This code is what is being executed. (Think of it as main)
private void handleSubmit(final AjaxRequestTarget target) {
List<Long> msgNums = new ArrayList<Long>();
msg_Num = Ta.getInput();
String[] Numbers = msg_Num.split(",");
for(String Number:Numbers){
msgNums.add(Long.valueOf(Number));
}
System.out.println(msgNums.get(1));
List<BulkReplayMessageDTO> brm = messageReplayDao.getMessageResults(msgNums);
System.out.println(brm.get(1).getMsgNum());
}
//This is the DAO
public class MessageReplayDao extends SimpleJdbcDaoSupport {
private final static String sql = "SELECT MSG_NBR, MSG_CPSD_DATA"
+ " FROM nti_raw_msg"
+ " WHERE THRD_NAME IS NOT null AND THRD_NAME NOT LIKE"
+ " 'out%' AND MSG_NBR IN (:messageNumbers)";
public List<BulkReplayMessageDTO> getMessageResults(final List<Long> msgNumList){
SqlParameterSource parameters = new MapSqlParameterSource()
.addValue("messageNumbers", msgNumList);
List<BulkReplayMessageDTO> result = getSimpleJdbcTemplate().query(sql, new MessageReplayMap(), parameters);
return result;
}
}
//The Map
public class MessageReplayMap implements ParameterizedRowMapper<BulkReplayMessageDTO> {
public MessageReplayMap(){
}
LobHandler lobHandler = new DefaultLobHandler();
#Override
public final BulkReplayMessageDTO mapRow(ResultSet rs, int rowNum)
throws SQLException {
final BulkReplayMessageDTO brm = new BulkReplayMessageDTO();
System.out.println(rowNum);
brm.setMsgNum(rs.getLong("MSG_NBR"));
brm.setMSG(CompressionUtils.uncompress(lobHandler.getBlobAsBytes(rs, "MSG_CPSD_DATA")));
return brm;
}
}
//And finally the DTO
public class BulkReplayMessageDTO{
private static Long msgNum;
private static String MSG;
public final Long getMsgNum() {
return msgNum;
}
public final void setMsgNum(final Long msgNumTemp) {
msgNum = msgNumTemp;
}
public final String getMSG(){
return MSG;
}
public final void setMSG(final String MSGTemp){
MSG = MSGTemp;
}
}
Notice that I have printed to the console in the handleSubmit method, and inside my map. The output I get is
858509491
0
1
2
858510385
when it should be
858509491
0
1
2
858509491
I have no clue what the problem could be since I have found other code example that are pretty much the same and mine seems to be pretty similar. I am pretty new to using Spring, so sorry if the answer is really obvious.
I have found the problem, and it was a really simple one. In the DTO the variables were made static from a previous problem I was working on. I had forgotten to get rid of it after I had fixed the issue. If I understand the meaning of static, then I had made all the instances of those variables the same. So that is why I could only print out the last number that had been entered in by the user.
Given the following code:-
//setup code and import statements, including:
private static String baseURL = Environment.getTestWebsiteURL();
public static String articleOneName = ArticleCreationTest.getArticleOneName();
public static String articleTwoName = ArticleCreationTest.getArticleTwoName();
public static String articleThreeName = ArticleCreationTest.getArticleThreeName();
public static String articleOnePath = ArticleCreationTest.getArticleOnePath();
public static String articleTwoPath = ArticleCreationTest.getArticleTwoPath();
public static String articleThreePath = ArticleCreationTest.getArticleThreePath();
public static String[] articlesPathArray = {articleOnePath, articleTwoPath, articleThreePath}
#BeforeClass
public static void setup() {
driver = Driver.getURL();
for (String s : articlesArray) {
if (s == null) {
//tell me which articles could not be found
System.out.println("Could not find an article for: " + s + " , perhaps it wasn't created in the prior test");
} else {
//assuming array holds some path values, append to the baseURL
driver.get(baseURL + s);
}
}
#Test...
//run some test assertions against the baseURL + path website page that is returned
I need the code to loop through wherever the path variable holds a value and run tests. The current solution is not helpful wherever the prior ArticleCreationTest fails to generate the article, because the variable simply contains null. So the text is: "Could not find an article for: null, perhaps it wasn't created in the prior test".
What I really need is to associate the articleName with the articlePath so the message is something like: "Could not find ArticleOne: perhaps is wasn't created", and then run the tests against all that were created. Perhaps some kind of hashmap or 2D array?
Based on the code given,
public static String articleOneName = ArticleCreationTest.getArticleOneName();
public static String articleTwoName = ArticleCreationTest.getArticleTwoName();
public static String articleThreeName = ArticleCreationTest.getArticleThreeName();
public static String articleOnePath = ArticleCreationTest.getArticleOnePath();
public static String articleTwoPath = ArticleCreationTest.getArticleTwoPath();
public static String articleThreePath = ArticleCreationTest.getArticleThreePath();
public static String[] articlesPathArray = {articleOnePath, articleTwoPath, articleThreePath}
It seems like, it is a list of articleNames and articlePaths
List<String> acticleNames = new ArrayList<String>();
List<String> acticlePaths = new ArrayList<String>();
The List will contain the Strings to be checked, which can be used for the tests.
I need the code to loop through wherever the path variable holds a
value and run tests
You can check this condition by checking if (s != null), currently you are checking for
if (s == null)
I was asked this question in an interview to improve the code that was provided. The provided code used lot of if statements and therefore I decided to use HashMap as retrieval would be faster. Unfortunately, I was not selected for the position. I am wondering if someone knows a better way than what I did to improve the code?
/* The following Java code is responsible for creating an HTML "SELECT" list of
U.S. states, allowing a user to specify his or her state. This might be used,
for instance, on a credit card transaction screen.
Please rewrite this code to be "better". Submit your replacement code, and
please also submit a few brief comments explaining why you think your code
is better than the sample. (For brevity, this sample works for only 5
states. The real version would need to work for all 50 states. But it is
fine if your rewrite shows only the 5 states here.)
*/
/* Generates an HTML select list that can be used to select a specific U.S.
state.
*/
public class StateUtils {
public static String createStateSelectList() {
return
"<select name=\"state\">\n"
+ "<option value=\"Alabama\">Alabama</option>\n"
+ "<option value=\"Alaska\">Alaska</option>\n"
+ "<option value=\"Arizona\">Arizona</option>\n"
+ "<option value=\"Arkansas\">Arkansas</option>\n"
+ "<option value=\"California\">California</option>\n"
// more states here
+ "</select>\n"
;
}
/* Parses the state from an HTML form submission, converting it to the
two-letter abbreviation. We need to store the two-letter abbreviation
in our database.
*/
public static String parseSelectedState(String s) {
if (s.equals("Alabama")) { return "AL"; }
if (s.equals("Alaska")) { return "AK"; }
if (s.equals("Arizona")) { return "AZ"; }
if (s.equals("Arkansas")) { return "AR"; }
if (s.equals("California")) { return "CA"; }
// more states here
}
/* Displays the full name of the state specified by the two-letter code. */
public static String displayStateFullName(String abbr) {
{
if (abbr.equals("AL")) { return "Alabama"; }
if (abbr.equals("AK")) { return "Alaska"; }
if (abbr.equals("AZ")) { return "Arizona"; }
if (abbr.equals("AR")) { return "Arkansas"; }
if (abbr.equals("CA")) { return "California"; }
// more states here
}
}
My solution
/* Replacing the various "if" conditions with Hashmap<key, value> combination
will make the look-up in a constant time while using the if condition
look-up time will depend on the number of if conditions.
*/
import java.util.HashMap;
public class StateUtils {
/* Generates an HTML select list that can be used to select a specific U.S.
state.
*/
public static String createStateSelectList() {
return "<select name=\"state\">\n"
+ "<option value=\"Alabama\">Alabama</option>\n"
+ "<option value=\"Alaska\">Alaska</option>\n"
+ "<option value=\"Arizona\">Arizona</option>\n"
+ "<option value=\"Arkansas\">Arkansas</option>\n"
+ "<option value=\"California\">California</option>\n"
// more states here
+ "</select>\n";
}
/* Parses the state from an HTML form submission, converting it to the
two-letter abbreviation. We need to store the two-letter abbreviation
in our database.
*/
public static String parseSelectedState(String s) {
HashMap<String, String> map = new HashMap<String, String>();
map.put("Alabama", "AL");
map.put("Alaska", "AK");
map.put("Arizona", "AZ");
map.put("Arkansas", "AR");
map.put("California", "CA");
// more states here
String abbr = map.get(s);
return abbr;
}
/* Displays the full name of the state specified by the two-letter code. */
public static String displayStateFullName(String abbr) {
{
HashMap<String, String> map2 = new HashMap<String, String>();
map2.put("AL", "Alabama");
map2.put("AK", "Alaska");
map2.put("AZ", "Arizona");
map2.put("AR", "Arkansas");
map2.put("CA", "California");
// more state abbreviations here here
String full_name = map2.get(abbr);
return full_name;
}
}
}
I think there are many things wrong with your code, not least the recreation of the Map for each method call.
I would start at the very beginning, with interfaces. We need two things; a State and a StateResolver. The interfaces would look like this:
public interface State {
String fullName();
String shortName();
}
public interface StateResolver {
State fromFullName(final String fullName);
State fromShortName(final String shortName);
Set<? extends State> getAllStates();
}
This allows the implementation to be swapped out for something more sensible at a later stage, like a database. But lets stick with the hardcoded states from the example.
I would implement the State as an enum like so:
public enum StateData implements State {
ALABAMA("Alabama", "AL"),
ALASKA("Alaska", "AK"),
ARIZONA("Arizona", "AZ"),
ARKANSAS("Arkansas", "AR"),
CALIFORNIA("Californiaa", "CA");
private final String shortName;
private final String fullName;
private StateData(final String shortName, final String fullName) {
this.shortName = shortName;
this.fullName = fullName;
}
#Override
public String fullName() {
return fullName;
}
#Override
public String shortName() {
return shortName;
}
}
But, as mentioned above, this can be replaced with a bean loaded from a database. The implementation should be self-explanatory.
Next onto the resolver, lets write one against our enum:
public final class EnumStateResolver implements StateResolver {
private final Set<? extends State> states;
private final Map<String, State> shortNameSearch;
private final Map<String, State> longNameSearch;
{
states = Collections.unmodifiableSet(EnumSet.allOf(StateData.class));
shortNameSearch = new HashMap<>();
longNameSearch = new HashMap<>();
for (final State state : StateData.values()) {
shortNameSearch.put(state.shortName(), state);
longNameSearch.put(state.fullName(), state);
}
}
#Override
public State fromFullName(final String fullName) {
final State s = longNameSearch.get(fullName);
if (s == null) {
throw new IllegalArgumentException("Invalid state full name " + fullName);
}
return s;
}
#Override
public State fromShortName(final String shortName) {
final State s = shortNameSearch.get(shortName);
if (s == null) {
throw new IllegalArgumentException("Invalid state short name " + shortName);
}
return s;
}
#Override
public Set<? extends State> getAllStates() {
return states;
}
}
Again this is self explanatory. Variables are at the instance level. The only dependency on the StateData class is in the initialiser block. This would obviously need to be rewritten for another State implementation but that should be not big deal. Notice this class throws an IllegalArgumentException if the state is invalid - this would need to be handled somewhere, somehow. It is unclear where this would happen but something that needs to be considered.
Finally we implement the required methods in the class
public final class StateUtils {
private static final StateResolver STATE_RESOLVER = new EnumStateResolver();
private static final String OPTION_FORMAT = "<option value=\"%1$s\">%1$s</option>\n";
public static String createStateSelectList() {
final StringBuilder sb = new StringBuilder();
sb.append("<select name=\"state\">\n");
for (final State s : STATE_RESOLVER.getAllStates()) {
sb.append(String.format(OPTION_FORMAT, s.fullName()));
}
sb.append("</select>\n");
return sb.toString();
}
public static String parseSelectedState(final String s) {
return STATE_RESOLVER.fromFullName(s).shortName();
}
public static String displayStateFullName(final String abbr) {
return STATE_RESOLVER.fromShortName(abbr).fullName();
}
}
Notice we only reference the implementation at the top of the utility class, this makes swapping out the implementation quick and painless. We use a static final reference to that the StateResolver is created once and only once. I have also replaced the hardcoded creation of the select with a dynamic loop based one. I have also used a formatter to build the select.
It should be noted that it is never a good idea to build HTML in Java and anyone that does so should have unspeakable things done to them.
Needless to say you should have thorough unit tests against each and every line of the above code.
In short your answer doesn't really come close to a proper, extensible, enterprise solution to the problem at hand. My solution might seem overkill, and you may be right. But I think it's the correct approach because abstraction is key to reusable code.
To avoid manually maintaining 2 maps and keeping them in sync I would just create the second one as the first one inverted. See here on how to do it.
Also as pointed out by others you need to create your maps only once outside of method call.
** Just for fun a way to do it in Scala **
val m = Map("AL" -> "Alabama", "AK" -> "Alaska")
m map { case (k, v) => (v, k) }
// gives: Map(Alabama -> AL, Alaska -> AK)
Everyone seems focused on the parse, but the create can be improved, too. Get all of the state names, sort them alphabetically, and iterate over that collection to create each option. That way, the states used for parsing are always in sync with the states used for cresting. If you add a new state, you only need to add it to the "master" Enum (or whatever), and both methods will reflect the change.
The only mistake you made was to rebuild the map every time around. If you had built the Map just once - perhaps in a constructor I suspect you would have done fine.
public class StateUtils {
class State {
final String name;
final String abbreviation;
public State(String name, String abbreviation) {
this.name = name;
this.abbreviation = abbreviation;
}
}
final List<State> states = new ArrayList<State>();
{
states.add(new State("Alabama", "AL"));
states.add(new State("Alaska", "AK"));
states.add(new State("Arizona", "AZ"));
states.add(new State("Arkansas", "AR"));
states.add(new State("California", "CA"));
}
final Map<String, String> nameToAbbreviation = new HashMap<String, String>();
{
for (State s : states) {
nameToAbbreviation.put(s.name, s.abbreviation);
}
}
final Map<String, String> abbreviationToName = new HashMap<String, String>();
{
for (State s : states) {
nameToAbbreviation.put(s.abbreviation, s.name);
}
}
public String getStateAbbreviation(String s) {
return nameToAbbreviation.get(s);
}
public String getStateName(String abbr) {
return abbreviationToName.get(abbr);
}
}
One thing I don't like about your code is that you create a hashmap each time the method is called. The map should be created just once, at class init time, and referenced from the method.
What you did wrong is what guys are saying - you are creating a new HashMap every time the method is invoked - a static field could rather congaing the data, and populating it only once the class is being loaded my the JVM.
I'd rather use simple switch on strings - the search is not worse than that of HashMap (at least asymptotically) but you don't use extra memory. Though you need two long switches - more code.
But than again HashMap solution the the later one would be the same for me.
I just started playing with Sencha's Ext GWT yesterday and I've hit a wall. I combined methods from their JSON loaded grid and their editable grid. As a test data set I'm using a list of Stargate Atlantis episodes hence the SGAEpisode which is defined as:
public class SGAEpisode extends BaseModel {
public SGAEpisode() {
}
public SGAEpisode(String season, String episode) {
set("season",season);
set("episode",episode);
}
public void setSeason(String season) {
set("season",season);
}
public String getSeason(){
return get("season");
}
public void setEpisode(String name) {
set("episode",name);
}
public String getEpisode() {
return get("episode");
}
public String toString() {
return "Season: " + get("season") + " episode: " + get("episode");
}
}
the onModuleLoad() starts off with...
ModelType type = new ModelType();
type.setRoot("seasons");
type.addField("Season","season");
type.addField("Episode","episode");
String path = GWT.getHostPageBaseURL() + "senchaapp/sgaepisodes";
final RequestBuilder builder = new RequestBuilder(RequestBuilder.GET,path);
final MVProxy<String> proxy = new SProxy<String>(builder);
JsonLoadResultReader<ListLoadResult<SGAEpisode>> reader = new JsonLoadResultReader<ListLoadResult<SGAEpisode>>(type);
final BaseListLoader<ListLoadResult<SGAEpisode>> loader = new BaseListLoader<ListLoadResult<SGAEpisode>>(proxy,reader);
final ListStore<SGAEpisode> episodes = new ListStore<SGAEpisode>(loader);
so loader.load() works great, populating a grid, I can edit fields, but I don't see commitChanges() doing anything and I can't iterate over the ListStore "episodes" to gather changed or added values. Oh, and SProxy is just a DataProxy subclass to allow me to specify the season's JSON I'm loading into the grid.
If I try either
for(SGAEpisode episode : episodes) {
save(episode);
}
or
for(int i = 0; i < episodes.getCount(); i++) {
save(episodes.getAt(i));
}
I get an exception with the message "com.extjs.gxt.ui.client.data.BaseModel cannot be cast to com.mvsc.sencha.shared.SGAEpisode" Any idea what I'm doing wrong? Everything up to that point was defined/populated with SGAEpisodes.....
Addendum
Ok, so if I try
List<Record> modified = episodes.getModifiedRecords();
for(Record r : modified) {
ModelData md = r.getModel();
save(md.get("season"),md.get("episode"));
}
I can iterate, and get the modified values, but what's the point of having a ModelData subclass if I have to use the base class like this. Which makes me think I don't in fact have to..... little help?
Addendum 2 I tried subclassing BaseModelData instead with no success.
I know its an older post, I had the same issue. This is how I fixed it.
try iterating through the models in listStore.
for(SGAEpisode episode : episodes.getModels()) {
save(episode);
}