In Class1 we have a method:
public void check(String username, String password) {
if (username and password are correct) {
message = "checked";
} else
{
message = "not checked";
}
}
In Class2 we have a method doPost and then we do this :
Class1 cl = new Class1();
cl.open();
cl.check(username,password);
cl.close()
In class Error I would like to show the message, which is in Class1. Maybe with one Dispatcher? Which is the most efficiency way to make it?
Surely there are much better ways for that, but if you don't want to change your solution as you are setting a message in Class1, you should be able to access to that message in Class2, so create getter and setter for the message variable and access the message via getter(and setters):
in Class1:
public String setMessage(String message){
this.message=message;
}
public String getMessage(){
return message;
}
public void check(String username, String password) {
if (username and password are correct) {
message = "checked";
} else
{
message = "not checked";
}
}
in Class2:
Class1 cl = new Class1();
cl.open();
cl.check(username,password);
cl.close();
out.println(cl.getMessage());//or anything else(you have access to generated message)
You can throw an exception in check() if the check fails.
Related
I have an abstract class
public abstract class Sender {
private IThrottler throttler;
public final Object sendMessage(String smsText, String smsSenderName, String contactNumber) throws Exception {
tdLogger.info("sending request >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
String messageId = (String) sendSMS(smsText, smsSenderName, contactNumber);
tdLogger.info("request sent <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
return messageId;
}
public final Object throttleMessage(String smsText, String smsSenderName, String contactNumber) throws Exception {
if (throttler != null) {
throttler.acquire();
tdLogger.info("sending request >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
String messageId = (String) sendSMS(smsText, smsSenderName, contactNumber);
tdLogger.info("request sent <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
return messageId;
} else {
throw new Exception("throttler is not initialized");
}
}
public abstract Object send(String smsText, String smsSenderName, String contactNumber) throws Exception;
}
I have another class SenderImpl that which extends Sender
is there a way to force implementing the function send without giving the ability to call it directly and only be able to call sendMessage and throttleMessage to force running certain logic?
You can make the abstract send method protected so that only subclasses and classes in the same package can call it. This achieves what you intend even if it can be circumvented by placing a class in the same package.
Here is my code
public class Validator {
private String message = "ok";
public String mainValidate(String value) {
if(!isAccept1()) {
message = "fail1";
return message;
}
if(!isAccept2()) {
message = "fail2";
return message;
}
if(!isAccept3()) {
message = "fail3";
return message;
}
return message;
}
public boolean isAccept1() {}
public boolean isAccept2() {}
public boolean isAccept3() {}
Requirement is: If the code meet any error, return message immediately.
As you can see, with current code, I repeat myself very much.
How can I structure the code and still keep requirement. If any error occur, the code skip other validate and return error message
Many thanks!
You can put all the checks in one method:
public String mainValidate(String value) {
String message = isAccept();
if(!message.equalsIgnoreCase("ok")) {
return message;
}
}
private String isAccept() {
String returnString = "ok";
//check1 - change returnString to whatever message if check fails
//check2 - change returnString to whatever message if check fails
//check3 - change returnString to whatever message if check fails
//etc...
return returnString;
}
You could store the actions / messages in a map and iterate over it:
private static final Map<Predicate<String>, String> VALIDATIONS = new LinkedHashMap<> ();
static {
VALIDATIONS.put(Validator::isAccept1, "fail1");
VALIDATIONS.put(Validator::isAccept2, "fail2");
//etc.
}
public String mainValidate(String value) {
for (Entry<Predicate<String>, String> v : VALIDATIONS.entrySet()) {
Predicate<String> validator = v.getKey();
String errorMsg = v.getValue();
if (!validator.test(value)) return errorMsg;
}
return "ok";
}
public static boolean isAccept1(String value) { return /* ... */; }
This is known as:
Design by Contract
or Precondition
or Method Argument Validation
See also A good Design-by-Contract library for Java?
I am trying to pull data from class in another class and populate a JPanel with the data, but it is not working for some reason.
Here is the full restConnector class where I pull the JSON data.
As far as I know this works fine.
public class restConnector {
private static final Logger LOGGER = LoggerFactory.getLogger(restConnector.class);
private static final restConnector INSTANCE = new restConnector();
public static restConnector getInstance() {
return restConnector.INSTANCE;
}
private restConnector(){
}
private static String user = "ss";
private static String pwd = "ee
public static String encode(String user, String pwd) {
final String credentials = user+":"+pwd;
BASE64Encoder encoder = new sun.misc.BASE64Encoder();
return encoder.encode(credentials.getBytes());
}
//Open REST connection
public static void init() {
restConnector.LOGGER.info("Starting REST connection...");
try {
Client client = Client.create();
client.addFilter(new LoggingFilter(System.out));
WebResource webResource = client.resource("https://somewebpage.com/
String url = "activepersonal";
ClientResponse response = webResource
.path("api/alerts/")
.queryParam("filter", ""+url)
.header("Authorization", "Basic "+encode(user, pwd))
.header("x-api-version", "1")
.accept("Application/json")
.get(ClientResponse.class);
if (response.getStatus() != 200) {
}else{
restConnector.LOGGER.info("REST connection STARTED.");
}
String output = response.getEntity(String.class);
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(new MyNameStrategy());
try {
List<Alert> alert = mapper.readValue(output, new TypeReference<List<Alert>>(){});
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void close() {
}
}
However, when I try to pull the data in another class it gives me just null values from the system.out.print inside refreshData() method. Here is the code that is supposed to print the data
public class Application{
Alert alerts = new Alert();
public Application() {
refreshData();
}
private void initComponents() {
restConnector.init();
refreshData();
}
private void refreshData() {
System.out.println("appalertList: "+alerts.getComponentAt(0));
}
}
Here is my Alert class
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonInclude(Include.NON_EMPTY)
public class Alert {
private int pasID;
private String status;
private boolean shared;
private String header;
private String desc;
public int getPasID() {
return pasID;
}
public void setPasID(int pasID) {
this.pasID = pasID;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public boolean isShared() {
return shared;
}
public void setShared(boolean shared) {
this.shared = shared;
}
public String getHeader() {
return header;
}
public void setHeader(String header) {
this.header = header;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("\n***** Alert Details *****\n");
sb.append("PasID="+getPasID()+"\n");
sb.append("Status="+getStatus()+"\n");
sb.append("Shared="+isShared()+"\n");
sb.append("Header="+getHeader()+"\n");
sb.append("Description="+getDesc()+"\n");
sb.append("*****************************");
return sb.toString();
}
public String getComponentAt(int i) {
return toString();
}
}
I'm kind a lost with this and been stuck here for a couple of days already so all help would be really appreciated. Thanks for the help in advance.
Edit: Formatted the code a bit and removed the NullPointerException as it was not happening anymore.
As stated in comments:
Me: In your first bit of code you have this try { List<Alert> alert.., but you do absolutely nothing with the newly declared alert List<Alert>. It this where the data is supposed to be coming from?
OP: I'm under the impression that that bit of code is the one that pushes the JSON Array to the Alert.class. Is there something I'm missing there?
Me: And what makes you think it does that? All it does is read the json, and the Alert.class argument is the class type argument, so the mapper know the results should be mapped to the Alert attributes when it creates the Alert objects. That's how doing List<Alert> is possible, because passing Alert.class decribes T in List<T>. The List<Alert> is what's returned from the reading, but you have to determine what to actually do with the list. And currently, you do absolutely nothing with it
You maybe want to change the class just a bit.
Now this is in no way a good design, just an example of how you can get it to work. I would take some time to sit and think about how you want the restConnector to be fully utilized
That being said, you can have a List<Alert> alerts; class member in the restConnector class. And have a getter for it
public class restConnector {
private List<Alert> alerts;
public List<Alert> getAlerts() {
return alerts;
}
...
}
Then when deserializing with the mapper, assign the value to private List<Alert> alerts. What you are doing is declaring a new locally scoped list. So instead of
try {
List<Alert> alert = mapper.readValue...
do this instead
try {
alerts = mapper.readValue
Now the class member is assigned a value. So in the Application class you can do something like
public class Application {
List<Alert> alerts;
restConnector connect;
public Application() {
initComponents();
}
private void initComponents() {
connector = restConnector.getInstance();
connector.init();
alerts = connector.getAlerts();
refreshData();
}
private void refreshData() {
StringBuilder sb = new StringBuilder();
for (Alert alert : alerts) {
sb.append(alert.toString()).append("\n");
}
System.out.println("appalertList: "+ sb.toString());
}
}
Now you have access to the Alerts in the list.
But let me reiterate: THIS IS A HORRIBLE DESIGN. For one you are limiting the init method to one single call, in which it is only able to obtain one and only one resource. What if the rest service needs to access a different resource? You have made the request set in stone, so you cant.
Take some time to think of some good OOP designs where the class can be used for different scenarios.
I'm trying to bind some data from a POST, but for some reason, it keeps throwing an exception. The weird thing though is that I have an almost identical object that is bound just fine. Some of my code is as follows:
public static Result login() {
return ok(
login.render(Form.form(Login.class))
);
}
public static Result authenticate() {
Form<Login> loginForm = Form.form(Login.class).bindFromRequest();
// Do stuff
}
public static Result createUser() {
return ok(createUser.render(Form.form(NewUser.class)));
}
public static Result createUserPost() {
Form<NewUser> newUserForm = Form.form(NewUser.class).bindFromRequest();
// Do stuff
}
public static class Login {
public String userName;
public String password;
public String validate(){
Logger.info("userName: %s, Password: %s", userName, password);
if (User.validate(userName, password) == null){
return "Invalid username or password";
}
return null;
}
}
public static class NewUser {
public String userName;
public String password;
public String validate() {
// TODO: Better error messages
if (Validation.username(userName) == null && Validation.password(password) == null) {
return null;
}
else {
return "The username or password is not valid.";
}
}
}
For some reason, the authenticate method binds the Login class fine, but the createUserPost method doesn't bind the NewUser class (both views are exactly the same with the exception that the Form type is either Login or NewUser). The weirder thing is that if I change the createUser, createUserPost, and the view to use the Login class, it binds just fine.
Does anyone have any idea why this is happening?
So it turns out that for some reason Play (or Java) doesn't like having multiple static classes in the same Java file. Once we refactored the two classes out to their own files, it worked fine.
I am creating a client side swing app that will have data provided by/from one of many data providers(brokers). The data providers however, have varying ways of perfoming same things e.g.
broker1's login method
public boolean doLogin(String username, String password);
broker2's login method
public int login(String username, String password,String sessionId);
For all providers the set of required actions is the same
e.g
login, getstatus, sendRequest, getData, logOff
(but they have different params and return types)
I took a look at the adapter pattern but am unfortunately not able to use it well as the required methods have different parameters.
Is the adapter pattern usable in this case? if so how?
If not what would be the best way of doing this?
Thanks.
Patterns are general guidelines (starting point) of best practices. Many developers "adapts" the patterns to their needs; the important thing is, then, if you must use a pattern, use it consistently throughout your whole application.
Now, to answer your question; yes the adapter pattern can very well be used in your situation. A possible solution (in the like) could be:
abstract class BrokerAbstract<T> {
private int errCode;
private String errMessage;
abstract public boolean login(String user, String pass, Map<String,Object> options);
abstract public int getStatus(Map<String,Object> options);
abstract public boolean sendRequest(Map<String,Object> options);
abstract public T getData(Map<String,Object> options);
abstract public boolean logOff(Map<String,Object> options);
protected void setError(int code, String message) {
this.errCode = code;
this.errMessage = message;
}
public int getErrorCode() { return this.errCode; }
public String getErrorMessage() { return this.errMessage; }
}
Then
class Broker1 extends BrokerAbstract<Object> {
private OriginalBroker1 original;
public boolean login(String user, String pass, Map<String,Object> options) {
return original.doLogin(user, pass); // ignore options
}
public boolean login(String user, String pass) {
return login(user, pass, null); // third parameters will be ignored
}
public int getStatus(Map<String,Object> options) { /*...*/ return 0; }
public boolean sendRequest(Map<String,Object> options) { /*...*/ return false; }
public Object getData(Map<String,Object> options) {
return original.getData(); // OriginalBroker1.getData():Object
}
public boolean logOff(Map<String,Object> options) {
return original.doLogout((boolean) options.get("clearSession"));
}
public boolean logoff() {
HashMap<String,Object> options = new HashMap<String,Object>();
options.put("clearSession", true);
return logoff(options); // proxy to original method
}
}
Or
class Broker2 extends BrokerAbstract<Integer> {
private OriginalBroker2 original;
public boolean login(String user, String pass, Map<String,Object> options) {
int code = original.doLogin(user, pass, (String) options.get("sessionId"));
if (0 != code) {
setError(code, "Custom error message"); // could use enum here for messages...
return false;
} else {
return true;
}
}
public boolean login(String user, String pass, String sessionId) {
HashMap<String,Object> options = new HashMap<String,Object>();
options.put("sessionId", sessionId);
return login(user, pass, options);
}
public int getStatus(Map<String,Object> options) { /*...*/ return 0; }
public boolean sendRequest(Map<String,Object> options) { /*...*/ return true; }
public Integer getData(Map<String,Object> options) {
return original.getData(options.get("key")); // OriginalBroker2.getData(key:String):int
}
public boolean logOff(Map<String,Object> options) {
return original.doLogout();
}
public boolean logoff() {
return logoff(null); // ignore third parameter
}
}
Of course this is a very general approach. If you know that one method will be receiving strings for all parameters, you could also have a abstract signature like :
abstract public boolean login(String...args);
Then your concrete implementation would be :
abstract class A {
abstract public boolean login(String...args);
}
class B extends A {
public boolean login(String...args) { return this.login(args[0], args[1]); }
public boolean login(String user, String pass) { return original.login(user,pass); }
}
class C {
public void login() {
B b = new B();
b.login("foo", "secret");
// or
b.login(new String[] {"foo", "secret"});
// or !
b.login("foo", "secret", "sessionId"); // will ignore third, but otherwise would still work...
}
}
etc.
My first thought was looking into the facade pattern, which, in my 'Head First Design Patterns' book, is explained in the same chapter as Adapter and compared with a remoted control for home theatre components.
This facade would sit between the client app and the various brokers. So the client wouldn't have to care, which and how many brokers are part of the 'theatre', it just have to 'press the login button' and 'all broker connections are switched on'.