In a desktop software, the user is available to presh a button and refresh the "database".
All the info is provided by an online service which returns JSON responses, those responses are saved into DAT files and then parsed with http://www.json.org/java/index.html in order to be saved into in-memory variables as String. The DAT files are only for break-exception-support.
Ok, so I'd created a SwingWorker class which should:
parse the content from the in-memory variable
iterate through elements
recover items
update a progress bar
This is an example of the JSON code:
{
"key":"value",
"data":{
"Name1":{...},
"Name2":{...},
[...]
}
}
The full iteration of the "data" element will create a List, which I must use to create a JTable and populate the main frame of the GUI. But when executing the SwingWorker, it only returns a List which all elements are the last item of the JSON.
Here's the code the SwingWorker:
package com.wolfchamane.lolapi;
import com.wolfchamane.logging.LoCLogger;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import org.json.JSONArray;
import org.json.JSONObject;
public class LoLChampions extends SwingWorker{
private static List<LoLChampion> _list;
private static JProgressBar _status;
private static LoCLogger _log;
private static String _exePath;
private static String _version;
private static LoLDDBB _ddbb;
//private static int _max;
public List<LoLChampion> getDataTable(){
return _list;
}
public LoLChampions(){}
public LoLChampions(JProgressBar status){
this();
_status = status;
}
public LoLChampions(JProgressBar status, LoCLogger log){
this(status);
_log = log;
}
public LoLChampions(JProgressBar status, LoCLogger log, String path){
this(status, log);
_exePath = path;
}
public LoLChampions(JProgressBar status, LoCLogger log, String path, LoLDDBB ddbb){
this(status, log, path);
_ddbb = ddbb;
}
public LoLChampions(JProgressBar status, LoCLogger log, String path, LoLDDBB ddbb, String version) throws Exception{
this(status, log, path, ddbb);
_version = version;
}
#Override
protected Object doInBackground() throws Exception {
getChampionsInfo(_ddbb.getJSONChampions());
return true;
}
public void getChampionsInfo(JSONObject jsonChampions) throws Exception{
String fldrImgsPath = _exePath+File.separator+"images";
String fldrImgsChampions = fldrImgsPath+File.separator+"champions";
File fldrImages = new File(fldrImgsPath);
if (fldrImages.isDirectory() || fldrImages.mkdir()){
File fldrChampions = new File(fldrImgsChampions);
if (fldrChampions.isDirectory() || fldrChampions.mkdir()){
JSONObject data = jsonChampions.getJSONObject("data");
JSONArray championsNames = data.names();
int _max = championsNames.length();
_status.setMaximum(_max);
if (_list == null)
_list = new ArrayList<LoLChampion>();
int curr = _list.size();
for (int i = 0; i < _max; i++){
_status.setString("Fetching ["+(curr+1)+"/"+_max+"] champions icos");
//Champion object
LoLChampion champion = new LoLChampion();
//Champion name
String name = String.valueOf(championsNames.get(i));
champion.setChampionName(name);
//Champion data
JSONObject jsonChamp = data.getJSONObject(name);
//Champion roles
JSONArray tags = jsonChamp.getJSONArray("tags");
//Main role
String mRole = String.valueOf(tags.get(0));
champion.setChampionMainRole(mRole);
//Secondary role (if exists)
String sRole = "";
if (tags.length() > 1)
sRole = String.valueOf(tags.get(1));
champion.setChampionSecondRole(sRole);
//Champion ico.
File pf = new File(fldrChampions.getPath()+File.separator+name+".jpg");
saveChampionImage(name, pf);
champion.setChampionIco(pf);
//Push LoLChampion object to list
_list.add(champion);
//Update status bar
curr = _list.size();
_status.setValue(curr);
System.gc();
}//for:i
_ddbb.setChampionsList(_list);
}else{
_log.error("Couldn't access or create \""+fldrImgsChampions+"\" folder");
throw new Exception("Couldn't access or create \""+fldrImgsChampions+"\" folder");
}//fi
}else{
_log.error("Couldn't access or create \""+fldrImgsPath+"\" folder");
throw new Exception("Couldn't access or create \""+fldrImgsPath+"\" folder");
}//fi
}
private void saveChampionImage(String name, File pf) throws Exception{
String endPointURL = (new ApiURLs()).getChampionsIcoURL();
endPointURL = endPointURL.replace("{version}", _version);
endPointURL = endPointURL.replace("{champion}", name);
try{
if (!pf.canWrite())
pf.createNewFile();
URL url = new URL(endPointURL);
InputStream is = url.openStream();
OutputStream os = new FileOutputStream(pf);
_log.info("Getting \""+endPointURL+"\"");
_log.info("Saving to \""+pf.getPath()+"\"");
byte[] buffer = new byte[2048];
int length;
while((length = is.read(buffer)) != -1){
os.write(buffer, 0, length);
}//while
is.close();
os.close();
}catch(Exception ex){
_log.error(ex.getMessage());
}
}
}
UPDATE
This is the complete JSON I want to parse:
https://global.api.pvp.net/api/lol/static-data/euw/v1.2/champion?champData=tags&api_key=d34be821-7f22-4d55-85da-7409413e6379
I dont think your JSON example is well formed. JSON consists of name value pairs. There should be a ":" in between the name and a value.
Something like this:
{
"glossary": {
"title": "example glossary",
"GlossDiv": {
"title": "S",
"GlossList": {
"GlossEntry": {
"ID": "SGML",
"SortAs": "SGML",
"GlossTerm": "Standard Generalized Markup Language",
"Acronym": "SGML",
"Abbrev": "ISO 8879:1986",
"GlossDef": {
"para": "A meta-markup language, used to create markup languages such as DocBook.",
"GlossSeeAlso": ["GML", "XML"]
},
"GlossSee": "markup"
}
}
}
}
}
The JSON example you have provided looks malformed. Refer to json.org for more details
Related
I'm trying to fill a combobox with a specific field (name) from a json file.
parser file to extract information from json:
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;
public class ReferencesParser {
private final File jsonFile;
public ReferencesParser(File jsonFile) {
this.jsonFile = jsonFile;
}
public Map<ReferencesEnum, Reference> parseReferenceFile() {
Map<ReferencesEnum, Reference> referencesMap = new HashMap<>();
try {
String content = new String(Files.readAllBytes(this.jsonFile.toPath()));
JSONObject json = new JSONObject(content);
for (Object object : (JSONArray) json.get("genes")) {
JSONObject geneObject = (JSONObject) object;
Long id = geneObject.getLong("id");
String name = geneObject.getString("name");
String sequence = geneObject.getString("sequence");
Reference reference = new Reference(id, name, sequence);
referencesMap.put(ReferencesEnum.valueOf(name), reference);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return referencesMap;
}
}
genes.json file containing data to implement:
{
"genes": [
{ "id":"1","name":"gene1", "sequence": "gcattgtgggcgctatattgt" },
{ "id":"2","name":"gene2", "sequence": "gcattgtgggcgctatattcc" },
{ "id":"3","name":"gene3", "sequence": "gcatcgtgggcgctatatcat" }
]
}
and I'm trying to populate a combobox with 'name' value from json using a controller file:
...
#FXML
private ComboBox<String> choosegene;
#FXML
public void initialize(){
try {
populateGene_reference();
// System.out.println(geneFile);
System.out.println(referencesMap);
} catch (IOException e) {
e.printStackTrace();
} catch (CompoundNotFoundException e) {
e.printStackTrace();
}
};
private void populateGene_reference() throws IOException, CompoundNotFoundException {
URL url = getClass().getResource("/genes.json");
if (url != null) {
File geneFile = new File(url.getPath());
// String _Path = url.getPath();
// System.out.println("URL = " + url);
ReferencesParser parser = new ReferencesParser(geneFile);
// System.out.println("genefile = " + geneFile);
Map<ReferencesEnum, Reference> referencesMap = parser.parseReferenceFile();
// Map<ReferencesEnum, Reference> test parser.parseReferenceFile();
System.out.println("refmap = " + referencesMap);
choosegene.getItems().add(String.valueOf(referencesMap));
I have tried different ways to get my gene names but 'system.out.println' give me this:
refmap = {gene2=gene2 gcatcgtgggcgctatatcat}
refmap2 = {}
What did I miss?
Thank you for your help
ok referencesMap was ok but not choosegene, this works for me:
private void populateGene_reference() throws IOException, CompoundNotFoundException {
URL url = getClass().getResource("/main/genes.json");
if (url != null) {
File geneFile = new File(url.getPath());
ReferencesParser parser = new ReferencesParser(geneFile);
Map<ReferencesEnum, Reference> referencesMap = parser.parseReferenceFile();
for (ReferencesEnum key : referencesMap.keySet()) {
choosegene.getItems().add(referencesMap.get(key).getName());
}
Hope it will help those having the same issue!
I'm crawling amazon products and principle it's going fine.
I have three classes from this nice tutorial:
http://www.netinstructions.com/how-to-make-a-simple-web-crawler-in-java/
I added the files to the following code (class Spider):
import java.io.FileNotFoundException;
import java.util.*;
public class Spider {
public static final int MAX_PAGES_TO_SEARCH = 10000;
private Set<String> pagesVisited = new HashSet<String>();
private List<String> pagesToVisit = new LinkedList<String>();
public void search(String url) {
while (this.pagesVisited.size() < MAX_PAGES_TO_SEARCH) {
String currentUrl;
SpiderLeg leg = new SpiderLeg();
if (this.pagesToVisit.isEmpty()) {
//System.out.println("abc");
currentUrl = url;
this.pagesVisited.add(url);
} else {
//System.out.println("def");
currentUrl = this.nextUrl();
}
try {
Thread.sleep(10000);
leg.crawl(currentUrl); // Lots of stuff happening here. Look at the crawl method in
} catch (FileNotFoundException e) {
System.out.println("Oops, FileNotFoundException caught");
} catch (InterruptedException e) {
e.printStackTrace();
}
this.pagesToVisit.addAll(leg.getLinks());
//System.out.println("Test");
}
System.out.println("\n**Done** Visited " + this.pagesVisited.size() + " web page(s)");
SpiderLeg leg = new SpiderLeg();
leg.calcAdjMatrix();
for (int i = 0; i < leg.adjMatrix.length; i++) {
System.out.println(Arrays.toString(leg.adjMatrix[i]));
}
}
private String nextUrl() {
String nextUrl;
do {
if (this.pagesToVisit.isEmpty()){
return "https://www.amazon.de/Proband-Thriller-Guido-Kniesel/dp/1535287004/ref=sr_1_1?s=books&ie=UTF8&qid=1478247246&sr=1-1&keywords=%5B%5D";
}
nextUrl = this.pagesToVisit.remove(0);
} while (this.pagesVisited.contains(nextUrl));
this.pagesVisited.add(nextUrl);
return nextUrl;
}
}
class SpiderLeg:
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.*;
import java.util.*;
public class SpiderLeg {
// We'll use a fake USER_AGENT so the web server thinks the robot is a normal web browser.
private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36";
private static List<String> links = new LinkedList<String>();
private static String graphLink;
private Document htmlDocument;
private static double counter = 0;
static Map<String, Set<String>> adjMap = new HashMap<String, Set<String>>();
static int[][] adjMatrix;
static List<String> mapping;
public boolean crawl(String url) throws FileNotFoundException {
if (url.isEmpty()) {
return false;
}
try{
Connection connection = Jsoup.connect(url).ignoreContentType(true).userAgent(USER_AGENT);
Document htmlDocument = connection.get();
this.htmlDocument = htmlDocument;
if(connection.response().statusCode() == 200){
// 200 is the HTTP OK status code
// indicating that everything is great.
counter++;
double progress;
progress = (counter/Spider.MAX_PAGES_TO_SEARCH)*100;
System.out.println("\n**Visiting** Received web page at " + url);
System.out.println("\n**Progress** " + progress + "%");
}
if(!connection.response().contentType().contains("text/html")) {
System.out.println("**Failure** Retrieved something other than HTML");
return false;
}
//Elements linksOnPage = htmlDocument.select("a[href*=/gp/product/]");
Elements linksOnPage = htmlDocument.select("a[href*=/dp/]");
Elements salesRank = htmlDocument.select("span.zg_hrsr_rank");
Elements category = htmlDocument.select("span.zg_hrsr_ladder a");
String categoryString = category.html();
String salesRankString = salesRank.html();
salesRankString = salesRankString.replace("\n", " ");
categoryString = categoryString.replace("\n", " ");
//System.out.println(categoryString);
System.out.println("Found (" + linksOnPage.size() + ") links");
PrintWriter pw = new PrintWriter(new FileWriter("Horror.csv", true));
StringBuilder sb = new StringBuilder();
int beginIndex = url.indexOf(".de/");
int endIndex = url.indexOf("/dp");
String title = url.substring(beginIndex+4,endIndex);
if(!adjMap.containsKey(title)){
if(categoryString.contains("Horror")){
adjMap.put(title, new HashSet<String>());
sb.append(title);
sb.append(',');
sb.append(salesRankString);
sb.append(',');
sb.append(categoryString);
sb.append(',');
for(Element link : linksOnPage){
String graphLink = link.attr("abs:href");
if(!graphLink.contains("one-click")){
if(!graphLink.contains("Kindle")){
if(!graphLink.contains("unsticky")){
this.links.add(graphLink);
//adjMap.get(url).add(graphLink);
adjMap.get(title).add(cutTitle(graphLink));
sb.append(graphLink);
sb.append(',');
}
}
}
}
sb.append('\n');
pw.write(sb.toString());
pw.close();
}
}
System.out.println("done!");
return true;
}
catch(IOException ioe) {
// We were not successful in our HTTP request
System.out.println("Error in out HTTP request " + ioe);
return false;
}
}
public static void calcAdjMatrix(){
Set<String> allMyURLs = new HashSet(adjMap.keySet());
for(String s: adjMap.keySet()){
allMyURLs.addAll(adjMap.get(s));
System.out.println(s + "\t" + adjMap.get(s));
}
int dim = allMyURLs.size();
adjMatrix = new int[dim][dim];
List<String> nodes_list = new ArrayList<>();
for(String s: allMyURLs){
nodes_list.add(s);
}
for(String s: nodes_list){
Set<String> outEdges = adjMap.get(s);
int i = nodes_list.indexOf(s);
if(outEdges != null){
for(String s1: outEdges){
int j = nodes_list.indexOf(s1);
adjMatrix[i][j] = 1;
}
}
}
}
public String cutTitle(String url) throws FileNotFoundException{
int beginIndex = url.indexOf(".de/");
int endIndex = url.indexOf("/dp");
String title;
if(url.contains(".de") && url.contains("/dp")){
title = url.substring(beginIndex+4,endIndex);
}else{
title = "wrong url";
}
return title;
}
public boolean searchForWord(String searchWord) {
if(this.htmlDocument == null) {
System.out.println("ERROR! Call crawl() before performing analysis on the document");
return false;
}
System.out.println("Searching for the word " + searchWord + "...");
String bodyText = this.htmlDocument.body().text();
return bodyText.toLowerCase().contains(searchWord.toLowerCase());
}
public List<String> getLinks(){
return this.links;
}
}
class SpiderTest:
public class SpiderTest {
public static void main(String[] args) {
Spider spider = new Spider();
spider.search("https://www.amazon.de/Wille-geschehe-Psychothriller-Guido-Kniesel/dp/1537455389/ref=pd_sim_14_1?_encoding=UTF8&psc=1&refRID=CQPDDGY4BJ4D8THNNSZ6");
}
}
Now the problem is, that after 100 URLs I think, that amazon is banning me from the server. The program doesn't find URLs anymore.
Does anyone has an idea how I can fix that?
Well, don't be rude and crawl them then.
Check their robots.txt (wiki) to see what they allow you to do. Don't be surprised if they ban you if you go places they don't want you to go.
The problem is very common when you try to crawl big websites that don't want to be crawled. They basically block you for a period of time to prevent their data being crawled or stolen.
With that being said, you have two options, either make each request from a different IP/server which will make your requests look legit and avoid the ban, or go for the easiest way which is to use a service that does that for you.
I've done both and the first one is complex, takes time and needs maintenance (you have to build a network of servers), the second option is usually not free but very fast to implement and guarantees that all your requests will always return data and you won't be banned.
There are some services on the internet that does that. I've used proxycrawl (which also has a free tier) in the past which works very good. They have an API that you can call and you only can use your same code, just changing the url you call.
This would be an example for amazon:
GET https://api.proxycrawl.com?token=yourtoken&url=https://amazon.com
And you would get always a response, even if you crawl 1000 pages a second, you will never be banned as you will be calling that proxy instead which does all the magic for you.
I hope it helps :)
You can try using proxy servers to prevent being blocked. There are services providing working proxies. I have good experience using https://gimmeproxy.com which specifically has proxies supporting amazon.
To get proxy working with Amazon, you need just to make the following request:
https://gimmeproxy.com/api/getProxy?api_key=your_api_key&websites=amazon
You will get JSON response with all proxy data which you can use later as needed:
{
"supportsHttps": true,
"protocol": "socks5",
"ip": "116.182.122.182",
"port": "1915",
"get": true,
"post": true,
"cookies": true,
"referer": true,
"user-agent": true,
"anonymityLevel": 1,
"websites": {
"example": true,
"google": false,
"amazon": true
},
"country": "BR",
"tsChecked": 1517952910,
"curl": "socks5://116.182.122.182:1915",
"ipPort": "116.182.122.182:1915",
"type": "socks5",
"speed": 37.78,
"otherProtocols": {}
}
This question already has answers here:
How to retrieve a context from a non-activity class?
(4 answers)
Closed 6 years ago.
I'm trying to figure out how to read a CSV file stored in the assets folder. What I tried doing is using an InputFileStream as I couldn't get the a FileReader to find the files. So I put the files into the assets folder and used an InputFileStream.
To do this I used an AssetManager. The problem is this is a non activity class and it would be really hard to pass the context from the main activity because it is a large series of methods.
It starts with loadCategory():
loadCategory(0);
Which in term calls the class ToolSource (a singleton):
public void loadCategory(int categoryIndex) {
...
ToolsCategory cat = ToolsSource.getInstance().getCategory(categoryIndex);
Which creates an array of ToolCategories[]:
public static ToolsSource getInstance() {
if (instance == null) {
try {
instance = new ToolsSource();
} catch (IOException e) {
e.printStackTrace();
}
}
return instance;
}
public ToolsSource() throws IOException {
int i;
mCategory = new ToolsCategory[CATEGORIES.length];
for (i = 0; i < CATEGORIES.length; i++) {
mCategory[i] = new ToolsCategory(CATEGORIES[i]);
}
}
Which finally gets to the main class where this error is occurring. The point of this class is to populate a Tool[] array (individual categories) which in turn populate each of the ToolCategories in the mCategory[] array. LoadCategory loads the calls getCategory(0) which pulls the name of the first category in mCategory[] and assigns it through an adapter.
What I want to do is parse a CSV that contains the information of all the tools as individual lines in a CSV that represents each category. e.g. categoryName.csv contains 3 lines ergo 3 tools.
It then iterates and assigns the information in the 3 lines to the member fields of the class Tool(). e.g. mTools[i].setTitle(nextLine[0]);
package com.anothergamedesigner.listviewtest;
import android.content.Context;
import android.content.res.AssetManager;
import com.opencsv.CSVReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class ToolsCategory {
final int TOOLS_PER_CATEGORY = 10;
Context context;
private CSVReader reader;
private String categoryName;
Tool[] mTools;
public ToolsCategory(String name) throws IOException {
this.context = context.getApplicationContext();
AssetManager assetManager = context.getAssets();
categoryName = name;
mTools = new Tool[TOOLS_PER_CATEGORY];
assignValues(categoryName, assetManager);
}
private void assignValues(String name, AssetManager am) {
String categoryCSV = name + ".csv";
System.out.println("category name is: "+ categoryCSV);
int i;
for(i= 0; i<mTools.length; ++i){
try {
InputStream csvStream = am.open(categoryCSV);
InputStreamReader csvStreamReader = new InputStreamReader(csvStream);
reader = new CSVReader(csvStreamReader);
String [] nextLine;
while ((nextLine = reader.readNext()) != null) {
// nextLine[] is an array of values from the line
System.out.println("New title is: " + nextLine[0]);
mTools[i].setTitle(nextLine[0]);
System.out.println("New Subtitle is: " + nextLine[0]);
mTools[i].setSubtitleTxt(nextLine[1]);
System.out.println("New Description is: " + nextLine[0]);
mTools[i].setDescriptionTxt(nextLine[2]);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public int getToolCount(){
return mTools.length;
}
public Tool getTool(int index){
return mTools[index];
}
}
However, I'm getting an error that states:
Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference.
Is there any way for me to fix this or an alternate way to retrieve the Uri/file path of the csv so that I can give it to the CSVReader parser?
You need to give the Context of Activities
loadCategory(0); - > loadCategory(0, this);
like this fix the code :
1.
public void loadCategory(int categoryIndex, Context context) {
...
ToolsCategory cat = ToolsSource.getInstance(context).getCategory(categoryIndex);
2.
public static ToolsSource getInstance(Context context) {
if (instance == null) {
try {
instance = new ToolsSource(context);
} catch (IOException e) {
e.printStackTrace();
}
}
return instance;
}
3.
public ToolsSource(Context context) throws IOException {
int i;
mCategory = new ToolsCategory[CATEGORIES.length];
for (i = 0; i < CATEGORIES.length; i++) {
mCategory[i] = new ToolsCategory(CATEGORIES[i], context);
}
}
4.
public ToolsCategory(String name, Context context) throws IOException {
this.context = context;
AssetManager assetManager = context.getAssets();
categoryName = name;
mTools = new Tool[TOOLS_PER_CATEGORY];
assignValues(categoryName, assetManager);
}
You can just pass the context as parameter in the constructor.
Context c;
...
public ToolsCategory(String name, Context c) throws IOException {
this.c= c;
...
}
I have a Java application that leverages the OBIEE Web Service API to consume data from the BI Server. I am able to XMLViewService and the WebCatalogService just fine, but I can't quite get the HtmlViewService to properly render a report in the Java app. The report just shows the spinning loader, but never actually renders the report. I'm pretty sure it has to do with the fact that the Java app and the BI Server are on different domains. This is what the API documentation says:
In situations where Oracle BI Web Services and the third-party Web server do not belong to the same Domain Name Service (DNS) domain, users may get JavaScript errors related to browser security constraints for cross-domain scripting. To avoid these issues, use the setBridge() method to modify callback URLs to point to the third-party Web server. Be aware that a Web component executed by the third-party Web server to re-route requests to Oracle BI Web Services is not provided. This function would need to be fulfilled by the third-party application.
Several years ago, I did this same type of integration using .NET/C# and ran in the the same issue because the .NET app and the BI Server were on different domains. As a result, I had to create an HTTP Handler (.ashx file) as well as use the setBridge() method to to solve the issue.
The challenge that I'm having is that I can't find a servlet bridge example for Java. And I'm not too confident in porting the .NET/.ASHX code to a Java servlet/bridge. Does anyone have any code examples or direction they could provide to point me in the right direction? Here's a snippet of code to show you what I'm doing to pull back the report data:
// define report path
ReportRef reportRef = new ReportRef();
reportRef.setReportPath(reportFolder + "/" + reportName);
// set page params
StartPageParams pageParams = new StartPageParams();
pageParams.setDontUseHttpCookies(true);
// set report params
String pageId = htmlService.startPage(pageParams, sawSessionId);
String reportId = pageId + reportName;
htmlService.addReportToPage(pageId, reportId, reportRef, null, null, null, sawSessionId);
// get report html
StringBuffer reportHtml = new StringBuffer();
reportHtml.append(htmlService.getHtmlForReport(pageId, reportId, sawSessionId));
// return html
return reportHtml.toString();
This is the error that is coming back in the browser:
XMLHttpRequest cannot load http://myobiserver.com/analytics/saw.dll?ajaxGo. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://myjavaapp.com' is therefore not allowed access.
Per requested, here is my .NET/.ASHX bridge:
using System.Collections.Specialized;
using System.Net;
using System.Text;
using System.Web;
using System;
using System.Collections;
using System.Configuration;
using System.Collections.Specialized;
using System.Web;
using System.Text;
using System.Net;
using System.IO;
using System.Diagnostics;
/*
This is a ASP.NET handler that handles communication
between the SharePoint site and OracleBI.
It will be deployed to:
C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS\OracleBI
*/
public class OracleBridge: IHttpHandler
{
public bool IsReusable {get{return true;}}
public OracleBridge()
{
}
string getServer()
{
string strServer = "http://<enter-domain>/analytics/saw.dll";
int index = strServer.LastIndexOf("/");//split off saw.dll
if (index >=0)
return strServer.Substring(0,index+1);
else
return strServer;
}
public void ProcessRequest(HttpContext context)
{
HttpWebRequest req = forwardRequest(context);
forwardResponse(context,req);
}
private HttpWebRequest forwardRequest(HttpContext context)
{
string strURL = makeURL(context);
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(strURL);
req.Method = context.Request.HttpMethod;
NameValueCollection headers = context.Request.Headers;
req.Accept = headers.Get("Accept");
req.Expect = headers.Get("Expect");
req.ContentType = headers.Get("Content-Type");
string strModifiedSince = headers.Get("If-Modified-Since");
if (strModifiedSince != null && strModifiedSince.Length != 0)
req.IfModifiedSince = DateTime.Parse(strModifiedSince);
req.Referer = headers.Get("Referer");
req.UserAgent = headers.Get("User-Agent");
if (!req.Method.Equals("GET"))
{
CopyStreams(context.Request.InputStream,req.GetRequestStream());
}
return req;
}
private void forwardResponse(HttpContext context, HttpWebRequest req)
{
HttpWebResponse resp =null;
try
{
resp = (HttpWebResponse)req.GetResponse();
}
catch(WebException e)
{
resp = (HttpWebResponse)e.Response;
}
context.Response.StatusCode = (int)resp.StatusCode;
for (int i = 0; i < resp.Cookies.Count; i++)
{
Cookie c = resp.Cookies[i];
HttpCookie hc = new HttpCookie(c.Name, c.Value);
hc.Path = c.Path;
hc.Domain = getServer();
context.Response.Cookies.Add(hc);
}
context.Response.ContentType = resp.ContentType;
CopyStreams(resp.GetResponseStream(), context.Response.OutputStream);
}
private string makeURL(HttpContext context)
{
string strQuery = context.Request.Url.Query;
string[] arrParams = strQuery.Split('?','&');
StringBuilder resultingParams = new StringBuilder();
string strURL=null;
foreach(string strParam in arrParams )
{
string[] arrNameValue = strParam.Split('=');
if (!arrNameValue[0].Equals("RedirectURL"))
{
if (strParam.Length != 0)
{
if (resultingParams.Length != 0)
resultingParams.Append("&");
resultingParams.Append(strParam);
}
}
else if (arrNameValue.Length >1)
strURL = HttpUtility.UrlDecode(arrNameValue[1]);
}
if (strURL ==null)
throw new Exception("Invalid URL format. requestURL parameter is missing");
String sAppendChar = strURL.Contains("?") ? "&" : "?";
if (strURL.StartsWith("http:") || strURL.StartsWith("https:"))
{
String tmpURL = strURL + sAppendChar + resultingParams.ToString();
return tmpURL;
}
else
{
String tmpURL = getServer() + strURL + sAppendChar + resultingParams.ToString();
return tmpURL;
}
}
private void CopyStreams(Stream inStr,Stream outStr)
{
byte[] buf = new byte[4096];
try
{
do
{
int iRead = inStr.Read(buf,0,4096);
if (iRead == 0)
break;
outStr.Write(buf,0,iRead);
}
while (true);
}
finally
{
outStr.Close();
}
}
}
Using the BridgeServlet from link (http://pastebin.com/NibVnBLb) posted in previous answer did not work for us. In our web portal, embedding Oracle BI dashboard using BridgeServlet above, redirected us to OBI login page and console log showed incorrect resources(js/css) web links (local URL instead of OBIEE URL's).
Instead we used this class (with some minor adjustments) https://gist.github.com/rafaeltuelho/9376341#file-obieehttpservletbridge-java.
Tested with Java 11, Oracle Business Intelligence 12.2.1.4.0, WSDL v12 of OBIEE (http://OBIEE-server:port/analytics/saw.dll/wsdl/v12), with SSO disabled.
Here it is the BridgeServlet class:
package com.abs.bi;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class OBIEEBridge
*/
public class BridgeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* #see HttpServlet#HttpServlet()
*/
public BridgeServlet() {
super();
}
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
this.processRequest(request, response);
} catch (Exception e) {
throw new ServletException(e);
}
}
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
this.processRequest(request, response);
} catch (Exception e) {
throw new ServletException(e);
}
}
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpURLConnection urlCon = forwardRequest(request);
forwardResponse(response, urlCon);
}
#SuppressWarnings("unchecked")
private String decodeURL(HttpServletRequest request) {
StringBuffer bufURL = new StringBuffer("");
Map<String, String[]> params = request.getParameterMap();
String[] arrURL = params.get("RedirectURL");
String strURL = arrURL == null || arrURL.length == 0 ? null : arrURL[0];
bufURL.append(strURL);
int nQIndex = strURL.lastIndexOf('?');
if (params != null && !params.isEmpty()) {
bufURL.append(((nQIndex >= 0) ? "&" : "?"));
Set<String> keys = params.keySet();
Iterator<String> it = keys.iterator();
while (it.hasNext()) {
try {
String strKey = it.next();
if (strKey.equalsIgnoreCase("RedirectURL")) {
continue;
}
String strEncodedKey = URLEncoder.encode(strKey, "UTF-8");
String[] paramValues = params.get(strKey);
for (String paramValue : paramValues) {
bufURL.append(strEncodedKey);
bufURL.append("=");
bufURL.append(URLEncoder.encode(paramValue, "UTF-8"));
bufURL.append("&");
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
bufURL.deleteCharAt(bufURL.length() - 1);
}
return bufURL.toString();
}
#SuppressWarnings("unchecked")
private HttpURLConnection forwardRequest(HttpServletRequest request) throws IOException {
String strURL = decodeURL(request);
String[] arrURL = strURL.split("&", 2);
String baseURL = arrURL[0];
URL url = new URL(baseURL);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
String strMethod = request.getMethod();
con.setRequestMethod(strMethod);
Enumeration<String> en = request.getHeaderNames();
String strHeader;
while (en.hasMoreElements()) {
strHeader = en.nextElement();
String strHeaderValue = request.getHeader(strHeader);
con.setRequestProperty(strHeader, strHeaderValue);
}
// is not a HTTP GET request
if (strMethod.compareTo("GET") != 0) {
con.setDoOutput(true);
con.setDoInput(true);
con.setUseCaches(false);
DataOutputStream forwardStream = new DataOutputStream(con.getOutputStream());
try {
String urlParameters = arrURL[1];
forwardStream.writeBytes(urlParameters);
forwardStream.flush();
} finally {
forwardStream.close();
}
}
return con;
}
private void forwardResponse(HttpServletResponse response, HttpURLConnection con) throws IOException {
int nContentLen = -1;
String strKey;
String strValue;
try {
response.setStatus(con.getResponseCode());
for (int i = 1; true; ++i) {
strKey = con.getHeaderFieldKey(i);
strValue = con.getHeaderField(i);
if (strKey == null) {
break;
}
if (strKey.equals("Content-Length")) {
nContentLen = Integer.parseInt(con.getHeaderField(i));
continue;
}
if (strKey.equalsIgnoreCase("Connection") || strKey.equalsIgnoreCase("Server")
|| strKey.equalsIgnoreCase("Transfer-Encoding") || strKey.equalsIgnoreCase("Content-Length")) {
continue; // skip certain headers
}
if (strKey.equalsIgnoreCase("Set-Cookie")) {
String[] cookieStr1 = strValue.split(";");
String[] cookieStr2 = cookieStr1[0].split("=");
// String[] cookieStr3 = cookieStr1[1].split("=");
/*
* Change the Set-Cookie HTTP Header to remove the 'path' attribute. Thus the
* browser can accept the ORA_BIPS_NQID cookie from Oracle BI Server
*/
Cookie c = new Cookie(cookieStr2[0], cookieStr2[1]);
c.setPath("/");
response.addCookie(c);
} else {
response.setHeader(strKey, strValue);
}
}
copyStreams(con.getInputStream(), response.getOutputStream(), nContentLen);
} finally {
response.getOutputStream().close();
con.getInputStream().close();
}
}
private void copyStreams(InputStream inputStream, OutputStream forwardStream, int nContentLen) throws IOException {
byte[] buf = new byte[1024];
int nCount = 0;
int nBytesToRead = 1024;
int nTotalCount = 0;
do {
if (nContentLen != -1)
nBytesToRead = nContentLen - nTotalCount > 1024 ? 1024 : nContentLen - nTotalCount;
if (nBytesToRead == 0)
break;
// try to read some bytes from src stream
nCount = inputStream.read(buf, 0, nBytesToRead);
if (nCount < 0)
break;
nTotalCount += nCount;
// try to write some bytes in target stream
forwardStream.write(buf, 0, nCount);
} while (true);
}
}
AbsServiceUtils which contains SAWSessionService and HtmlViewService web service calls to Oracle BI server:
package com.abs.bi;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspWriter;
import oracle.bi.web.soap.AuthResult;
import oracle.bi.web.soap.HtmlViewService;
import oracle.bi.web.soap.HtmlViewServiceSoap;
import oracle.bi.web.soap.ReportHTMLLinksMode;
import oracle.bi.web.soap.ReportHTMLOptions;
import oracle.bi.web.soap.ReportRef;
import oracle.bi.web.soap.SAWLocale;
import oracle.bi.web.soap.SAWSessionParameters;
import oracle.bi.web.soap.SAWSessionService;
import oracle.bi.web.soap.SAWSessionServiceSoap;
import oracle.bi.web.soap.StartPageParams;
public class AbsServiceUtils {
private AbsServiceUtils() {
}
public static URL buildWsdlUrl() throws MalformedURLException {
return new URL(IAbsService.BASEWSDLURL);
}
public static void writeBiContent(HttpServletRequest request, JspWriter out, String biReport) throws IOException {
String userAgent = request.getHeader("User-Agent");
Locale userLocale = request.getLocale();
String bridgeServletContextPath = request.getContextPath() + "/bridgeservlet";
String reportHtml = writeBiContent(biReport, userAgent, userLocale, bridgeServletContextPath);
if (out != null) {
out.println(reportHtml);
}
}
public static String writeBiContent(String biReport, String userAgent, Locale userLocale,
String bridgeServletContextPath) throws MalformedURLException {
HtmlViewService htmlViewService = new HtmlViewService(buildWsdlUrl());
HtmlViewServiceSoap htmlClient = htmlViewService.getHtmlViewService();
SAWSessionService sAWSessionService = new SAWSessionService(buildWsdlUrl());
SAWSessionServiceSoap myPort = sAWSessionService.getSAWSessionServiceSoap();
SAWSessionParameters sessionparams = new SAWSessionParameters();
sessionparams.setUserAgent(userAgent);
SAWLocale sawlocale = new SAWLocale();
sawlocale.setLanguage(userLocale.getLanguage());
sawlocale.setCountry(userLocale.getCountry());
sessionparams.setLocale(sawlocale);
sessionparams.setAsyncLogon(false);
AuthResult result = myPort.logonex(IAbsService.BIUSERNAME, IAbsService.BIPASSWORD, sessionparams);
String sessionID = result.getSessionID();
List<String> keepAliveSessionList = new ArrayList<>(1);
keepAliveSessionList.add(sessionID);
myPort.keepAlive(keepAliveSessionList);
StartPageParams spparams = new StartPageParams();
spparams.setDontUseHttpCookies(true);
String pageID = htmlClient.startPage(spparams, sessionID);
/**
* This method will set the path to the servlet which will act like a bridge to
* retrieve all the OBIEE resources like the javascript, CSS and the report.
*/
if (bridgeServletContextPath != null) {
htmlClient.setBridge(bridgeServletContextPath, sessionID);
}
ReportHTMLOptions htmlOptions = new ReportHTMLOptions();
htmlOptions.setEnableDelayLoading(false);
htmlOptions.setLinkMode(ReportHTMLLinksMode.IN_PLACE.value());
ReportRef reportref = new ReportRef();
reportref.setReportPath(IAbsService.BIROOTPATH + biReport);
StartPageParams startpageparams = new StartPageParams();
startpageparams.setDontUseHttpCookies(false);
htmlClient.addReportToPage(pageID, biReport.replace(" ", ""), reportref, null, null, htmlOptions, sessionID);
String reportHtml = htmlClient.getHeadersHtml(pageID, sessionID);
reportHtml = reportHtml + htmlClient.getHtmlForReport(pageID, biReport.replace(" ", ""), sessionID);
reportHtml = reportHtml + htmlClient.getCommonBodyHtml(pageID, sessionID);
return reportHtml;
}
}
IAbsService:
package com.abs.bi;
public interface IAbsService {
public static final String BASEWSDLURL = "http://<OracleBIServer:port>/analytics/saw.dll/wsdl/v12";
public static final String BIUSERNAME = "USER";
public static final String BIPASSWORD = "PASS";
public static final String BIROOTPATH = "/shared/sharedfolder/";
public static final String BIREPORTNAME = "report";
}
Use the link http://pastebin.com/NibVnBLb to check out the bridge code for java. Hope this might be helful.
I have this string coming from my dataBase:
<user>
<name>John</name>
<surname>Shean</surname>
<birthdate>1/1/1111</birthdate>
<phone >(555) 444-1111</phone>
<city>NY</city>
</user>
I need to parse it and add to:
arrayList<User>.(User(name,surname,...))
It should end up looking like this:
user[1]={name="John",surname="Shena",...}
I used the following method but it isn't working right. Does anyone have a method to will do this?
public User parseList(String array) {
User user = new User();
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
URL u = new URL("xmldb:exist://192.168.1.71:8094/exist/xmlrpc/db/testDB/userInformation.xml");
Document doc = builder.parse(u.openStream());
NodeList nodes = doc.getElementsByTagName("user");
Element element = (Element) nodes.item(0);
user.setName(getElementValue(element, "name"));
user.setSurname(getElementValue(element, "surname"));
user.setBirthdate(getElementValue(element, "birthdate"));
user.setPhone(getElementValue(element, "phone"));
user.setCity(getElementValue(element, "city"));
System.out.println(user);
} catch (Exception e) {
e.printStackTrace();
}
return user;
}
protected String getElementValue(Element parent, String label) {
return getCharacterDataFromElement((Element) parent.getElementsByTagName(label).item(0));
}
private String getCharacterDataFromElement(Element e) {
try {
Node child = e.getFirstChild();
if (child instanceof CharacterData) {
CharacterData cd = (CharacterData) child;
return cd.getData();
}
} catch (Exception ex) {
}
return "";
}
1 - model your use class:
package com.howtodoinjava.xml.sax;
/**
* Model class. Its instances will be populated using SAX parser.
* */
public class User
{
//XML attribute id
private int id;
//XML element name
private String Name;
//XML element surname
private String SurName;
//...
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return Name;
}
public void setName(String Name) {
this.Name = Name;
}
public String getSurName() {
return SurName;
}
public void setSurName(String SurName) {
this.SurName = SurName;
}
// [...]
#Override
public String toString() {
return this.id + ":" + this.Name + ":" +this.SurName ;
}
}
2 - Build the handler by extending DefaultParser
package com.howtodoinjava.xml.sax;
import java.util.ArrayList;
import java.util.Stack;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class UserParserHandler extends DefaultHandler
{
//This is the list which shall be populated while parsing the XML.
private ArrayList userList = new ArrayList();
//As we read any XML element we will push that in this stack
private Stack elementStack = new Stack();
//As we complete one user block in XML, we will push the User instance in userList
private Stack objectStack = new Stack();
public void startDocument() throws SAXException
{
//System.out.println("start of the document : ");
}
public void endDocument() throws SAXException
{
//System.out.println("end of the document document : ");
}
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException
{
//Push it in element stack
this.elementStack.push(qName);
//If this is start of 'user' element then prepare a new User instance and push it in object stack
if ("user".equals(qName))
{
//New User instance
User user = new User();
//Set all required attributes in any XML element here itself
if(attributes != null && attributes.getLength() == 1)
{
user.setId(Integer.parseInt(attributes.getValue(0)));
}
this.objectStack.push(user);
}
}
public void endElement(String uri, String localName, String qName) throws SAXException
{
//Remove last added element
this.elementStack.pop();
//User instance has been constructed so pop it from object stack and push in userList
if ("user".equals(qName))
{
User object = this.objectStack.pop();
this.userList.add(object);
}
}
/**
* This will be called everytime parser encounter a value node
* */
public void characters(char[] ch, int start, int length) throws SAXException
{
String value = new String(ch, start, length).trim();
if (value.length() == 0)
{
return; // ignore white space
}
//handle the value based on to which element it belongs
if ("name".equals(currentElement()))
{
User user = (User) this.objectStack.peek();
user.setName(value);
}
else if ("surname".equals(currentElement()))
{
User user = (User) this.objectStack.peek();
user.setSurName(value);
}
}
/**
* Utility method for getting the current element in processing
* */
private String currentElement()
{
return this.elementStack.peek();
}
//Accessor for userList object
public ArrayList getUsers()
{
return userList;
}
}
3 - Write parser for xml file
package com.howtodoinjava.xml.sax;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
public class UsersXmlParser
{
public ArrayList parseXml(InputStream in)
{
//Create a empty link of users initially
ArrayList<user> users = new ArrayList</user><user>();
try
{
//Create default handler instance
UserParserHandler handler = new UserParserHandler();
//Create parser from factory
XMLReader parser = XMLReaderFactory.createXMLReader();
//Register handler with parser
parser.setContentHandler(handler);
//Create an input source from the XML input stream
InputSource source = new InputSource(in);
//parse the document
parser.parse(source);
//populate the parsed users list in above created empty list; You can return from here also.
users = handler.getUsers();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
}
return users;
}
}
4 - Test parser
package com.howtodoinjava.xml.sax;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
public class TestSaxParser
{
public static void main(String[] args) throws FileNotFoundException
{
//Locate the file OR String
File xmlFile = new File("D:/temp/sample.xml");
//Create the parser instance
UsersXmlParser parser = new UsersXmlParser();
//Parse the file Or change to parse String
ArrayList users = parser.parseXml(new FileInputStream(xmlFile));
//Verify the result
System.out.println(users);
}
}
If you want to parse XML, you can use an XML parser.
This may help you:
Java:XML Parser