I am running into a Access-Control-Allow-Origin error when I am trying to build an OpenSocial Gadget with IBM Social Business ToolKit for IBM Connections.
I have 3 servers participating in this gadget:
CONNECTIONS: The IBM Connections 4.0 Server that will be hosting the gadget
IBMSBT: A server hosting the Social Business Toolkit scripts and app
JESSE_API: My application server hosting the API that the gadget will be using
The gadget xml is loaded from JESSE_API by CONNECTIONS. The view for the gadget loads scripts and makes calls to JESSE_API. I would like to use the Social Business Toolkit for accessing parts of Connections so the gadget view is also loading those components from IBMSBT.
I am currently just prototyping this - I was able to make this work just using the Connections 4.0 API but would rather use the SBT libraries.
For getting started I just dropped in the "Get My Communities - Main Window" snippet into my gadget's view and included the following scripts:
<script type="text/javascript">
var djConfig = {
parseOnLoad: true
};
</script>
<script src="//IBMSBT/sbt.dojo180/dojo/dojo.js"></script>
<script src="//IBMSBT/sbt.sample.web/library?ver=1.8.0"></script>
Reloading the gadget gives the following error in the console:
XMLHttpRequest cannot load http://IBMSBT/sbt.sample.web/service/proxy/connections/http/CONNECTIONS/communities/service/atom/communities/my?ps=5
Since my gadget was running on the CONNECTIONS server I should not need the proxy. I did not see an immediate way to disable the proxy for this endpoint so I just set a breakpoint in Endpoint.js before line 160 where the following code is executed:
if(this.proxy) {
args.url = this.proxy.rewriteUrl(args.url,this.proxyPath);
}
When the breakpoint hits, I set this.proxy = null which causes the proxy to not be used and the community information to return correctly.
My question is should I be doing this differently or should a way be added to bypass the use of a proxy given the structure I am currently using?
The SDK Proxy does not need to be used in this environment. We've made some changes in this area recently as part of the work to support OAuth. What you need to do is configure the SDK library initialization so it knows it's running in a Gadget context.
Take a look at the acme.social.sample.webapp:
In faces-config.xml you will see an environment for use with OpenSocial
<!-- OpenSocial Environment -->
<managed-bean>
<managed-bean-name>openSocial</managed-bean-name>
<managed-bean-class>com.ibm.sbt.jslibrary.SBTEnvironment</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
<managed-property>
<property-name>endpoints</property-name>
<value>acmeAirOS:acmeAir</value>
</managed-property>
</managed-bean>
The endpoint definition used a gadget endpoint (further down in the faces-config.xml)
<managed-bean>
<managed-bean-name>acmeAirOS</managed-bean-name>
<managed-bean-class>com.ibm.sbt.services.endpoints.GadgetOAuthEndpoint</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>url</property-name>
<value>%{acme.url}</value>
</managed-property>
</managed-bean>
In the gadget xml (or imported html) when loading the library pass a parameter to indicate that the OpenSocial environment should be used
<script type="text/javascript" src="../../library?ver=1.8.0&context=gadget&env=openSocial"></script>
Based on the information from Mark Wallace, I looked a bit closer at what the /library/ endpoint was doing.
I was not able to make it quite work exactly with that code but the following works nicely:
<script data-dojo-config="parseOnLoad:true"
src="//IBMSBT/sbt.dojo180/dojo/dojo.js.uncompressed.js"></script>
<script>
if(typeof _sbt=='undefined' || window._sbt_bridge_compat){
_sbt=0;
dojo.registerModulePath('sbt','http://IBMSBT/sbt/js/sdk/sbt');
dojo.registerModulePath('sbt/_bridge','http://IBMSBT/sbt/js/sdk/_bridges/dojo-amd');
dojo.registerModulePath('sbt/dojo','http://IBMSBT/sbt/js/sdk/dojo');
define('sbt/config',['sbt/Proxy','sbt/_bridge/Transport','sbt/authenticator/Basic','sbt/Endpoint'],function(Proxy,Transport,Basic,Endpoint){
window.sbt = {};
sbt.Properties={
"sbtUrl":"http:\/\/IBMSBT\/sbt\/js\/sdk"
};
sbt.Endpoints={
'connections':new Endpoint({
"baseUrl":"http:\/\/connectionsww.demos.ibm.com",
"transport":new Transport({}),
"authType":"basic",
"authenticator":new Basic({}),
"proxyPath":"connections"})
};
return sbt;
});
}
</script>
The contents of the script tag was basically the output from the /library/ endpoint. The sbt.Endpoints.connections definition originally included a defined proxy attribute which I removed.
Related
I use Web Flow and JSF, so they works well actually. But I am trying to find out alternative way for set default page different from redirecting on index.html.
The main problem is web analytics scripts don't work properly. I can't track user source fore home page.
The application run on Tomcat 8
Web.xml
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
index.html
<html>
<head>
<meta http-equiv="Refresh" content="0; URL=web/home-page">
</head>
</html>
UPDATE :
I replace index.html with index.jsp and I set response status as 301. At least it works for google analytics, so I'll check it out for other analytics tools.
But this solution still did not satisfy me.
Web.xml
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
index.jsp
<%
response.setStatus(301);
String path=(String)request.getAttribute("javax.servlet.forward.request_uri");
if(path==null){
path="web/home-page";
}
response.setHeader( "Location", path);
response.setHeader( "Connection", "close" );
%>
I would use spring security project instead of welcome files because JSF (or any view framework) is not aware how to resolve a view in welcome-file that is why your logic is not executing.
A possible solution is if you are using the spring security project. Add the following to your security config
<security:http auto-config="true" use-expressions="true">
<!--- config omitted for brevity -->
<security:session-management invalid-session-url="/index.jsp"/>
</security:http>
Again this is just a sample. You can also use other means to define rules. It is quite modular
<security:intercept-url pattern="/**" ....
Moreover, you will need to define a classless controller with the following defintion: (assuming you also are using Spring MVC with Webflow)
<mvc:view-controller path="/index.jsp" />
I think it's less cryptic to define intercept,forward,routing, etc... rules all in Spring Security config that way it is clear that any such rules are stored in one place.
Note: you might be able to keep your current setup and use that spring <mvc:view-controller path="/index.jsp" /> definition only to trigger the JSF to execute.
Edit: The only technologies required to reproduce this issue are JSF 2.2 and Spring Boot 1.2.1 + Its embedded Tomcat 8.0.5 server. Everything else listed in this question is just to give context on the tech I'm using.
Update #2: Following along with BalusC's thoughts, I ported my sample custom component into a barebones Servlet 3.1 + JSF 2.2 application. You can find the code for it on Github here.
This simple case does not exhibit the issue I'm describing here. The #FacesComponent annotation works. This heavily implies that the problem is being caused either by Spring 4.1.2 or Spring Boot itself. It's getting late, so I'll be investigating this further tomorrow.
TL;DR: I want to use #FacesComponent and its attributes to replace foundation-components-html.taglib.xml and the <component> entry in faces-config.xml
I currently have custom components working in my project using XML definitions. I recently learned that JSF 2.2 introduced a feature which removes the need for XML entirely. I would love to use this, but when I purely use annotations, they are ignored by JSF. Raw tags show up in my HTML.
(i.e. <custom:paragraph></custom:paragraph>)
I have demonstrated this issue in a sandbox of mine I keep hosted on Github. If you want to take a crack at that, I'll explain how at the bottom of this post.
All you need to do is delete foundation-components-html.taglib.xml, and comment out the faces-config.xml entry for <component> and run the application to encounter the issue. I left it in the 'functioning' state so that anyone who wishes to help has an easy, verifiably correct starting point. Just hit up http://localhost:8080
Technologies Used:
Spring Boot 1.2.1
JSF 2.2 via Mojarra 2.2.6
Embedded Tomcat 8.0.5
NOTE: Remember, this setup currently works, but it's running on the taglib and faces-config entries! My question is how to remove these dependencies using the latest features in JSF 2.2
Full Project
Custom Component
package foundation.components;
import java.io.IOException;
import javax.faces.component.FacesComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
/**
* The Paragraph Component
* #author Seth Ellison
*/
#FacesComponent(value=UIParagraph.COMPONENT_TYPE, createTag=true, tagName="paragraph", namespace="http://www.blah.com/components/html")
public class UIParagraph extends UIComponentBase {
public static final String COMPONENT_TYPE = "foundation.components.Paragraph";
private String value;
private String styleClass;
#Override
public void encodeBegin(final FacesContext facesContext) throws IOException {
// Encode Implementation Omitted for Brevity.
}
#Override
public String getFamily() {
return "blah.components.family";
}
// Getters/Setters...
}
Taglib Definition
<facelet-taglib version="2.2"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facelettaglibrary_2_2.xsd">
<namespace>http://www.blah.com/components/html</namespace>
<tag>
<tag-name>paragraph</tag-name>
<component>
<component-type>foundation.components.Paragraph</component-type>
</component>
</tag>
</facelet-taglib>
Faces Config
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
version="2.2" metadata-complete="false">
<component>
<component-type>foundation.components.Paragraph</component-type>
<component-class>foundation.components.UIParagraph</component-class>
</component>
</faces-config>
XHTML Template (Stripped down for clarity)
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:jsf="http://xmlns.jcp.org/jsf"
xmlns:custom="http://www.blah.com/components/html">
<head jsf:id="head"></head>
<body jsf:id="body">
<custom:paragraph value="This is a template for a simple marketing or informational website. It includes a large callout called a jumbotron and three supporting pieces of content. Use it as a starting point to create something more unique." />
</body>
</html>
If you'd like to run this, the easiest way would be to download the Spring Tool Suite, grab the code from Github, right click the project, and run it as a Spring Boot App. You'll get a connection error when the JPA configuration fires up, because you (likely) aren't running a local MySQL server. Don't worry about this. It's not at all required to visit the index page and check out the tag status. I frequently run the app both with, and without the DB fired up to no ill effect. Lastly, to get PrettyFaces to play nice with Spring Boot, you have to create either a Symbolic Link or a Hard Link from target/classes into WEB-INF/ -- PrettyFaces is coded to look in WEB-INF/classes or WEB-INF/lib when scanning for annotations.
Snippets for BalusC
This function exists in a class which is marked with #Configuration and implements ServletContextAware
#Bean
public ServletListenerRegistrationBean<ConfigureListener> jsfConfigureListener() {
return new ServletListenerRegistrationBean<ConfigureListener>(
new ConfigureListener());
}
Alright, I figured out what was causing the issue.
This morning I sat down to think about the differences between my working Servlet 3.1 version of the code, and the broken Spring Boot version. The main difference was how the code was being run. Embedded server vs. Standalone.
Spring Boot's embedded Tomcat server was the cause.
When I switched my sandbox around in accordance with this answer, everything turned on normally, and my custom components worked purely off of the #FacesComponent annotation!
I figure this has something to do with the way classes are organized post-startup on the embedded server vs. a discrete deploy to the Pivotal Tomcat server. JSF's annotation scanner seems to simply ignore annotations in that case.
I want to run a content script on an iframe with a chrome-extension:// URL. I added a line to my manifest.json that I copied out of the documentation http://code.google.com/chrome/extensions/match_patterns.html
chrome-extension://*/*
But when I reload my extension I get an alert:
Could not load extension from '/work/sirius/extension'.
Invalid value for 'content_scripts[2].matches[0]': Invalid scheme.
Any idea how to get this to worK?
No. Only ftp:, file:, http: and https: can be matched by a content script declaration.
Invalid URL patterns at any of the matches and exclude_matches fields are rejected (generating an error when trying to load the extension).
Invalid patterns at the permissions option in the manifest file are ignored.
If you want to run a script on a tab from your extension, use chrome.extension.getViews in your background script.
Even better, design your extension's pages such that they effectively communicate with each other (example).
I'm having the exact same problem, look at the API http://code.google.com/chrome/extensions/match_patterns.html it says clearly that they accept chrome-extension://*/* yet they don't.
They need to update the API so as not to confuse people.
It seems that Chrome authors have silently removed the ability for content scripts to be injected into chrome-extension: pages. Documentation still says that it works and even contains examples with chrome-extension: scheme but actually it doesn't work. So now only http:, https: and ftp: work "from the box" and file: can work if user of your extension has enabled this on Extensions (chrome://extensions/) page.
Update: now documentation referred above is updated and says nothing about ability to inject content scripts to chrome-extension: pages.
You can inject js to your iframe html(chrome-extension: pages) without declaring it in manifast.json. The injected js can visit Chrome APIs directly.
iframe.html:
<!DOCTYPE html>
<html>
<head>
...
</head>
<body>
...
</body>
<script src="iframe.js"></script>
</html>
iframe.js:
console.log(chrome); // {loadTimes: ƒ, csi: ƒ, …}
I created a simple slideshow script to include on a Google Site for Google+ albums (it uses a library found at: https://sites.google.com/site/scriptsexamples/new-connectors-to-google-services/picasa-services). The test version worked except for the fact that if publish for anonymous access, it displays that aweful "This application was not created by Google" nonsense at the top. As this is a slideshow, I tried finding a way to avoid this. Thus I decided to try my hand at a Gadget. I opted to use Google Gadget Editor and combed through the internet to see how to do this (I am a complete noob with regards to gadgets, so excuse my ignorance...)
In the end I came up with this: http://hosting.gmodules.com/ig/gadgets/file/117039901033759910299/google-plus-slider.xml
Once I insert the gadget, I do not get any error messages and the frame does display on my google site (without the warning message, as far as I can tell), but nothing else happens. And I have no idea why.
Some notes:
the javascript works when it is a google apps script, published and then inserted in my site (but the warning message is ugly)
I have no idea whether it is even possible to call typical GAS calls such as Ui.App in XML gadget - if not, then I will have to learn, but don't know where.
Obviously the library that I am using needs to be loaded - I researched as much as I could but cannot find any way to load the library. The only option I could find was to include specific predefined libraries with the Required tag.
I hope you have all the info and that someone can help! Thanks in advance.
Do you get any Cross-Domain warnings in your console?
I would try and include the external library in your gadget-name.xml file. You're free to include (mostly) whatever JS you like under
<?xml version="1.0" encoding="UTF-8" ?>
<Module>
<ModulePrefs
title="Slider"
height="50"
width="200"
border="none"
/>
<Content type="html">
<![CDATA[
<script type="text/javascript">
function my-slide-show(){
//Dump your lib JS here
}
</script>
<div class="slideshowHtml"></div>
]]>
</Content>
</Module>
This will at least avoid any scoping / Cross origin worries you might be having
I want to run a content script on an iframe with a chrome-extension:// URL. I added a line to my manifest.json that I copied out of the documentation http://code.google.com/chrome/extensions/match_patterns.html
chrome-extension://*/*
But when I reload my extension I get an alert:
Could not load extension from '/work/sirius/extension'.
Invalid value for 'content_scripts[2].matches[0]': Invalid scheme.
Any idea how to get this to worK?
No. Only ftp:, file:, http: and https: can be matched by a content script declaration.
Invalid URL patterns at any of the matches and exclude_matches fields are rejected (generating an error when trying to load the extension).
Invalid patterns at the permissions option in the manifest file are ignored.
If you want to run a script on a tab from your extension, use chrome.extension.getViews in your background script.
Even better, design your extension's pages such that they effectively communicate with each other (example).
I'm having the exact same problem, look at the API http://code.google.com/chrome/extensions/match_patterns.html it says clearly that they accept chrome-extension://*/* yet they don't.
They need to update the API so as not to confuse people.
It seems that Chrome authors have silently removed the ability for content scripts to be injected into chrome-extension: pages. Documentation still says that it works and even contains examples with chrome-extension: scheme but actually it doesn't work. So now only http:, https: and ftp: work "from the box" and file: can work if user of your extension has enabled this on Extensions (chrome://extensions/) page.
Update: now documentation referred above is updated and says nothing about ability to inject content scripts to chrome-extension: pages.
You can inject js to your iframe html(chrome-extension: pages) without declaring it in manifast.json. The injected js can visit Chrome APIs directly.
iframe.html:
<!DOCTYPE html>
<html>
<head>
...
</head>
<body>
...
</body>
<script src="iframe.js"></script>
</html>
iframe.js:
console.log(chrome); // {loadTimes: ƒ, csi: ƒ, …}