Creating Constants For Use In Annotation Fields - java

I'm incorporating cache in an existing spring project using Spring annotations. I have created this class for storing cache configuration -
public class CacheParams {
public final String name;
public final int lifeTime;
public final TimeUnit lifeTimeUnit;
public final String key;
public CacheParams(args here) {/*implementation here*/}
}
and this is how I intend to use it -
class FooDaoCache extends FooDaoImpl {
private static final CacheParam USER_BY_ID_CACHE = new CacheParams(values here);
#Override
#Cacheable(cacheNames = USER_BY_ID_CACHE.name, key = USER_BY_ID_CACHE.key)
public User getUser(int userId) {
implementation here
}
}
But this does not work as USER_BY_ID_CACHE will be created on compile time. If I simply create a string constant containing cache name I can successfully use it -
class FooDaoCache extends FooDaoImpl {
private static final String CACHE_NAME = "baz";
#Override
#Cacheable(cacheNames = CACHE_NAME)
public User getUser(int userId) {
//implementation here
}
}
Is there any way to deal with this or an alternate design? I need the class CacheParams because I have to perform other operations using cache name, lifetime etc in other parts of code too.

CacheParam needs to be an enum or the name field needs to be a static final String.
Annotation return types may only be primitive types, enums, Strings, classes and arrays of these.

Related

Java - conditional access to methods of a class

I am having to java classes track and Session.
The track class...
package trackmanagement;
public class track {
private String trackName, networkingEventTime;
private Session morningSession, afternoonSession;
track(String name)
{
trackName = name;
}
public void alloteSession()
{
morningSession = new Session("Morning Session", trackName);
afternoonSession = new Session("Afternoon Session", trackName);
}
}
The Session class...
package trackmanagement;
import java.util.ArrayList;
public class Session {
private String sessionName, relatedTrack, startTime, endTime;
private ArrayList<Slot> allotedSlots;
public Session(String name, String track)
{
sessionName = name;
relatedTrack = track;
}
public void morningSlots()
{
}
public String afternoonSlots()
{
return "";
}
}
In the method alloteSession in class track, I am making two objects of class Session with names morningsession and afternoonsession.
The class Session contains two methods namely morningSlots and afternoonSlots.
I want only morningSlots method to be accessed from morningsession object while afternoonSlots is private for morningsession object.
Similarly, afternoonSlots method should be accessed from afternoonsession object while morningSlots is private for afternoonsession object.
Thus there should be a conditional privacy for the methods. The method morningSlots should be public for morningsession object while it should be private for afternoonsession object and vice-versa.
Is it possible to do this, if not please suggest some other way to implement this kind of design.
Instead of trying to change the method visibility from one class or another, you could create 2 classes morningSession & afternoonSession which would extend session.
session could be an abstract class with the method slots() which would need to be implemented in morningSession & afternoonSession.
From the implementation point of view when you create sessions it is either morningSession or afternoonSession but in both case you can call the slots() method which will invoke the correct method
You should change your design instead of trying something that's not possible in Java :)
public abstract class Session {
public abstract String getSlots();{//try to have methods that describes a verb/action
}
public class MorningSession extends Session{
public abstract String getSlots(){
return "Morning slot received";
}
}
public class AfternoonSession extends Session{
public abstract String getSlots(){
return "Afternoon slot received";
}
}
By doing this, you wrap the implementation and let your Child Classes Morning/AfternoonSession to get the required slots.

generic class for static variables

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).

Not possible to create List of inner class with jackson

Is it not possible to create a list with an inner class with Jackson? The external class Tradables will work perfectly. But the inner class Underlyings will not work (Same of course if I make Tradables an inner class).
Is there a way to solve this without making every class that belong to an array of json objects be in it's own class?
Also it does not matter if the JsonProperty is above the set method. Any inner class that is not part of an array will also work.
private String sector_group;
#JsonProperty("underlyings")
private List<Underlyings> listUnderlyings;
#JsonProperty("tradables")
private List<Tradables> listTradables;
public class Underlyings {
private long instrument_id;
private String symbol;
private String isin_code;
public long getInstrument_id() {
return instrument_id;
}
public void setInstrument_id(long instrument_id) {
this.instrument_id = instrument_id;
}
public String getSymbol() {
return symbol;
}
public void setSymbol(String symbol) {
this.symbol = symbol;
}
public String getIsin_code() {
return isin_code;
}
public void setIsin_code(String isin_code) {
this.isin_code = isin_code;
}
}
Mapping method
ObjectMapper mapper = new ObjectMapper();
try {
String json = RestLogin.getBaseResource()
.path("instruments").path("lookup").path("market_id_identifier").path(market_id + ":" + identifier)
.request(RestLogin.getResponsetype()).get(String.class);
List<Instrument> tmpInstruments = mapper.readValue(json, mapper.getTypeFactory().constructCollectionType(List.class, Instrument.class));
Jackson and Inner Classes: yes, you can use, but they must be STATIC inner classes
Here's a snippet (but you should read the entire article for more explanation).
If you do not add static, resulting class is generally useless for Jackson as well as any other data binding framework (Hibernate, JAXB); can often be serialized, but never serialized into

better modeling design java

I have to supply a class by another with regulatory management.
I suppose these two classes:
Class A:
public class A {
private String attributeA1;
...
private String attributeA50;
...
// getters and setters
}
Class B:
public class B {
private String attributeB1;
...
private String attributeB50;
...
// getters and setters
}
Each attribute from Class A will supply attribute from B.
Exemple:
public Class Supplying {
public B elementB;
public A elementA;
public void supplyAttributeB1( String toto){
String tata = elementA.getattributeA1();
// Example of regulatory management "Substring"
elementB.setAttributeB1(tata.substring(5));
}
public void supplyAttributeB2(String toto){
...
}
...
public void supplyAttributeB50(String toto){
...
}
}
When I see my code, it's not very pretty, I think I have a modeling problem because the class supplying will have over 150 lines of code.
Is there another way to make this concept by using interface or inheritance or a design pattern? I'm trying to learn how to code better.
If your operations fall into some broad categories, you can use the Strategy pattern:
public interface DataConverter<F,T> {
public T convert( F from );
}
public class SubstringConverter implements DataConverter<String,String> {
private final int start;
public SubstringConverter( int start ) { this.start = start; }
public String convert( String from ) {
return from.substring( start );
}
}
And in your supplying class
public class Supplying {
private static final DataConverter<String,String> b1Converter = new SubstringConverter( 5 );
// and so on ...
public void supplyAttributeB1() {
elementB.setAttributeB1( b1Converter.convert( elementA.getAttributeA1() ) );
}
}
This will make it easy to change the logic (so long as field Ax always converts into field Bx, all you need is plug in a new converter), and easy to see what's going on.
This is about as far as you can go without building a full-size data conversion framework, where you'll probably use reflection to access the fields and have external config files to drive the mapping between entities.

Determine which subclass to choose by accessing static variables from the Class object

I am trying to implement an interface in Java to use different types of databases for one application.
My though was to create an abstract class with the common interface and two static variables which are then overwritten by the subclasses. I then wanted to add a Class[] List with the classes of all available subclasses to the abstract class as well as a couple of functions that allow the determination of the correct class to be used.
The goal is to first get a list of all available database types and let the user choose one. Afterwards another function should translate the name (which could be localized) to the IDENTIFIER which is specified in the subclass. Finally a third function allows the instantiation of an object by giving such an IDENTIFIER.
My abstract class would look something like this:
public abstract class DataBase {
public static final IDENTIFIER = "";
public static final NAME = "";
private static final Class[] dbTypes = new Class[]{PostgreSQL.class, MySQL.class};
public static String[] getNameList() {
String[] names = new String[dbTypes.length];
for(int i = 0; i < dbTypes.length; i++){
names[i] = dbTypes[i].NAME; //Cannot access the static variable this way.
}
return names;
}
public static String getIdentifierForName(String name) {
for(int i = 0; i < dbTypes.length; i++){
if(name.equals(dbTypes[i].NAME){
return dbTypes[i].IDENTIFIER;
}
}
return "";
}
public static DataBase getInstanceOf(String identifier) {
for(int i = 0; i < dbTypes.length; i++){
if(identifier.equals(dbTypes[i].IDENTIFIER) {
return dbTypes[i].newInstance();
}
}
return null;
}
}
The Child classes would look something like this:
public class MySQL extends DataBase {
public static final IDENTIFIER = "ab.cde.MySQL";
public static final NAME = "MySQL";
...
}
public class PostgreSQL extends DataBase{
public static final IDENTIFIER = "ab.cde.PostgreSQL";
public static final NAME = "PostgreSQL";
...
}
My problem now is, that I cannot access the static variables from the Class object. Obviously the dbTypes list does not contain any typed classes. I tried changing the type of the Array to Class<? extends DataBase>, but I get an error Cannot create a generic array of Class<? extends DataBase> I also tried checking the classes with isAssignableFrom() and then casting the class, but I was still not able to access the static variables.
For now I have two solutions which are working:
Hardcode all existing subclasses into each function if(PostgreSQL.NAME.equals(name)){...}etc.
However, if I add new subclasses, I only want to have to add them at one point in my implementation.
Instead of using a Class[] array, I can use an array of DataBase[] with instances of each class. However, I would think this is bad practice to instantiate each available DataBase subclass, even though I only need one in the end.
Since I have never done such a thing before I might also be approaching the problem completely wrong. Maybe I am missing the correct way in which something like this is usually done?
Thank you for your help.
There are no "abstract properties" in Java. You have to create two astract methods in the DataBase class, like this:
public abstract class DataBase {
// No "abstract propeties"
public abstract String getDBName();
public abstract String getDBIdentifier();
// etc etc...
}
and then, in each subclass:
public class MySQL extends DataBase {
public static final IDENTIFIER = "ab.cde.MySQL";
public static final NAME = "MySQL";
#Override
public String getDBName() {
return NAME;
}
#Override
public String getDBIdentifier() {
return IDENTIFIER;
}
// etc etc...
}
When using the classes, you can just cast to DataBase (not MySQL or PostgreSQL) and call the two abstract methods.
Therefore, in order to solve your "pick a database class" problem, I would create a configuration file that contains the names of the databases and the corresponding class, and instantiate it with reflection (newInstance()) as needed.
As an alternative, you can use reflection to access the static variables like Nikita's answers suggested, or you can just use the name of the class as the identifier of the database it supports, like this (not tested):
public abstract class DataBase {
private static final Class[] dbTypes = new Class[]{PostgreSQL.class, MySQL.class};
public static Class getDBClass(String type) {
for (Class c : dbTypes) {
if (c.getSimpleName().toLowerCase().equals(type.toLowerCase())) {
return c;
}
}
return null;
}
public static Set<String> getSupportedDB() { // <-- you populate a dropdown menu with this
Set<String> supported = new HashSet<String>();
for (Class c : dbTypes) {
supported.add(c.getSimpleName());
}
return supported;
}
// etc etc...
}
However, I don't like this solution and I would not use it.
You can use reflection to get values for each class:
public static String[] getNameList(){
String[] names = new String[dbTypes.length];
for(int i=0; i<dbTypes.length; i++){
Field f = dbTypes[i].getField("NAME");
names[i] = f.get(null);
}
return names;
}
But it might be slow.
Also I'd suggest to create separate enum DBRegistry that will contain names, identifiers and classes:
public enum DBRegistry {
MYSQL("ab.cde.MySQL", "MySQL", MySQL.class),
POSTGRESQL("ab.cde.PostgreSQL", "PostgreSQL", PostgreSQL.class);
private String name;
private String identifier;
private Class<?> dbClass;
private DBRegistry(String identifier, String name, Class<?> dbClass) {
this.identifier = identifier;
this.name = name;
this.dbClass = dbClass;
}
// Getters...
}
You can iterate on all items in registry using DBRegistry.values
Not tested, but I would suggest something like this. You could register databases by calling DataBase.registerDataBase(new DataBase(...))); which may be invoked from the main file.
public class DataBase {
private final static List<DataBase> INSTANCES = new ArrayList<DataBase>();
private final String identifier;
private final String name;
private final Class<?> dbType;
public DataBase(String identifier, String name, Class<?> dbType) {
this.identifier=identifier.toString();
this.name=name.toString();
this.dbType=dbType;
}
String getIdentifier() {return identifier;}
String getName() {return identifier;}
Class<?> getDbType() {return dbtype;}
public synchronized static void registerDatabase(DataBase database) {
database.getClass();
INSTANCES.add(database);
//may check if already registered and either fail or replace it
}
public synchronized static List<DataBase> getNameList() {
return new ArrayList<DataBase>(INSTANCES);
}
public synchronized static List<String> getNameList() {
List<String> names = new ArrayList<String>(INSTANCES.size());
for (Database db:INSTANCES) names.add(db.getName());
return names;
}
public synchronized static String getIdentifierForName(String name) {
for(DataBase db:INSTANCES){
if(name.equals(db.getName())) return db;
}
return null;
}
public synchronized static DataBase getInstanceOf(String identifier) {
for(DataBase db:INSTANCES){
if(identifier.equals(db.getIdentifier())) return db;
}
return null;
}
}
}
I would advise to keep it simple, never more than necessary to utilize in the actual application. It is easier to extend things than to re-factor code to accomodate for additional complexity. Most of the stuff you mention are merely artefacts of your problem solving, not the actual requirements of your application per se. And it so happens, that a modern object-oriented language has everything you need, and you can implement a good design without reflection and without resorting to static properties and string identifiers.
Remember to rely on the compiler rather than runtime for whatever you know in advance - anything that is known not to change from one application run to another, does not need reflection, because it does not involve runtime variables! I would go for interfaces, classes implementing them, and more importantly the Factory pattern to abstract using these classes:
interface Database
{
void query(String sqlString);
}
class MySQLDatabase implements Database
{
public void query(String sqlString)
{
}
}
class PostgreSQLDatabase implements Database
{
public void query(String sqlString)
{
}
}
class DatabaseFactory
{
Database connectDatabase()
{
/// F.e. return new MySQLDatabase();
}
}
The whole "database abstraction layer" has been done to death already anyway, giving birth to DBA, ODBC and other software stacks that solve your problem. You should let yourself be inspired by these, unless you are sure your particular way of solving this yields advantages that can be proven. If you want to go about this in a professional way, of course. If you want to educate yourself, by all means, use reflection, strings in place of more specific objects, and tight-coupling instead of aggressive modularity.

Categories