Imagining that I have some endpoint defined as:
#Path("path/{variable}/{variable}")
class Resource {
#Path("hey")
public void function(#PathParam("variable") final String variable) {
}
}
In the case of calling path/A/B/hey what will be the value bound to variable?
I'm aware I could use UriInfo#getPathParameters() but I'd like to know what's the specified behaviour in this case.
EDIT: this was obviously a simplification of the problem, the real issue here is when I'm trying to have several resources to inherit from a common behaviour.
Example: imagine that I have nested resources for a family tree (son, father, grandfather) and I want to be able to get the children of a given type.
I'd write:
class AbstractFamilyMember {
#Path("children")
public Collection<Stuff> children(#PathParam("name") final String name) {
return (...);
}
}
#Path(URL)
class Grandfather extends AbstractFamilyMember {
public static final String URL = "something/{name}";
}
#Path(URL)
class Father extends AbstractFamilyMember {
public static final String URL = Grandfather.URL + "father/{name}";
}
#Path(URL)
class Son extends AbstractFamilyMember {
public static final String URL = Father.URL + "son/{name}";
}
Do you have any suggestion to re-design this in order that doesn't involve overriding the children method?
You should use different names for your path parameters variable templates, then you can get the path parameters with UriInfo#getPathParameters() in the AbstractFamilyMember#children() method.
I would avoid the constants for the path. They make it hard to read. Keep it simple:
public abstract class AbstractFamilyMember {
#GET
#Path("children")
public Response children(#Context UriInfo uriInfo) {
MultivaluedMap<String, String> pathParameters = uriInfo.getPathParameters();
String grandfatherName = pathParameters.getFirst("grandfatherName");
String fatherName = pathParameters.getFirst("fatherName");
String sonName = pathParameters.getFirst("sonName");
return Response.ok().build();
}
}
#Path("grandfather/{grandfatherName}")
public class Grandfather extends AbstractFamilyMember {
...
}
#Path("grandfather/{grandfatherName}/father/{fatherName}")
public class Father extends AbstractFamilyMember {
...
}
#Path("grandfather/{grandfatherName}/father/{fatherName}/son/{sonName}")
public class Son extends AbstractFamilyMember {
...
}
Depending on your requirements, you could bind the path parameters to fields:
public abstract class AbstractFamilyMember {
#PathParam("grandfatherName")
private String grandfatherName;
#PathParam("fatherName")
private String fatherName;
#PathParam("sonName")
private String sonName;
...
}
Related
I have two classes that extend an abstract class in a very similar manner, and I'd like to abstract out the common parts since I will likely have to use this again. They each return a ThingLink containing data linking them to a Parent object. They also return a Widget that varies based on the class, but only up to their name. Here is the pattern:
public abstract class SomeClass extends TopClass {
protected abstract Widget createWidget();
public void someMethod() { // Does something }
}
public class ThingA extends SomeClass {
private static final String INFO_TYPE = "int";
public ThingLink newLink(Parent master, Int info) {
ThingLink link = new ThingLink(parent, ThingA.class);
link.addData(INFO_TYPE, info);
return link;
}
public Widget createWidget() {
// Stuff to get someData
return ThingAWidget.createMe(someData);
}
}
public class ThingB extends SomeClass {
private static final String INFO_TYPE = "String";
public ThingLink newLink(Parent master, String info) {
ThingLink link = new ThingLink(parent, ThingB.class);
link.addData(INFO_TYPE, info);
return link;
}
public Widget createWidget() {
// Stuff to get someData
return ThingBWidget.createMe(someData);
}
}
I have no access to TopClass, the ThingLink class, or the Widget class. I was trying to abstract out the common parts using generics, but I can't seem to figure out if that will provide a complete solution. My big problem is figuring out how to get the pieces that are self-referential. I would like a class something like:
public abstract class Thing<T> extends SomeClass {
private String infoType;
public void setInfoType(String type) { infoType = type; }
public ThingLink newLink(Parent master, T info {
ThingLink link = new ThingLink(parent, ???????????);
link.addData(infoType, info);
return link;
}
public Widget createWidget() {
// Stuff to get someData
return ??????????????.createMe(someData);
}
}
Keep in mind that I am fairly new to Java, and self-taught, but I am trying very hard to make some bigger leaps and really understand how to write good code. I appreciate your help.
I have two Java classes TeradataTable and RdbmsTable-
Useful part of RdbmsTable.java
public class RdbmsTable {
public RdbmsTable(String uri, String type) {
this.uri = uri;
this.type = type;
}
Useful part of TeradataTable.java
public class TeradataTable extends RdbmsTable {
public TeradataTable(String uri) {
super(uri, "TERADATATABLE");
}
I need to set className in upper case in super() constructor. I don't want to use hardcoded string.
I can't use this.getClass().getSimpleName().toUpperCase(); in super().
Is there something wring design wise?
If you need that name in the RdbmsTable constructor, use this.getClass().getSimpleName().toUpperCase() there (rather than super):
public RdbmsTable(String uri) {
this.uri = uri;
this.type = this.getClass().getSimpleName().toUpperCase();
}
getClass always gives you the instance's actual class, regardless of where you call it from. So in RdbmsTable above, this.getClass() will return the Class instance for whatever class the instance actually is. If it's a TeradataTable instance, this.getClass() will return a reference to the Class for TeradataTable (not RdbmsTable).
Live Example:
class Example
{
public static void main (String[] args) throws java.lang.Exception
{
new TeradataTable("foo");
}
}
class RdbmsTable {
public RdbmsTable(String uri) {
System.out.println(this.getClass().getSimpleName().toUpperCase());
}
}
class TeradataTable extends RdbmsTable {
public TeradataTable(String uri) {
super(uri);
}
}
Output:
TERADATATABLE
But I'd think it would be better to use an annotation or some such to parameterize this, in case you need to use a name that isn't an exact match for the class name at some point.
Would that work for you?
public class TeradataTable extends RdbmsTable {
public TeradataTable(String uri) {
super(uri, TeradataTable.class.getSimpleName().toUpperCase());
}
it does not need 'this'
it is just the static version of your approach
it still updates if you refactor your class names
you can keep the other code as is
I'm trying to write more generic class for below code so the type and static variables that define in EvenTypes can be changed by the end developer and give them options to add or remove static variables in EventType.
I'm also think of having generic enum for event type as below.
public interface EventType<T extends Enum<T>>
{
String name();
String getFriendlyName();
Class<T> getDeclaringClass();
T getRaw();
public String getFullClassName();
}
Original Code
public class Event implements Serializable
{
private String eventId;
private String eventType;
.....
}
public class EventTypes
{// below static variables can be changed by the developer based on requirements
public static final String DO_FILE_CONVERSION = "100";
public static final String DO_REMOVE_FILE = "101";
public static final String DO_COPY_FILE = "102";
.....
}
public class EventProcessorFactory
{
#SuppressWarnings("rawtypes")
public IEventProcessor createProcessor(EventType eventType)
throws EventException
{
String eventProcessorClassName = (getEvenClassName based on type from properties files);
Class eventProcessorClazz = Class.forName(eventProcessorClassName);
return (IEventProcessor) eventProcessorClazz.newInstance();
}
}
properties.file
----
100=FileConversion.class
101=FileRemove.class
102= FileCopy.class
Make Event an interface and extend it from Serializable.
Then use an enum to implement that Event interface. Example:
public interface Event extends Serializable {
// Throw in your methods here
}
public enum MyEvents implements Event {
DO_FILE_CONVERSION, DO_REMOVE_FILE, DO_COPY_FILE;
// Implement methods
}
This way you have your interface (namely whatever you want Event capable of doing) seperated from the implementation (which Events exist and the implementation of them).
I have two classes that inherit from another class
class AEntity {
private String name;
public AEntity(String name){this.name = name;}
}
class Course extends AEntity {
private String code;
public Course(String name, String code){
super(name);
this.code = code;
}
}
class Classroom extends AEntity {
private String code;
public Classroom(String name, String code){
super(name);
this.code = code;
}
}
Now, there is a "middle" class that I want to take notice of the type of AEntity has been created. Different classes can create different types of AEntity.
class AEntityDefinition {
private AEntity entity;
public void setEntity(AEntity ae){this.entity = ae;}
public AEntity getEntity(){return this.entity;}
}
Now, I have a class that creates an instance of AEntity class and therefore I use AEntityDefinition class.
class C1 {
private AEntityDefinition aEntityDefinition;
public C1(){
aEntityDefinition = new AEntityDefinition();
aEntityDefinition.setEntity(new Course("Course","Course code"));
}
}
Finally, I want to call getEntity() in order to see the type of AEntity that has been created.
public class EntityDefinition {
public static void main(String[] dgf){
AEntityDefinition aEntityDefinition = new AEntityDefinition();
System.out.println(aEntityDefinition.getEntity() instanceof Course);
System.out.println(aEntityDefinition.getEntity());
}
}
Running the project returns null, because entity variable is not known outside class. My question is: How am I going to get the type of AEntity inside main, without passing from C1? Is there any way to do that, or there is another approach? Thank you in advance.
Context:
I have some client code that creates and stores an AEntity within an AEntityDefinition that is a field inside another (unspecified) class. I would like to be able to solve this without changing the code for the client class too much, or preferably not at all, because there are numerous classes that could be containers.
You could provide a getter:
class C1 {
private AEntityDefinition aEntityDefinition;
public C1(){
aEntityDefinition = new AEntityDefinition();
aEntityDefinition.setEntity(new Course("Course","Course code"));
}
public Class<? extends AEntity> getEntityType() {
return aEntityDefinition.getEntity().getClass();
}
}
You may want to put some null checking in there in case the entity definition or the entity can be null.
If you can't change class C1, but you know that it has an AEntityDefinition field and you want to get a reference to the AEntity instance inside it, use can use reflection:
public static Class<? extends AEntity> getEntityType(Object o) throws Exception {
for (Field field : o.getClass().getDeclaredFields()) {
if (AEntityDefinition.class.isAssignableFrom(field.getType())) {
AEntityDefinition def = (AEntityDefinition) field.get(o);
return def.getEntity().getClass();
}
}
return null;
}
Have you tried a simple getClass call?
AEntity ae = aEntityDefinition.getEntity();
String klass = ae != null ? ae.getClass().getName() : "*not defined*";
System.out.println("The class type is " + klass);
I have a lot of subclasses of an abstract class and each of them declare a public static final field with the same name. I was thinking of having this field in the abstract superclass without initializing it and hoping that each subclass would be forced to initialize it.
I was thinking of this because all of my subclasses of the abstract class declare a public static final String field called UNIQUE_ID, and it is necessary for every subclass to declare such a field with exactly that name.
I hope my question is clear enough, if not please tell me so.
Can something more or less equivalent to this be done?
EDIT: Code added:
My abstract class looks like:
public abstract class ExperimentPanelModel extends Panelizable {
protected String nextButtonText;
protected String backButtonText;
protected String skipButtonText;
protected Properties currentFile;
protected List<Properties> pastFiles = new ArrayList<Properties>();
public ExperimentPanelModel(Properties argcurrentfile, List<Properties> argpastfiles) {
currentFile = argcurrentfile;
pastFiles = argpastfiles;
nextButtonText = "Next";
backButtonText = "Back";
skipButtonText = "Skip";
}
...
}
Some of the non-abstract subclasses of that abstract class look like (note that all of them declare public static final String UNIQUE_ID) :
public class ConfigurationGUI extends ExperimentPanelModel {
public static final String UNIQUE_ID = "ConfigurationGUI";
public static final String DATA_MODIFIED = "DataModified";
Date dateOfLastSession;
int ExperimentalSession;
int ExperimentOrder;
boolean nextButtonEnabled = false;
public ConfigurationGUI(Properties argcurrentfile, List<Properties> argpastfiles) {
super(argcurrentfile, argpastfiles);
nextButtonText = "Confirm";
backButtonText = "Abort";
}
...
}
One example more:
public class Introduction extends ExperimentPanelModel {
public static final String UNIQUE_ID = "Introduction";
public static final String INSTRUCTIONS_XML_FILE = "instructions.xml";
public static final String THIS_INSTRUCTION_PROPERTY = UNIQUE_ID;
private String thisInstructionText = UNIQUE_ID;
Properties readInstructionsProperties = new Properties();
public Introduction(Properties argcurrentfile, List<Properties> argpastfiles) {
...
And the last one:
public class Instruction1 extends ExperimentPanelModel {
public static final String UNIQUE_ID = "Instruction1";
public static final String INSTRUCTIONS_XML_FILE = "instructions.xml";
public static final String THIS_INSTRUCTION_PROPERTY = UNIQUE_ID;
...
}
The field idea won't work, because static fields can't be overridden in subclasses. What you can do is you can declare an abstract method on the abstract class so that your subclasses must implement it.
Also note you can't make it a static method because those don't get overridden either.
In your case I would define the variable in the ancestor. No point in having a variable in each of the extending classes, unless you have a particularly good reason, which you don't sound like having.
+1 for Nathan's reply though. In quite a few cases, that's a better thing to do.
Put the public final field UNIQUE-ID in the abstract class and declare a protected constructor which takes the value for UNIQUE-ID. You'll not be able to make it static though as the values are required to be different for different instances.