I am writing an azure function in java. To use a good modular pattern I created a service layer which has abstract interface classes and an impl layer that implements the service layer.
However, I am not using Spring-framework so I can't use #Autowired to create a singleton instance of the service layer in the runner file. How can I use my service layer functions in my runner class (or other places in my project)?
Service Layer
public interface TimeTriggeredService {
String getLogs(String token, String url,final ExecutionContext context);
}
Impl Layer
public class TimeTriggeredServiceImpl implements TimeTriggeredService {
public String getLogs(String token, String url,final ExecutionContext context) {
// Some logic
}
}
Runner Class
public class TimeTriggeredFunction {
#FunctionName("TimeTriggeredFunction")
public void run(#TimerTrigger(name = "timerInfo", schedule = "0 */1 * * * *") String timerInfo,
final ExecutionContext context) {
String timeAuditLogs = TimeTriggeredService.getLogs(token, URL ,context); // unsure what should replace this line or what should be done before this.
}
}
Note : This is NOT a spring project.
Dependency Injection for Java is not supported yet. Check out GitHub issue around the same: #324.
For now, you can use Spring Framework to use Azure Function for HTTP
requests only (not the bindings.
Here is a sample of how to use it.
If you do not want to use Spring framework, you will have to create a global instance in the class and use it.
Related
I have a REST API built on Spring Boot consisting of 2 seperate web services. I don't know if those two web services will be hosted on the same machine so I want to make remote and local implementation for all services. Example below:
Local service implementation:
public class LocalExampleService implements ExampleService{
public Item getItem(long id){
//Get item using implementation from another local project
}
}
Remote service implementation:
public class RemoteExampleService implements ExampleService{
#Value("${serviceURL}")
private String serviceURL;
public Item getItem(long id){
//Get item calling remote service
}
}
Controller:
public class MyController{
#Autowired
private ExampleService exampleService;
}
Web service has many services with local and remote implementation and I want to let Spring know which type of implementation it should choose for all services.
I've been thinking about putting url in properties file and during intialization the app would check whether properties contain url and then autowire service approprietly. But then I would have to write logic for every service autowiring.
What's the best option to autowire correct service implementation automatically?
You can use Spring profiles to control which version of implementation should be used via spring properties.
In spring properties add below entry
spring.profiles.active=NAME_OF_ACTIVE_PROFILE
Every service implementation needs profile annotation. That's how your services implementation should look like:
#Component
#Profile("local")
public class LocalExampleService implements ExampleService{}
#Component
#Profile("remote")
public class RemoteExampleService implements ExampleService{}
If your project needs to use local implementation of a service then in properties instead of NAME_OF_ACTIVE_PROFILE insert local otherwise remote.
For fully automatic auto-wiring you need to add method running at the startup that checks whether local implementation class exists and then set profile properly. To do this you need to modify code in spring boot main method:
public static void main(String[] args){
String profile = checkCurrentProfile(); //Method that decides which profile should be used
System.setProperty(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME, profile);
SpringApplication.run(MyApplication.class, args);
}
If you choose this approach then you don't need previous entry in properties file.
My attempt to implement something like this https://github.com/StanislavLapitsky/SpringSOAProxy
The idea is to check if a spring bean cannot be found locally then automatically create a Proxy which uses RestTemplate internally to call the same service remotely.
You need to define contract - services interfaces plus DTO and define URL resolver to specify which URL should be used for each service.
Hello I am trying to create an application using dropwizard framework. I have the DAO classes impl which needs an handle to connection manager instance which will then be used to get database connections. I have a multi tenant database application. This connection manager would be a custom implementation.
The application uses hikari cp as connection pool and mysql database. I want to initialize the datasource and connection pool using dropwizard managed object feature. Once the datasource is initialized I want to inject the connection manager instance in each of dao classes using guice binding something like
bind(ConnectionManager.class).toProvider(ConnectionManagerProvider.class);
Then in each dao impl classes
#Inject
public class UserDAOIpl extends AbstractDAO {
protected UserDAOImpl(ConnectionManager connectionManager) {
super(connectionManager);
}
}
I have looked everywhere on the net there is no particular example for my use case. Also there is a lack of documentation at dropwirzard.io
This is more of an architectural design question rather than code question.
The datasource module would be a separate module which would be used in many service. I am using maven as build tool.
My questions are
How I can approach this situation ? Some class names and implementation guide lines would be very useful.
The application would be handing half a million requests a day. The solution should be feasible.
I look forward to community for any guidance or if any body can point me to some good resources.
NOTE: We won't be using hibernate for this application and would be using JDBI.
I prepared a setup similar to the one you described as follows. It sets up guice, initializes a DBIFactory (you might need to adopt that part to your scenario). Then a JDBI object is handed over to a repository implementation that can use it to persist an entity of type Vessel.
(1) Adding guice to the project
<dependency>
<groupId>com.hubspot.dropwizard</groupId>
<artifactId>dropwizard-guice</artifactId>
<version>x.x.x</version>
</dependency>
(2) Setup Guice in initialize():
guiceBundle = GuiceBundle.<YourConfiguration>newBuilder()
.addModule(new GuiceModule())
.enableAutoConfig("your.package.name.heres")
.setConfigClass(YourConfiguration.class)
.build();
(3) Guice config for preparing JDBI elements
public class GuiceModule extends AbstractModule {
private DBI jdbi;
#Provides
public DBI prepareJdbi(Environment environment,
SightingConfiguration configuration) throws ClassNotFoundException {
// setup DB access including DAOs
// implementing a singleton pattern here but avoiding
// Guice to initialize DB connection too early
if (jdbi == null) {
final DBIFactory factory = new DBIFactory();
jdbi = factory.build(environment, configuration.getDataSourceFactory(), "h2");
}
return jdbi;
}
#Provides
public VesselJDBI prepareVesselJdbi(DBI jdbi) {
return jdbi.onDemand(VesselJDBI.class);
}
#Override
protected void configure() {
bind(VesselRepository.class).to(VesselRepositoryImpl.class);
/* ... */
}
}
(4) start using it in your classes
public class VesselRepositoryImpl implements VesselRepository {
private VesselJDBI jdbi;
#Inject
public VesselRepositoryImpl(VesselJDBI jdbi) {
this.jdbi = jdbi;
}
public Vessel create(Vessel instance) {
return jdbi.inTransaction((transactional, status) -> {
/* do several things with jdbi in a transactional way */
});
}
}
(please note: the last code example used Java 8. To use JDBI with Java 8 with Dropwizard 0.8.1 please use jdbi version 2.62 to avoid bug https://github.com/jdbi/jdbi/issues/144)
Please let me know if this helped you.
Best regards,
Alexander
I can't comment, but wanted to add on to Alex's answer:
For the repository implementation, I recommend having the repository be handled by jDBI instead of using Guice. Here's what I did:
In the Guice module, add a provide method:
#Provides
#Singleton
public void repository(Dbi dbi) {
// dbi.onDemand(whateverYourClassIs.class)
}
in the repository class, use #CreateSqlObject to have your DAOs available:
public abstract class Repo {
#CreateSqlObject
abstract Dao dao(); // will return a jDBI managed DAO impl
public void doWhatever() {
/// logic
}
}
This has the distinct advantage that you can now use jDBI annotations. (I have not found a way to use them with guice directly). This is very nice for example, if you need to execute DAO code in a transaction. The Repository is still handled within Guice so it can be injected anywhere, but jDBI handles the tricky bits within your DAO/Repository code.
Hope this helps :)
Artur
I'm a Tapestry5 user and wondering how I would #Inject a service class with a few arguments. From my understanding, using #Inject to inject a service class is very similar to instantiating a class with new MyClass();. The problem I seem to be having is I'm not sure how to pass the arguments into the service.
Example
Using Tapestry Servce
public class Main {
#Inject
private MyService myService;
public Main() {
//Where would I pass in my arguements?
this.myService();
//I can't seem to do this by passing the arg's in through
//this.myService(arg1, arg2) unless I may be missing something.
}
}
Traditional Usage
public class Main {
public Main() {
//In this example I can pass my arg's into the constructor.
MyService myService = new MyService(arg1, arg2);
}
}
You are not quite right in assuming that #Inject is similar to instantiation. You might somewhat argue this when your service is annotated with #Scope(ScopeConstants.PERTHREAD) but even then, tapestries IoC will instantiate the service for you. I find that most of my services are instantiated only once by tapestry and #Inject'ing them gives me a reference to this service. If you want to #Inject a service you will first need to define it with your AppModule. The simplest way to make your service available though the IoC is to bind it like so in your AppModule:
public static void bind(ServiceBinder binder) {
binder.bind(ServiceInterface.class, ServiceImplementation.class)
}
Then in your pages/components you can #Inject the interface like:
#Inject
private ServiceInterface service;
If your service then needs constructor arguments, you can create a constructor in your ServiceImplementation.class taking your required arguments. If those arguments are in themselves bound services, tapestry will figure this out and you're done. If these arguments are not services known to Tapetsry and you can't bind them for whatever reason, you can create a build method in your AppModule:
/**
* These methods may in them selves take bound services as arguments helping you build your new service
*/
public ServiceInterface buildServiceInterface(AnotherBoundService service2) {
...
return new ServiceImplementation(service2, someMoreArgsIfRequired)
}
Might you not want to use the IoC, you can always just instantiate the service in your page/component because they are just simple pojo's. Do have a look at the IoC documentation. It nicely outlines all powerful features at your disposal.
I have a moderate sized Java EE 6 project that uses several EJBs, including one which sole purpose is managing database calls through JPA. My question is what is the best way to add a new class that does some random bit of functionality and then calls the database access EJB to persist the data from this class.
Does this new class have to be an EJB if it needs access to annotations and injections? Does it have to be an EJB if it has to be deployed with the rest of the project?
I was told that if you want to add a new logic class to the project it either has to be an EJB or you can remotely integrate it using JNDI to access EJB elements and create some kind of client interface. Right now my new class is just a POJO but it's not able to access the EJB functionality.
What should I do in general?
EDIT: Please note my question IS NOT about database access. That's just an example I'm using. My guestion is more broad. I want to know how to access EJB methods from other classes I create. From one EJB to another you can simply inject the other EJB since they're both container managed. But say I create another class in the same package as the EJBs how might How can I access those methods? Is it possbile? What is the best practices here.
Right now I have a class that is taking twitter feed data from a URL it then parses the JSON and returns a string of the top 10 entries. I want to call my EJB that manages database access and pass that string to its corresponding method but I cannot do that because my class is not also an EJB.
EJBs are generally used to implement services of any kind. They integrate really well with JPA so are often used for DB access, but that's not their only usage.
What EJBs are typically not suited for is modeling data. I.e. they should be the verbs in your application, not the nouns. The following is thus wrong:
#Stateless
#Entity
public class CreditCard { // silly, don't do this!
#Id
Long id; + getters/setters
Data expiration date; + getters/setters
}
The following is better, it's a service that when your application starts up fetches some quote data from somewhere:
#Singleton
#Startup
public class QuoteFetcher {
private List<Quote> quotes; // + getter
#PostConstruct
public fetchQuote()
quotes = SomeUrlBuilder.someUrl().getQuotes();
}
}
The following is the obligatory DAO example:
#Stateless
public class JPAInvoiceDAO implements InvoiceDAO {
#PersistenceContext
private EntityManager entityManager;
public Invoice getById(Long invoiceId) {
return entityManager.find(invoiceId, Invoice.class);
}
// More DAO methods
}
The following shows how declarative security is used, and how a bean looks up something that has been externally mapped into its private context (ENC):
#Stateless
public class TokenFetcher
#Resource
private SessionContext sessionContext;
#RolesAllowed("SYSTEM")
public Token getToken() {
return (Token) sessionContext.lookup("token");
}
}
The second part of the question seems to be how to use these beans in your code. There are basically four methods:
Injection in managed beans
Bootstrapping via JNDI
Automatically called at startup
Automatically via a timer
Injection is the easiest way, but only managed beans are injection candidates (basically meaning the Java EE framework creates the bean, and you don't use new() to instantiate it).
E.g. Injection:
#ManagedBean
public class InvoiceBacking {
private Long invoiceId; // + getter/setter
private Invoice invoice; // + getter
#EJB
private InvoiceDAO invoiceDAO;
#PostConstruct
public void init() {
invoice = invoiceDAO.getById(invoiceId);
}
}
(also see Communication in JSF 2.0#Processing GET request parameters)
Bootstrapping via JNDI:
public class SomeQuartzJob implements Job {
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
InvoiceDAO invoiceDAO = (InvoiceDAO) new InitialContext().lookup("java:global/myApp/myEJB/InvoiceDAO");
List<Invoice> openInvoices = invoiceDAO.getAllByOpenStatus();
// verbose exception handling and closing JNDI context omitted for brevity
}
}
The #Singleton bean showed earlier was an example of how the Java EE framework calls your code itself at startup. For the automatic timer you would use the #Schedule annotation on a bean's method.
I have three hierarchical layers injected in Spring - rest, business logic and database operations. Junit tests for BL and DAO are working OK, when rest can inject only business logic ioc layer.
My supper class for junit tests:
import org.springframework.test.AbstractTransactionalSpringContextTests;
public class AbstractTest extends AbstractTransactionalSpringContextTests {
protected static final String path = "config/spring/applicationContext.xml";
/**
* Disabled autowire by type
* Disabled dependency check
*/
public AbstractTest() {
super();
this.setAutowireMode(AUTOWIRE_BY_NAME);
this.setDependencyCheck(false);
}
#Override
protected String[] getConfigLocations() {
return new String[] {
path
};
}
}
So - rest calls business logic and this calls database operations. Nullpointer exception falls in business logic for database calls.
More info with example:
REST: getUser(id) calls
BL: getUserBO(id) calls
DAO: getUserDAO(id)
Nullpointer is thrown on getUserDAO in getUserBO method. This only happens with junit tests it is working deployed.
do you have a data source bean defined? without more details (such as stack trace, application context files, etc.), that's the best guess i have ...
I found that it is a problem of struts2 rest class mapping. So Spring couldn't inject...