What I have done currently is
Created an abstract class
public interface AbstractRawPathStrategy {
String getRouteKey();
void processRequest();
}
Implemented the classes
public class GetDocumentImpl implements AbstractRawPathStrategy {
#Override
public String getRouteKey() {
return "GET_DOCUMENT";
}
#Override
public void processRequest() {
log.info("Inside get document");
}
}
Created a routing factory
public class RawPathStrategyFactory {
private final Map<String, AbstractRawPathStrategy> dictionary;
#Inject
public RawPathStrategyFactory(final Set<AbstractRawPathStrategy> abstractRawPathStrategySet) {
dictionary = new HashMap<>();
for (AbstractRawPathStrategy abstractRawPathStrategy : abstractRawPathStrategySet) {
dictionary.put(abstractRawPathStrategy.getRouteKey(), abstractRawPathStrategy);
}
}
public AbstractRawPathStrategy getByRouteKey(final String rawPath) {
return dictionary.get(rawPath);
}
}
Instantiated the factory
#Module
public class AppModule {
#Provides
#Singleton
public RawPathStrategyFactory getRouteKeyStrategyFactory() {
Set<AbstractRawPathStrategy> abstractRouteKeyStrategies = new HashSet<>();
abstractRouteKeyStrategies.add(new GetDocumentImpl());
abstractRouteKeyStrategies.add(new GetUserRightsImpl());
return new RawPathStrategyFactory(abstractRouteKeyStrategies);
}
What I want is to go to respective class based on the route key (String). How can this be done without instantiating each class with new in AppModule. Any cleaner way to do this?
Try to use multibindings when create RawPathStrategyFactory
https://dagger.dev/dev-guide/multibindings.html
The easy, boring, way would be to use some static identifier which you'll have to set for each distinct subtype of your abstract class, and subsequent subtype thereof.
The more complicated, albeit fun, way to do this would be to use reflection.
Related
I have a Spring Boot web application that is working correctly. I noticed that two #Repository beans had a lot in common, so I refactored them using an abstract super class and now my application is broken. I've double-checked and this is the only change that I've made between the working and non-working states. Can anyone see what I've done wrong?
Here's my working code:
public class One { ... }
public class Two { ... }
#Repository
public class RepoOne {
private final ISource<One> sourceOne;
private ICache<One> cache;
#Value("${com.example.lifetime.one}")
private int lifetime;
public RepoOne(ISource<One> sourceOne) {
this.sourceOne = sourceOne;
}
#PostConstruct
public void createCache() {
Duration lifetime = Duration.ofMinutes(this.lifetime);
this.cache = new Cache<>(lifetime, sourceOne);
}
public One get(String key) {
return cache.get(key);
}
}
#Repository
public class RepoTwo {
private final ISource<Two> sourceTwo;
private ICache<Two> cache;
#Value("${com.example.lifetime.two}")
private int lifetime;
public RepoOne(ISource<Two> sourceTwo) {
this.sourceTwo = sourceTwo;
}
#PostConstruct
public void createCache() {
Duration lifetime = Duration.ofMinutes(this.lifetime);
this.cache = new Cache<>(lifetime, sourceTwo);
}
public Two get(String key) {
return cache.get(key);
}
}
#Service
public class RepoService {
private final RepoOne repoOne;
private final RepoTwo repoTwo;
public RepoService(RepoOne repoOne, RepoTwo repoTwo) {
this.repoOne = repoOne;
this.repoTwo = repoTwo;
}
public void doSomething(String key) {
One one = repoOne.get(key);
...
}
}
Here's my re-factored code where I introduced an abstract, generic super-class.
abstract class AbstractRepo<T> {
private final ISource<T> source;
private ICache<T> cache;
AbstractRepo (ISource<T> source) {
this.source = source;
}
#PostConstruct
private void createCache() {
Duration lifetime = Duration.ofMinutes(lifetime());
this.cache = new Cache<>(lifetime, source);
}
protected abstract int lifetime();
public final T get(String key) {
return cache.get(key);
}
}
#Repository
public class RepoOne extends AbstractRepo<One> {
#Value("${com.example.lifetime.one}")
private int lifetime;
public RepoOne(ISource<One> sourceOne) {
super(source);
}
protected int lifetime() { return lifetime; }
}
#Repository
public class RepoTwo extends AbstractRepo<Two> {
#Value("${com.example.lifetime.two}")
private int lifetime;
public RepoTwo(ISource<Two> sourceTwo) {
super(source);
}
protected int lifetime() { return lifetime; }
}
When using the re-factored code I get a NullPointerException in AbstractRepo::get(). I've confirmed via the debugger that cache is null (along with source). However, I also confirmed via the debugger that instances of RepoOne and RepoTwo are created and their createCache() method called. It's as if two instances of each are being created and only the one is initialised. Any thoughts?
It isn't the fact that you introduced a parent class but the fact that you turned the get method into a final method.
A class annotated with #Repository will get automatic exception translation. This automatic exception translation is added through the use of AOP. The default mechanism to apply AOP in Spring is to use proxies and in this case a class based proxy.
What happens is that CgLib creates a proxy for your classes by subclassing it, so that when a method is called an advice can be added. However a final method cannot be overridden in a subclass. Which will lead to the get method being called on the proxy instead of the actual instance.
There are 2 ways of fixing this
Remove the final keyword
Introduce an interface defining the contract for your repositories. This will lead to a JDK Dynamic proxy being created. JDK Dynamic Proxies are interface based and don't need to subclass your actual class (that is only for class based proxies).
I'm trying to use SPQR to generate GraphQL schema from a Cayenne generated class.
Cayenne class looks like this
public class MyCayenneClass {
public static final Property<Integer> A_PROPERTY = Property.create("aProperty", Integer.class);
public static final Property<Integer> ANOTHER_PROPERTY = Property.create("anotherProperty", String.class);
public void setAProperty(Integer aProperty) {
writeProperty("aProperty", aProperty);
}
public Integer getAProperty() {
return (Integer)readProperty("aProperty");
}
public void setAnotherProperty(String anotherProperty) {
writeProperty("anotherProperty", anotherProperty);
}
public String getAnotherProperty() {
return (String)readProperty("anotherProperty");
}
}
As the class isn't a simple POJO, SPQR throws an exception and the schema isn't generated.
Error: QUERY_ROOT fields must be an object with field names as keys or a function which returns such an object.
What's the best approach here (without modifying the cayenne class (i.e. annotating a method)?
GraphQLEndPoing.java
#WebServlet(urlPatterns = "/graphql")
public class GraphQLEndpoint extends SimpleGraphQLServlet {
public GraphQLEndpoint() {
super(buildSchema());
}
//This method used SPQR
private static GraphQLSchema buildSchema() {
GraphQLSchema schemaGenerator = new GraphQLSchemaGenerator()
.withOperationsFromSingletons(myRepository) //register the beans
.generate();
return schemaGenerator;
}
private static final MyRepository myRepository;
static {
myRepository= new MyRepository ();
}
}
MyRepository.java
public class MyRepository{
private MyLibService libService;
#GraphQLQuery
public MyCayenneClass find(Integer id) {
List<MyCayenneClass> myList= libService.fetchById(new Integer[] {id});
return myList.get(0);
}
}
*FYI. If I declare the schema. Code will work just fine
schema {
query: Query
}
type Query {
find(id: Int): MyCayenneClass
}
type ConcContract {
id: ID
aProperty: Int
anotherProperty: String
}
From SPQR's perspective, this isn't really different from a POJO, as SPQR cares only about the types.
By default, for all nested classes (MyCayenneClass in your case), everything that looks like a getter will be exposed. For top-level classes (MyRepository in your case), only annotated methods are exposed by default. And at least one top-level method must be exposed, otherwise you have an invalid schema.
The error, as it stands, just means not a single top-level query was discovered. I see the #GraphQLQuery annotation is commented out. Is that intentional? With the default config, this would not expose any query.
You can register a different ResolverBuilder, e.g. PublicResolverBuilder (or your own implementation/extension) if you want to expose un-annotated methods.
E.g.
generator.withOperationsFromSingleton(new MyRepository(), new PublicResolverBuilder())
This would expose all public methods from that class.
Here's a slightly simplified example I tried with v0.9.6 and seems to work as expected (I know you're using a rather old version from the error text).
public class MyRepository {
#GraphQLQuery //not commented out
public MyCayenneClass find(Integer in) {
return new MyCayenneClass();
}
}
// extends CayenneDataObject because I don't know where to get the
// writeProperty and readProperty from
// but shouldn't change anything from SPQR's perspective
public class MyCayenneClass extends CayenneDataObject {
public static final Property<Integer> A_PROPERTY = Property.create("aProperty", Integer.class);
public static final Property<String> ANOTHER_PROPERTY = Property.create("anotherProperty", String.class);
public void setAProperty(Integer aProperty) {
writeProperty("aProperty", aProperty);
}
public Integer getAProperty() {
return (Integer)readProperty("aProperty");
}
public void setAnotherProperty(String anotherProperty) {
writeProperty("anotherProperty", anotherProperty);
}
public String getAnotherProperty() {
return (String)readProperty("anotherProperty");
}
}
There's many more customizations you can apply, depending on what you end up needing, but from the question as it stands, it doesn't seem you need anything extra...
To override the ResolverBuilder used for nested classes, you have 2 options.
1) Register it globally, so all nested types use it:
generator.withNestedResolverBuilders(customBuilder)
2) Or per type:
.withNestedResolverBuildersForType(MyCayenneClass.class, new BeanResolverBuilder())
But this is very rarely needed...
In my Android application I have a class which gives me static string values; something like this:
public class VehicleInfo {
public static String getVehicleEnginePower(boolean isNew) {
return isNew ? "1800CC" : "1600CC";
}
}
Now I have another category, so I will have to pass another Boolean, and I will get the value I need. However, these categories will keep on increasing. So I looked into the Open/Closed principle which looks promising for quick enhancement. To ensure this I will make the VehicleInfo class as an Interface and then I will have other classes implement VehicleInfo.
public interface VehicleInfo {
String getVehicleEnginePower();
}
public class NewVehicle implements VehicleInfo {
#Override
public String getVehicleEnginePower() {
return "1800CC";
}
}
and the other category classes will also be something like this. In this way I will have to add another class for all the new categories.
The question I wanted to ask is: is there a way that I can have single instance of this interface? Because in the whole application flow, a user will only be able to see one category until he switches to another category.
I don't want to instantiate these classes at multiple points. To clarify my question, I want to do something like this at the start of my application:
if (isNew) {
VehicleInfo vehicleInfor = new NewVehicle();
}
And in the whole application, whenever I call VehicleInfo.getVehicleEnginePower, it should always return engine power from the NewVehicle class.
Is something like this possible? Or am I just being silly and I will have to instantiate this interface on multiple points?
Maybe you need a singleton here
public class VehicleInfoManager {
private static VehicleInfoManager INSTANCE = new VehicleInfoManager();
private VehicleInfo currentVehicleInfo;
public static VehicleInfoManager getInstance() {
return INSTANCE;
}
public void setCurrentVehicleInfo(VehicleInfo info) {
this.currentVehicleInfo = info;
}
public String getVehicleEnginePower() {
return this.currentVehicleInfo.getVehicleEnginePower();
}
private VehicleInfoManager() {
// Constructor private by default
}
}
Then you can call it from everywhere like this
VehicleInfoManager.getInstance().getVehicleEnginePower()
//Or set current info like this
VehicleInfoManager.getInstance().setCurrentVehicleInfo(new NewVehicle())
Just be careful as currentVehicleInfo is null by default so you need to handle null pointer cases.
If I understand your question correctly.
My solution to this would be Enum
public enum VehicleEnginePower {
NEW ("1800CC"),
OLD ("1600CC"),
private final String name;
private Modes(String s) {
name = s;
}
public String toString() {
return this.name;
}
}
Then you can do
if (isNew) {
String powerOfEngine = VehicleEnginePower.NEW.toString();
}
Let's say I have a Strategy interface :
public interface Strategy {
void perform();
}
And a template method to implement it :
public abstract class AbstractStrategy implements Strategy {
#Override
public void perform() {
String firstInfo = doStuff();
String secondInfo = firstDelegationToImplementor(firstInfo);
String thirdInfo = processSecondInfo(secondInfo);
String fourthInfo = secondDelegationToImplementor(thirdInfo);
finalProcessing(fourthInfo);
}
private void finalProcessing(String fourthInfo) {
//TODO automatically generated method body, provide implementation.
}
protected abstract String secondDelegationToImplementor(String thirdInfo);
protected abstract String firstDelegationToImplementor(String firstInfo);
private String processSecondInfo(String secondInfo) {
return "thirdResult";
}
private String doStuff() {
return "firstResult";
}
}
And I have a concrete subclass of that :
public class ConcreteStrategy extends AbstractStrategy {
private String firstInfo;
#Override
protected String secondDelegationToImplementor(String thirdInfo) {
return someMoreProcessing(firstInfo, thirdInfo);
}
private String someMoreProcessing(String firstInfo, String thirdInfo) {
return null;
}
private String someProcessing(String firstInfo) {
return null;
}
#Override
protected String firstDelegationToImplementor(String firstInfo) {
this.firstInfo = firstInfo;
return someProcessing(firstInfo);
}
}
But due to the fact that it needs to remember some intermediate result in between the method calls it is not stateless. Stateless classes have several advantages, they are automatically thread safe for instance.
So the question is : how can I make ConcreteStrategy stateless, while taking advantage of the template method?
(edit) Clarification : the published methods of both the interface and the template method class cannot change.
(note, I have solved this question already and will answer it myself, but I'll give others a chance to solve it)
Ok here's the answer I have come up with when I faced this :
public class StatelessConcreteStrategy implements Strategy {
#Override
public void perform() {
new ConcreteStrategy().perform();
}
}
StatelessConcreteStrategy is stateless. It has all the benefits any other stateless class has, and by delegating the perform() to a new ConcreteStrategy instance, it gets to use the template method pattern, and is able to 'remember' any data it wants to in between method calls.
In fact you'll most likely want to inline ConcreteStrategy to an inner or even anonymous inner class.
I have an enum
public enum Vehicle {
CAR("CAR", "Car"), PUSHBIKE("PUSHBIKE", "PuschBike");
public boolean isCar()
{
...
}
public boolean isPushBike()
{
....
}
}
I have a 2 DAO CarDAO and PushBikeDAO which is are implementing a BaseDao
I have a JSF managed bean somthing like this
public class JsfManagedBean {
private Vehicle vehicle;
private BaseDAO baseDao;
public void Search()
{
//I need to get rid of this if statement
if (vehicle.isCar())
{
baseDao = new CarDao;
baseDao.search();
}
else if(vehicle.isPushBike())
{
baseDao = new PushBike;
baseDao.search();
}
//Please Note each type of search is very different call to an other party's Jar
}
}
I am trying to get rid of this if statement possibly by using generics or any proper OO technique
may be something like
baseDao = new baseDaoImpl<getClass(vehicle.getcode())>
where if vehicle.getcode() returns String value Car I do have a model class Car.
Just loud thinking (clinching the straws really :)).
This is an offshot of this question of mine
Add a method to the enum that calls new and returns the right dao.
Let each of the enum constants define their respective DAO classes:
public enum Vehicle {
CAR("CAR", "Car"){
public BaseDAO getNewDAO(){
return new CarDAO();
}
},
PUSHBIKE("PUSHBIKE", "PuschBike"){
public BaseDAO getNewDAO() {
return new PushBikeDAO();
}
};
Vehicle(String a, String b){/* ... */}
//this forces every enum constant to implement a getNewDAO() method:
abstract BaseDAO getNewDAO();
}
This way, you can use:
public void Search() {
baseDao = vehicle.getNewDAO();
baseDao.search();
}
Take a look at the Factory method pattern and the Strategy pattern if you'd like to know more. Enums are my preferred way to use the latter.
I would use a factory method, like so:
public class JsfManagedBean {
private static final Map<Vehicle,BaseDAO> daos;
static {
Map<Vehicle,BaseDAO> tmp = new HashMap<Vehicle,BaseDAO>();
tmp.put(Vehicle.CAR,new CarDAO());
tmp.put(Vehicle.BIKE,new BikeDAO());
daos = Collections.unmodifiableMap(tmp);
}
public static getDao(Vehicle v) {
return daos.get(v);
}
private Vehicle vehicle;
private BaseDAO baseDao;
public void Search()
{
baseDao = getDao(vehicle);
baseDao.search();
}
}
Unless you have more uses for DAO objects, you could make this code shorter:
if (vehicle.isCar()) new CarDao().search();
else if(vehicle.isPushBike()) new PushbikeDao().search();
With two alternatives, I'd stay with the if statement. If you had really many variants of vehicles, you could use a hash table keyed by the enum values and storing the DAO classes:
Map<Vehicle, Class> DAOClass = new HashMap<...>();
...
DAOClass.get(vehicle).getConstructor().newInstance().search();
Reflection is not that slow not to use here.