Java interface access different classes by calling same interface - java

I want to use java interface in a way that i will make a call defining interface in my other class like 'private SoapURL soapURL;' and than i can access any class's method for example : i want to use login:-
private SoapURL soapURL;
SoapUrl = LoginSoap ();
String nameSpace = soapURL.getMethodName();
String url = soapURL.getUrl();
Is there any way to do something like this. I am sorry i am not very good with Object Oriented principles but if there is a solution for my problem i would like to know it. Thanks in advance.
public interface SoapURL {
public String getNameSpace();
public String getUrl();
public String getSoapAction();
public String getMethodName();
public String getTag();
}
LoginSoap class
public class LoginSoap implements SoapURL {
#Override
public String getNameSpace() {
return "https://host.com/MobileWFC/";
}
#Override
public String getUrl() {
return "https://host.com/MobileWFC/MobileWS.asmx";
}
#Override
public String getSoapAction() {
return "https://host.com/MobileWFC/UserControl";
}
#Override
public String getMethodName() {
return "UserControl";
}
#Override
public String getTag() {
return "Login Activity";
}
}
SignUpSoap class
public class SignUpSoap implements SoapURL {
#Override
public String getNameSpace() {
return "https://host.com/MobileWFC/";
}
#Override
public String getUrl() {
return "https://host.com/MobileWFC/MobileWS.asmx";
}
#Override
public String getSoapAction() {
return "https://host.com/MobileWFC/UserRegister";
}
#Override
public String getMethodName() {
return "UserRegister";
}
#Override
public String getTag() {
return "SignUp Activity";
}
}
ResetPasswordSoap class
public class ResetPasswordSoap implements SoapURL {
#Override
public String getNameSpace() {
return "https://host.com/MobileWFC/";
}
#Override
public String getUrl() {
return "https://host.com/MobileWFC/MobileWS.asmx";
}
#Override
public String getSoapAction() {
return "https://host.com/MobileWFC/UserPasswordReset";
}
#Override
public String getMethodName() {
return "UserPasswordReset";
}
#Override
public String getTag() {
return "Forget Password Activity";
}
}

Your implementation looks correct. To make use of it, you can do this in main:
SoapURL reset = new ResetPasswordSoap();
System.out.println(reset.getUrl());
This is a method of minimizing coupling in large systems. And reduces dependency between objects by making use of a common interface for groups of objects that work together. You might be new at Object oriented principles, but you are one step ahead of the game already
To pass it to a function, you do:
public JPanel resetPass(SoapURL reset) {
...
}
// In main:
JPanel resetPassPanel = resetPass(reset);

Just do, for example:
SoapURL example = new LoginSoap();
String a = example.getTag();
a should be equal to "Login Activity"

The main use of Interface is polymorphism, or the ability to perform the same
operation on a number of different objects,
which is exactly what you wanted in your scenario
Your approach is absolutely fine , just a modification needed
private SoapURL soapURL;
//SoapUrl = LoginSoap (); // This line should be replaced with the Below line
soapURL=new LoginSoap();
String nameSpace = soapURL.getMethodName();
String url = soapURL.getUrl();
Since LoginSoap, SignUpSoap,ResetPasswordSoap classes are implemented classes of SoapURL Interface , thus reference variable of SoapURL can store Object of any of these child classes
soapURL=new LoginSoap();//soapURL.someMethod will call method of LoginSoapClass
soapURL=new SignUpSoap();// will call method of SignUpSoap class
soapURL=new ResetPasswordSoap();

Related

Inject several implementations of an abstraction in a class

I hope you're doing well, I have a doubt when I try to create a method that can validate some business rules.
In this case, I have a class
public class ValidationUtils {
final List<CreditValidations> creditValidations;
public ValidationUtils(){
creditValidations = Arrays.asList(
new ValidateAge(),
new ValidateSalary()
);
}
public ValidationRs passAllValidations(Client client){
final var validationsFailed = new ArrayList<String>();
boolean validationResult = false;
for (CreditValidations creditValidationClasses : creditValidations){
validationResult = Boolean.logicalXor(creditValidationClasses .validate(client,validationsFailed),
validationResult);
}
final var rs = new ValidationRs();
rs.setSuccessfulValidations(validationResult);
rs.setValidationsFailed(validationsFailed);
return rs;
}
}
this class has a method called "passAllValidations" That method can evaluate each CreditValidation implementation and join their results, Using this code I don't need to create more methods when I have a new validation, only extends the abstraction and create the new Validation class and inject it in the ValidationUtils constructor.
the abstraction and implementation of CreditValidations look like
public abstract class CreditValidations {
protected final String errorCode;
protected CreditValidations(final String errorCode) {
this.errorCode = errorCode;
}
protected abstract boolean validate(final Client client,final List<String> validationsFailed);
protected boolean evaluateValidation(boolean validationResult, List<String> validationsFailed){
if (!validationResult){
setCode(validationsFailed);
}
return validationResult;
}
protected String getErrorCode() {
return this.errorCode;
}
protected void setCode(List<String> failedValidations) {
failedValidations.add(errorCode);
}
}
public class ValidateAge extends CreditValidations {
public ValidateAge() {
super(CreditValidationErrorEnum.ERROR_VALIDATING_AGE.getCode());
}
#Override
public boolean validate(final Client client, List<String> validationsFailed) {
return this.evaluateValidation(client.getAge() >= 18,validationsFailed);
}
}
in summary, my question is referring to the dependency injection in the class ValidationUtils, I don't know if it way is correct or if Spring Framework has some things that help me to inject all of the CreditValidation implementations and avoid using Array.asList(new NewValidationClass()) or another design pattern which can help.
Thanks in advance.

The interface class issue in the Java Spring

I try to learn Spring framework. I have some questions.
I create one controller and few class. Here is the controller:
#Controller
#RequestMapping("/man")
public class manController {
private SwordImp Sword = new SwordImp();
private GunImp Gun = new GunImp();
private String mainWeapon;
private String subWeapon;
#RequestMapping(value = "set/{weapon:[a-z A-Z 0-9]+}", method = RequestMethod.GET)
public String setWeapon(#PathVariable String weapon, Model model){
System.out.println(weapon);
if(weapon.equals("gun")){
Gun.set(weapon);
mainWeapon = Gun.getWeapon();
subWeapon = Gun.getSubWeapon();
}else{
if(weapon.equals("sword")){
Sword.set(weapon);
mainWeapon = Sword.getWeapon();
subWeapon = Sword.getSubWeapon();
}else{
mainWeapon = "no weapon";
subWeapon = "no sub weapon";
}
}
model.addAttribute("weapon_status", mainWeapon);
model.addAttribute("sub_weapon_status", subWeapon);
return "man/index";
}
}
I also create some class.
Weapon interface
public interface Weapon {
public void set(String weaponName);
public String getWeapon();
public String getSubWeapon();
}
Sword class
public class SwordImp implements Weapon {
private String weaponName = null;
public void set(String weapon) {
this.weaponName = "fire "+weapon;
}
public String getWeapon() {
return this.weaponName;
}
public String getSubWeapon() {
return "no sub weapon";
}
}
Gun Class
public class GunImp implements Weapon {
private String weaponName = null;
private String bullet = null;
public void set(String weapon) {
this.weaponName = "ice "+weapon;
this.bullet = "need bullet";
}
public String getWeapon() {
return this.weaponName;
}
public String getSubWeapon() {
return this.bullet;
}
}
The questions I have:
If I don't implement the Weapon class in the gun Class and sword class as below, it seems like that the function still can work... So why do we need to use interface?
Sword class
public class SwordImp {...}
Gun Class
public class GunImp {...}
I try to put the all of class into the repositories folder. Is this correct path? or do I need to put them into model folder?
At first, I try to put the weaponName variable and bullet variable that in the Gun class and Sword class into the weapon interface, so I don't need to declare them in every class, like this:
Weapon interface
public interface Weapon {
private String weaponName = null;
private String bullet = null;
public void set(String weaponName);
public String getWeapon();
public String getSubWeapon();
}
Sword class
public class SwordImp implements Weapon {
public void set(String weapon) {
this.weaponName = "fire "+weapon;
this.bullet = "no sub weapon";
}
public String getWeapon() {
return this.weaponName;
}
public String getSubWeapon() {
return this.bullet;
}
}
Gun Class
public class GunImp implements Weapon {
public void set(String weapon) {
this.weaponName = "ice "+weapon;
this.bullet = "need bullet";
}
public String getWeapon() {
return this.weaponName;
}
public String getSubWeapon() {
return this.bullet;
}
}
But this seems like that is wrong... what is the reason?
You can use the Abstract factory pattern to inject the specific weapon during runtime rather than hardcoding them in controller.
Consider that you have 100 different weapons, It will be hard to add all the weapon implementation class to the controller. You can find the example and implementation of this pattern in google. It is considered to be a best practice.
Try to follow the best practice. It will help you to learn better and write neat and maintainable code. yes moving to the model folder is better.
In OOP it is important to create your object well defined. Interface can only have the constant fields and methods. The state defined in the interface cannot be changed.

Optimizing copied code in Java, avoiding if clause and casting

I have two classes:
DocumentState and ElectronicDocumentState.
They look like this:
public class DocumentState extends LabeledEnum {
public static final DocumentState CREATED = new DocumentState("created");
// ..... - 15 other statuses
}
ElectronicDocumentState also extends LabeledEnum and has its own statuses, some are common like created, other are unique.
Then I have plenty of methods in code that take DocumentState as a parameter or are returning DocumentState as result. Now they should work also with ElectronicDocumentState.
Also I have plenty places that do:
if (DocumentSate.CREATED.equals(doc.getState()) || DocumentState.DELETED.equals(doc.getState())) {
//do something with document
}
I want to avoid 'if' and avoid creating new methods for ElectronicDocumentState as more state can appear in future.
How would you do that ?
So using the below example, how would you refactor it so it could work with DocumentState and ElectronicDocumentState? I have plenty of such methods that now should also work with ElectronicDocumentState. Someone asks us to mix electronicDocuments with documents in business logic:
private DocumentState getDocumentStateForDetails(Document doc, DocumentState sourceState) {
if (DocumentState.CREATED.equals(doc.getDocumentState())) {
if (sourceState.equals(DocumentState.CREATED)) {
return DocumentState.CREATED;
} else {
return DocumentState.BLOCKED;
}
} else {
return sourceState.getDocumentState();
}
}
If you are worrying about further extension of your state model, I'd suggest you to think about using inheritance instead of if/switch and instanceof by splitting the document class to Value and State, for instance. If you have the same set of available actions for any state of document, just use classical State pattern, otherwise, each State may have its own set of available actions:
public class Document {
public static CreatedDocument<Document> create(String author) {
return new CreatedDocument<>(new Document(author));
}
private String author;
//...
private Document(String author) {
//...
}
}
public class ElectronicDocument extends Document {
public static CreatedElectronicDocument create(String author, String url) {
return new CreatedElectronicDocument(author, url);
}
private String url;
//...
public ElectronicDocument(String author, String url) {
//...
}
//...
}
public interface DocumentState<T extends Document> {
T getDocument();
char getCode(); // might be needed for something like logging?
}
public abstract class AbstractDocumentState<T extends Document> implements DocumentState<T> {
protected final T document;
protected AbstractDocumentState(T document) {
this.document = document;
}
#Override
public T getDocument() {
return document;
}
}
public class CreatedDocument<T extends Document> extends AbstractDocumentState<T> {
public CreatedDocument(T document) {
super(document);
}
#Override
public char getCode() {
return 'C';
}
public DocumentState<T> delete() {
return new DeletedDocument<>(document);
}
}
public class CreatedElectronicDocument extends CreatedDocument<ElectronicDocument> {
public CreatedElectronicDocument(String author, String url) {
super(new ElectronicDocument(author, url));
}
public DownloadElectronicDocument download() {
return new DownloadElectronicDocument(document);
}
}
public class DownloadElectronicDocument extends AbstractDocumentState<ElectronicDocument> {
public DownloadElectronicDocument(ElectronicDocument document) {
super(document);
// DO DOWNLOAD HERE
}
#Override
public char getCode() {
return 'L';
}
public DocumentState<ElectronicDocument> delete() {
return new DeletedDocument<>(document);
}
}
public class DeletedDocument<T extends Document> extends AbstractDocumentState<T> {
public DeletedDocument(T document) {
super(document);
// DO DELETE HERE
}
#Override
public char getCode() {
return 'D';
}
}
Not sure you need getCode() now, when you use inheritance. BTW, switch works faster than a set of if/else if.
If you'd like to stay with your enum classes, why wouldn't to extract common states to a super class?
public class CommonDocumentState extends LabeledEnum {
public static final CommonDocumentState CREATED = new CommonDocumentState ("created");
..... - n other statuses
}
public class DocumentState extends CommonDocumentState {
..... - m other statuses
}
public class ElectronicDocumentState extends CommonDocumentState {
..... - k other statuses
}
That's the only way to have such generic rules like
if (DocumentSate.CREATED.equals(doc.getState()) || DocumentState.DELETED.equals(doc.getState())) {
//do something with document
}
be working for both DocumentState and ElectronicDocumentState.
There are not enough information about your domain to provide a final answer, but I have some suggestions:
it seems that both DocumentState and ElectronicDocumentState inherit from LabeledEnum; if you want to manage both of them in your methods you can make ElectronicDocumentState inherit from DocumentState of it's feasibile merge the two classes. This will allow to pass ElectronicDocumentState or DocumentState in your methods and perhaps solve your second question.
if you want to avoid the if you can build a list of allowed method and check against the list, something like:
L
public class YourClass {
List<DocumentSate> allowedStates=//init here or in constructor
....
public void yourMethod(....) {
if (allowedStates.contains(doc.getState())) {
//do something
}
}
allowedStates may be factored out in separate class if it is a common case. If you find the refactoring feasible, may be you can check if you are dealing with a finite state machine and implement it (with the help of some exisiting libraries).

implicit QueryStringBindable java.util.List[models.InputTimeSheetDataStore]

Hi i am trying to pass a list of objects of type models.InputTimeSheetDataStore from view to application.java and i am getting No QueryString binder found for type java.util.List[models.InputTimeSheetDataStore]. Try to implement an implicit QueryStringBindable for this type error
in application.java i am passing list of object to view
InputTimeSheetDataStore ITSDS= new InputTimeSheetDataStore();
ITSDS.ConsultantName=EmployeeFilter;
ITSDS.Client=ClientFilter;
ITSDS.Project=ProjectFilter;
ITSDS.Role=EmployeeRoleFilter;
ITSDS.Task=Task;
ITSDS.TimeSheetDate=TimeSheetDate;
ITSDS.Hours=TaskHours;
ITSDS.IsBilled=IsBilled;
ITSDS.Workplace=WorkPlace;
InputTimeSheetList.add(ITSDS);
return ok(TimeSheetInput.render(Consultant.PopulateConsultant(),Client.PopulateClient(),Project.PopulateProject(ClientFilter),
Consultant.PopulateConsultantRole(),Consultant.ConsultantRoleRate(EmployeeRoleFilter),InputTimeSheetList));
in view i am passing that object back to application.java
#(EmployeeList:java.util.List[String],ClientList:java.util.List[String],
ProjectList:java.util.List[String],EmployeeRoleList: java.util.List[String],Rate:String,
CurrentPage:List[InputTimeSheetDataStore])
<form id="TimeSheetEntryForm" name="TimeSheetEntryForm" action="#{routes.Application.save("name","name","name","name","name","name","name","name","name",CurrentPage)}" method="GET">
<code.....>
here is my class file
InputTimeSheetDataStore.java
package models;
public class InputTimeSheetDataStore {
public String ConsultantName;
public String Client;
public String Project;
public String Role;
public String Task;
public String TimeSheetDate;
public String Hours;
public String IsBilled;
public String Workplace;
public String getConsultantName(){
return this.ConsultantName;
}
public String getClient(){
return this.Client;
}
public String getProject(){
return this.Project;
}
public String getRole(){
return this.Role;
}
public String getTask(){
return this.Task;
}
public String getTimeSheetDate(){
return this.TimeSheetDate;
}
public String getHours(){
return this.Hours;
}
public String getIsBilled(){
return this.IsBilled;
}
public String getWorkPlace(){
return this.Workplace;
}
}
my routes is
GET /Application/save controllers.Application.save(EmployeeFilter:String,ClientFilter:String,ProjectFilter:String, EmployeeRoleFilter:String,Task:String,TaskHours:String,TimeSheetDate:String,IsBilled:String,WorkPlace:String,CurrentPage:java.util.List[models.InputTimeSheetDataStore])
can someone help me with the implicit querybinder of type InputTimeSheetDataStore
Thanks in advance
Hi this is the example implementation of QueryStringbindable:
public class InputTimeSheetDataStore implements QueryStringBindable<InputTimeSheetDataStore> {
public String consultantName, client, project;
#Override
public Optional bind(String key, Map data) {
if (data.containsKey("consultantName")) {
this. consultantName = data.get("consultantName").toString();
}
if (data.containsKey("client")) {
this.client = data.get("client").toString();
}
if (data.containsKey("project")) {
this.project = data.get("project").toString();
}
return Optional.of(this);
}
#Override
public String unbind(String key) {
return null;
}
#Override
public String javascriptUnbind() {
return null;
}
}
Extra tips for you, when writing a programming language, make sure you are following the code convention. For example: the convention in Java syntax you must write variable with lower case for the first character;
public String ConsultantName; // this is wrong
public String consultantName; //this is right
Hope it helps.

Polymorphism in XStream serialization and deserialization

I have these classes:
#XStreamAlias("person")
public class PersonConfig {
private AnimalConfig animalConfig;
}
public interface AnimalConfig {}
#XStreamAlias("dog");
public class DogConfig extend AnimalConfig {}
#XStreamAlias("cat");
public class CatConfig extend AnimalConfig {}
And I would like to be able to deserialize this xml with the classes above:
<person>
<dog/>
<person>
As well as deserialize this xml too, with the same classes:
<person>
<cat/>
<person>
So that in both cases, the PersonConfig's field animalConfig is filled. In the first XML with a DogConfig instance and in the second XML with a CatConfig instance.
Is this possible by adding some annotation to make this work?
It seems XStream does not allow you to do it easily.
Your question is similar to this one, asking for managing something like a xsd:choice with XStream.
If you don't necessarily need to use XStream, JAXB will allow you to do it easily :
#XmlRootElement(name="person")
public class PersonConfig {
private AnimalConfig animalConfig;
#XmlElementRefs({
#XmlElementRef(name="cat", type=CatConfig.class),
#XmlElementRef(name="dog", type=DogConfig.class)
})
public AnimalConfig getAnimalConfig() {
return animalConfig;
}
public void setAnimalConfig(AnimalConfig animalConfig) {
this.animalConfig = animalConfig;
}
}
After some researches, listing all available classes for your property can be avoided if you choose to use the XmlAdapter.
In Blaise Doughan link, the example uses an abstract class, not an interface.
Edit :
As Blaise Doughan said in its comment, #XmlElementRef is better suited for this purpose. Code has been updated accordingly.
You can write a converter.
public class CustomConverter implements Converter {
public void marshal(Object source, HierarchicalStreamWriter writer,
MarshallingContext context) {
// TODO: Get annotation value from object 'source' with name of tag via Reflection.
// Or add a method to the AnimalConfig interface giving you tag name to put to serialization output.
}
public Object unmarshal(HierarchicalStreamReader reader,
UnmarshallingContext context) {
// TODO: use reflection to create animal object based on what you xml tag you have at hahd.
return context.convertAnother(context.currentObject(), SomeAnimalClazz.class);
}
public boolean canConvert(Class type) {
return type.equals(AnimalConfig.class);
}
}
There's a disadvantage: polymorphism will require you to use Java Reflection API and performance degradation.
This is quite easy. You just have to do it right and not like my previous speakers. When you process the annotations, XStream can assign those classes.
#XStreamAlias("person")
public class PersonConfig {
private AnimalConfig animalConfig;
public String toXml() {
XStream xstream = new XStream();
xstream.processAnnotations(DogConfig.class);
xstream.processAnnotations(CatConfig.class);
return xstream.toXML(this);
}
}
public interface AnimalConfig {}
#XStreamAlias("dog");
public class DogConfig implements AnimalConfig {}
#XStreamAlias("cat");
public class CatConfig implements AnimalConfig {}
It works out of the box, with out any annotations...
private static interface Test {
String getName();
Params getParams();
}
private static interface Params {
}
private static class OneParams implements Params {
private String oneValue;
public String getOneValue() {
return oneValue;
}
public void setOneValue(String oneValue) {
this.oneValue = oneValue;
}
#Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("OneParams [oneValue=");
builder.append(oneValue);
builder.append("]");
return builder.toString();
}
}
private static class TwoParams implements Params {
private String twoValue;
public String getTwoValue() {
return twoValue;
}
public void setTwoValue(String twoValue) {
this.twoValue = twoValue;
}
#Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("TwoParams [twoValue=");
builder.append(twoValue);
builder.append("]");
return builder.toString();
}
}
private static class OneTest implements Test {
private String name;
private Params params;
#Override
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public Params getParams() {
return params;
}
public void setParams(Params params) {
this.params = params;
}
#Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("OneTest [name=");
builder.append(name);
builder.append(", params=");
builder.append(params);
builder.append("]");
return builder.toString();
}
}
---- now deserialize like this...
System.out
.println(ser
.deserialize("<XStreamTest_-OneTest><name>OneTest</name><params class=\"XStreamTest$OneParams\"><oneValue>1</oneValue></params></XStreamTest_-OneTest>"));
System.out
.println(ser
.deserialize("<XStreamTest_-OneTest><name>TwoTest</name><params class=\"XStreamTest$TwoParams\"><twoValue>2</twoValue></params></XStreamTest_-OneTest>"));

Categories