How to convert BI/reporting Request into SQL statements - java

I am trying to create a data analytics service that can be used by REST client. REST request needs to send a ANSI SQL queries. Challenge is client/UI team wants to create their own Tableau like drag and drop style user interface where User can see parts of their data and build reports with it. So to bridge the gap between such UI and Analytics service, someone needs to convert form data into SQL Statements (we ruled out json based descriptive rest payload as it doesn't scale for full fledge sql). Datasource Metadata (tables, columns, datatypes etc) is available via REST api to UI so UI can send them back with their API request to some another service which can do SQL transformation. This service can also access API that describe relationships between tables/datasources (join, start-schema etc). so such service has enough information on what kind of SQL queries to form based on user selection. It doesn't need to optimize the query as it will be done by backend data analytics service. Is this seems like a good approach? I wonder UI visualization tool connecting via JDBC to datasources taking same approach. Any other suggestions are welcome.
Also, I can see such middleware service can be a generic framework for development of analytics or cubing visualization tool.

Related

Sending Dynamic Emails through a Java Cron Job using Microsoft Graph

I have a java (Spring boot) web service which does not have any UI.
I want to send a dynamic Email (created using Thymeleaf and injecting values from a database) using my web service on a daily Cron schedule, using Microsoft Graph and O365 APIs.
Right now I use SMTP to send emails, but I cannot use it anymore as that is no longer going to be supported by the O365 account that I am using.
I found the SendMail APIs on the Graph Documentation which looks pretty straightforward.
But, using the Graph AIPs requires you to create an Azure AD project first and use their Microsoft Identity platform - which I created.
Now, the problem is that most of the flows also require a user to manually login from a login window.
This is where things get complicated.
I do not have a place to show a Login window to any user from my web service, because it is just a backend service there is no UI. I intend to use a service account for sending the emails through the Application.
I found a Daemon support as well, but it seems to only support Python or .Net code.
Migrating my code from Java to either of those platforms just to be able to send emails
does not feel like a good solution.
And, I'm not even sure if they even offer similar capabilities of sending dynamic emails like Java+Thylemeaf do?
Is there a way to be able to continue doing this using my existing code in Java?
If not, then as the worst case scenario, are there any libraries in Python which can allow me to send dynamic emails like thymeleaf does in Java?
As you don't want to manually login from a login window, you can use the client credential flow.
Here is the guide regarding how to access graph api without user.
Reference:
msgraph-sdk-java-auth (You can choose to use Client credential provider)

How to write a function to handle custom query in JPA repository in spring boot java?

Basically I am hosting a database on server side using spring boot. And I wanted to write custom query from client side which is developed in angular and call a function from server side for giving me the needed results.
The function for server side will look like this:
List<rows> func(String customQuery){
//fetch rows from table using this custom query and return those rows
//which I can use in client side.
}
Below are examples of customQuery which I need to send from client side:
select * from table;
select * from table where id>10;
select * from table where id>20 and id<30;
So far I searched in Internet I could not find any solution. Please help.
Sending SQL directly from the client would be a complete security failure, because a malicious user could easily figure out how it works and send a delete from table to kill your entire app.
Much worse, they might even be able to run create user ... to give themselves complete access to your entire database, get sensitive information, install malware, etc.
Instead you'll want to create a REST service in your application with methods such as
GET /table
GET /table?minId=10
GET /table?minId=20&maxId=30
Return as application/json or a similar data format and only return the information your angular app really needs.
Angular would then be responsible for selectively updating the display with your data.
Edit:
This is a guide I have found for creating a basic web app based on Spring Boot and Angular. Might be a good starting point for you:
https://www.baeldung.com/spring-boot-angular-web
The best way is to send only the parameters (minID and maxID in your case) from the client-side and then build the query dynamically on server-side using Spring JPA Specifications.

Exposing a web site through web services

I know what I am asking is somehow weird. There is a web application (which we don't have access to its source code), and we want to expose a few of its features as web services.
I was thinking to use something like Selenium WebDriver, so I simulate web clicks on the application according to the web service request.
I want to know whether this is a better solution or pattern to do this.
I shall mention that the application is written using Java, Spring MVC (it is not SPA) and Spring Security. And there is a CAS server providing SSO.
There are multiple ways to implement it. In my opinion Selenium/PhantomJS is not the best option as if the web is properly designed, you can interact with it only using the provided HTML or even some API rather than needing all the CSS, and execute the javascript async requests. As your page is not SPA it's quite likely that an "API" already exists in form of GET/POST requests and you might be lucky enough that there's no CSRF protection.
First of all, you need to solve the authentication against the CAS. There are multiple types of authentication in oAuth, but you should get an API token that enables you access to the application. This token should be added in form of HTTP Header or Cookie in every single request. Ideally this token shouldn't expire, otherwise you'll need to implement a re-authentication logic in your app.
Once the authentication part is resolved, you'll need quite a lot of patience, open the target website with the web inspector of your preferred web browser and go to the Network panel and execute the actions that you want to run programmatically. There you'll find your request with all the headers and content and the response.
That's what you need to code. There are plenty of libraries to achieve that in Java. You can have a look at Jsop if you need to parse HTML, but to run plain GET/POST requests, go for RestTemplate (in Spring) or JAX-RS/Jersey 2 Client.
You might consider implementing a cache layer to increase performance if the result of the query is maintained over the time, or you can assume that in, let's say 5 minutes, the response will be the same to the same query.
You can create your app in your favourite language/framework. I'd recommend to start with SpringBoot + MVC + DevTools. That'd contain all you need + Jsoup if you need to parse some HTML. Later on you can add the cache provider if needed.
We do something similar to access web banking on behalf of a user, scrape his account data and obtain a credit score. In most cases, we have managed to reverse-engineer mobile apps and sniff traffic to use undocumented APIs. In others, we have to fall back to web scraping.
You can have two other types of applications to scrape:
Data is essentially the same for any user, like product listings in Amazon
Data is specific to each user, like in a banking app.
In the firs case, you could have your scraper running and populating a local database and use your local data to provide the web service. In the later case, you cannot do that and you need to scrape the site on user's request.
I understand from your explanation that you are in this later case.
When web scraping you can find really difficult web apps:
Some may require you to send data from previous requests to the next
Others render most data on the client with JavaScript
If any of these two is your case, Selenium will make your implementation easier though not performant.
Implementing the first without selenium will require you to do lots of trial an error to get the thing working because you will be simulating the requests and you will need to know what data is expected from the client. Whereas if you use selenium you will be executing the same interactions that you do with the browser and hence sending the expected data.
Implementing the second case requires your scraper to support JavaScript. AFAIK best support is provided by selenium. HtmlUnit claims to provide fair support, and I think JSoup provides no support to JavaScript.
Finally, if your solution takes too much time you can mitigate the problem providing your web service with a notification mechanism, similar to Webhooks or Resthooks:
A client of your web service would make a request for data providing a URI they would like to get notified when the results are ready.
Your service would respond immediatly with an id of the request and start scraping the necessary info in the background.
If you use skinny payload model, when the scraping is done, you store the response in your data store with an id identifying the original request. This response will be exposed as a resource.
You would execute an HTTPPOST on the URI provided by the client. In the body of the request you would add the URI of the response resource.
The client can now GET the response resource and because the request and response have the same id, the client can correlate both.
Selenium isn't a best way to consume webservices. Selenium is preferably an automation tool largely used for testing the applications.
Assuming the services are already developed, the first thing we need to do is authenticate user request.
This can be done by adding a HttpHeader with key as "Authorization" and value as "Basic "+ Base64Encode(username+":"+password)
If the user is valid (Users login credentials match with credentials in server) then generate a unique token, store the token in server by mapping with the user Id and
set the same token in the response header or create a cookie containing token.
By doing this we can avoid validating credentials for the following requests form the same user by just looking for the token in the response header or cookie.
If the services are designed to chcek login every time the "Authorization" header needs to be set in request every time when the request is made.
I think it is a lot of overhead using a webdriver but it depends on what you really want to achieve. With the info you provided I would rather go with a restTemplate implementation sending the appropriate http messages to the existing webapp, wrap it with a nice #service layer and build your web service (rest or soap) on top of it.
The authentication is a matter of configuration, you can pack this in a microservice with #EnableOAuth2Sso and your restTemplate bean, thanks to spring boot, will handle the underlining auth part for you.
May be overkill..... But RPA? http://windowsitpro.com/scripting/review-automation-anywhere-enterprise

How to handle user information with Spring Security, Spring LDAP, and Hibernate?

I have an application built on Spring MVC that uses Hibernate for all of it's DB interaction needs. There is now a need to update the application to use our LDAP infrastructure to drive the user information, including basic user data, such as name and email, as well as authentication and authorization needs as well.
Since everything has been in one spot (the DB) up to now, the reports are all fairly straightforward, since Hibernate is managing retrieval of information as needed when starting with the required queries. Grabbing the users' name, etc. is very simple, since Hibernate loads the data lazily.
With the desire to drive the user information with LDAP, Hibernate will no longer be able to populate the user information on the fly, since it won't be managing the users' data. How should we use LDAP to drive the user data and deal with authentication / authorization without causing to much pain when we need to grab user data like Name, etc.?
We have considered using a hybrid approach where LDAP is treated as the "source" for the data and the current system is left as-is. This would require changes to the transaction processing code to update against LDAP so that the live transaction is using up-to-date information, and also a periodic sync against LDAP to keep the application DB up-to-date for reporting purposes.
This solution seems a bit hacky, and seems to have a lot of moving parts, but I could not find much on this subject elsewhere on the web.
How should user information be handled / how should the app be structured so that all of the user information is still easily accessible and can be easily tied to the rest of the system for reporting purposes? Is there a way to integrate Spring LDAP and Hibernate so that layers above the data layer don't have to know? Or is pulling the info from LDAP into the existing database the easiest way to go?
If you can not drop the user table at all, because it is used from other entities, then my suggestion is to separete the security stuff from the business stuff.
This mean remove the only for security needed information from the user table (login, password, ...), so that only the stuff remains that is needed to implement the buiness cases.
Then rewrite the security stuff so that is is based on the LDAP. I guess you find a way to get the user data base object for an given prinipal.
Only one thing will remain, how to create new user database entities if a new person get a new login. You have 3 choices, what is the best one strongly depends on your application:
Create the database entity if the users first login
Create the database entity if you first need it
Create the database entity when it is created in the LDAO (or some minites later) for example with an cron job, or some Spring Scheduling service.

Master data validation in service layer

User enters the data in the forms by choosing values from the master data drop downs in web layer. Data is populated in the dropdowns based on some logic from the master data tables and we know for sure that its a valid master data as far as web layer is concern. Now my question is, should be check the validity of the master data in service layer again because we want to use service layer for mulitple interfaces (Web User Interface, Web Services, Unit Test Cases etc.) or we should validate the master data in respective interfaces only.
In general we should validate incoming data. Right now, we kow that the data, that is sent to the service layer is valid, just because we trust the web frontend. But you already mentioned that the service layer is not restricted to receiving input from that single trusted source.
And as soon as it provides a 'public interface', it should expect receiving invalid data.
I usually stick to the simple paradigm: a sender or data source should always send in an absolutely correct format and a receiver or data sink should always be prepared to receive invalid data. Nice example for this: web servers and browsers.

Categories

Resources