I have created a Adobe IO runtime project based on firefly template. I have added Adobe Analytics API in my console.adobe.io. While creating the project thru AIO, it has created a sample action which fetches collections from adobe analytics.
Problem 1: When I open this app using localhost:9080, I get this error
in ForwardRef($f01f0d1066865f7027d77d32f5de6fe$var$Picker) (created by App) in ModalProvider (created by ForwardRef($bc3300334f45fd1ec62a173e70ad86$var$Provider)) in I18nProvider (created by ForwardRef($bc3300334f45fd1ec62a173e70ad86$var$Provider)) in ForwardRef($bc3300334f45fd1ec62a173e70ad86$var$Provider) (created by ForwardRef($d618213cd07bac427c632ce5c90d7$var$Form)) in form (created by ForwardRef($d618213cd07bac427c632ce5c90d7$var$Form)) in ForwardRef($d618213cd07bac427c632ce5c90d7$var$Form) (created by App) in div (created by ForwardRef($f9fee2c1db386bde8f28b36a814d1eb2$var$Flex)) in ForwardRef($f9fee2c1db386bde8f28b36a814d1eb2$var$Flex) (created by App) in div (created by ForwardRef($f9fee2c1db386bde8f28b36a814d1eb2$var$Flex)) in ForwardRef($f9fee2c1db386bde8f28b36a814d1eb2$var$Flex) (created by App) in div (created by ForwardRef(ProviderWrapper)) in ForwardRef(ProviderWrapper) (created by ForwardRef($bc3300334f45fd1ec62a173e70ad86$var$Provider)) in ModalProvider (created by ForwardRef($bc3300334f45fd1ec62a173e70ad86$var$Provider)) in I18nProvider (created by ForwardRef($bc3300334f45fd1ec62a173e70ad86$var$Provider)) in ForwardRef($bc3300334f45fd1ec62a173e70ad86$var$Provider) (created by App) in ErrorBoundary (created by App) in App Cannot destructure property 'scale' of '(0 , _provider.useProvider)(...)' as it is null.
Problem 2: When I call the action from CURL I get this error
400: missing parameter(s) 'companyId'
I understand that I need to send company Id. But what I am not understanding is how to send it. Here is what i tried so far:
1. sent it as a header - 400: missing parameter(s) 'companyId'
2. sent it in json body - Request defines parameters that are not allowed (e.g., reserved properties)
3. sent it as query param.-Request defines parameters that are not allowed (e.g., reserved properties)
None of these have worked so far. I do not see any documentation on how to send this parameter. Please help.
EDIT: here is the app.js. I havent made any changes to these files.
/*
* <license header>
*/
// react imports
import React from 'react'
import PropTypes from 'prop-types'
import ErrorBoundary from 'react-error-boundary'
// react spectrum components
import { Provider } from '@react-spectrum/provider'
import { theme } from '@react-spectrum/theme-default'
import { Button } from '@react-spectrum/button'
import { TextField } from '@react-spectrum/textfield'
import { Link } from '@react-spectrum/link'
import { Picker, Item } from '@react-spectrum/picker'
import { Form } from '@react-spectrum/form'
import { Flex } from '@react-spectrum/layout'
import { ProgressCircle } from '@react-spectrum/progress'
import { Heading, Text } from '@react-spectrum/text';
// local imports
import './App.css'
import { actionWebInvoke } from './utils'
import actions from './config.json'
/* Here is your entry point React Component, this class has access to the Adobe Experience Cloud Shell runtime object */
export default class App extends React.Component {
constructor (props) {
super(props)
// error handler on UI rendering failure
this.onError = (e, componentStack) => {}
// component to show if UI fails rendering
this.fallbackComponent = ({ componentStack, error }) => (
<React.Fragment>
<h1 style={{ textAlign: 'center', marginTop: '20px' }}>Something went wrong :(</h1>
<pre>{ componentStack + '\n' + error.message }</pre>
</React.Fragment>
)
this.state = {
actionSelected: null,
actionResponse: null,
actionResponseError: null,
actionHeaders: null,
actionHeadersValid: null,
actionParams: null,
actionParamsValid: null,
actionInvokeInProgress: false
}
console.log('runtime object:', this.props.runtime)
console.log('ims object:', this.props.ims)
// use exc runtime event handlers
// respond to configuration change events (e.g. user switches org)
this.props.runtime.on('configuration', ({ imsOrg, imsToken, locale }) => {
console.log('configuration change', { imsOrg, imsToken, locale })
})
// respond to history change events
this.props.runtime.on('history', ({ type, path }) => {
console.log('history change', { type, path })
})
}
static get propTypes () {
return {
runtime: PropTypes.any,
ims: PropTypes.any
}
}
// parses a JSON input and adds it to the state
async setJSONInput (input, stateJSON, stateValid) {
let content
let validStr = null
if (input) {
try {
content = JSON.parse(input)
validStr = 'valid'
} catch (e) {
content = null
validStr = 'invalid'
}
}
this.setState({ [stateJSON]: content, [stateValid]: validStr })
}
// invokes a the selected backend actions with input headers and params
async invokeAction () {
this.setState({ actionInvokeInProgress: true })
const action = this.state.actionSelected
const headers = this.state.actionHeaders || {}
const params = this.state.actionParams || {}
// all headers to lowercase
Object.keys(headers).forEach(h => {
const lowercase = h.toLowerCase()
if (lowercase !== h) {
headers[lowercase] = headers[h]
headers[h] = undefined
delete headers[h]
}
})
// set the authorization header and org from the ims props object
if (this.props.ims.token && !headers.authorization) {
headers.authorization = 'Bearer ' + this.props.ims.token
}
if (this.props.ims.org && !headers['x-gw-ims-org-id']) {
headers['x-gw-ims-org-id'] = this.props.ims.org
}
try {
// invoke backend action
const actionResponse = await actionWebInvoke(action, headers, params)
// store the response
this.setState({ actionResponse, actionResponseError: null, actionInvokeInProgress: false })
console.log(`Response from ${action}:`, actionResponse)
} catch (e) {
// log and store any error message
console.error(e)
this.setState({ actionResponse: null, actionResponseError: e.message, actionInvokeInProgress: false })
}
}
render () {
return (
// ErrorBoundary wraps child components to handle eventual rendering errors
<ErrorBoundary onError={ this.onError } FallbackComponent={ this.fallbackComponent } >
<Provider UNSAFE_className='provider' theme={ theme }>
<Flex UNSAFE_className='main'>
<Heading UNSAFE_className='main-title'>Welcome to OnkarAnalyticsIO!</Heading>
<Flex UNSAFE_className='main-actions'>
<h3 className='actions-title'>Run your application backend actions</h3>
{ Object.keys(actions).length > 0 &&
<Form UNSAFE_className='actions-form' necessityIndicator='label'>
<Picker
placeholder='select an action'
aria-label='select an action'
items={ Object.keys(actions).map(k => ({ name: k })) }
itemKey='name'
onSelectionChange={ name => this.setState({ actionSelected: name, actionResponseError: null, actionResponse: null }) }>
{ item => <Item key={item.name}>{ item.name }</Item> }
</Picker>
<TextField
label='headers'
placeholder='{ "key": "value" }'
validationState={ this.state.actionHeadersValid }
onChange={ input => this.setJSONInput(input, 'actionHeaders', 'actionHeadersValid' ) }/>
<TextField
label='params'
placeholder='{ "key": "value" }'
validationState={ this.state.actionParamsValid }
onChange={ input => this.setJSONInput(input, 'actionParams', 'actionParamsValid' ) }/>
<Flex UNSAFE_className='actions-invoke'>
<Button
UNSAFE_className='actions-invoke-button'
variant='primary'
onPress={ this.invokeAction.bind(this) }
isDisabled={ !this.state.actionSelected }>
Invoke
</Button>
<ProgressCircle
UNSAFE_className='actions-invoke-progress'
aria-label='loading'
isIndeterminate
isHidden={ !this.state.actionInvokeInProgress }/>
</Flex>
</Form>
}
{ Object.keys(actions).length === 0 &&
<Text>You have no actions !</Text>
}
{ this.state.actionResponseError &&
<Text UNSAFE_className='actions-invoke-error'>
Failure! See the error in your browser console.
</Text>
}
{ !this.state.actionError && this.state.actionResponse &&
<Text UNSAFE_className='actions-invoke-success'>
Success! See the response content in your browser console.
</Text>
}
</Flex>
<Flex UNSAFE_className='main-doc'>
<h3 className='doc-title'>Useful documentation for your app</h3>
<Link UNSAFE_className='doc-item'>
<a href='https://github.com/AdobeDocs/project-firefly/blob/master/README.md#project-firefly-developer-guide' target='_blank'>
Firefly Apps
</a>
</Link>
<Link UNSAFE_className='doc-item'>
<a href='https://github.com/adobe/aio-sdk#adobeaio-sdk' target='_blank'>
Adobe I/O SDK
</a>
</Link>
<Link UNSAFE_className='doc-item'>
<a href='https://adobedocs.github.io/adobeio-runtime/' target='_blank'>
Adobe I/O Runtime
</a>
</Link>
<Link UNSAFE_className='doc-item'>
<a href='https://react-spectrum.adobe.com/react-spectrum/index.html' target='_blank'>
React Spectrum
</a>
</Link>
</Flex>
</Flex>
</Provider>
</ErrorBoundary>
)
}
}
Solved! Go to Solution.
Topics help categorize Community content and increase your ability to discover relevant content.
Views
Replies
Total Likes
Problem 1: please try giving all the `@react-spectrum` dependencies version "3.0.1", then `npm install` and re-run your app. This is the tracking issue for the record: https://github.com/adobe/aio-cli/issues/201.
Problem 2: if you selected "Adobe Analytics" from the template with `aio app init`, your .env file would have a variable called `ANALYTICS_COMPANY_ID` commented out. Please set your company ID there, uncomment (by removing the hash "#"), and then re-run the app. The env var is picked up by the app according to the mapping in manifest.yml.
Views
Replies
Total Likes
Hi there - To troubleshoot problem 1, could you please share your code in web-src/src/App.js ? Did you modify anything in the web-src/ folder?
Views
Replies
Total Likes
Problem 1: please try giving all the `@react-spectrum` dependencies version "3.0.1", then `npm install` and re-run your app. This is the tracking issue for the record: https://github.com/adobe/aio-cli/issues/201.
Problem 2: if you selected "Adobe Analytics" from the template with `aio app init`, your .env file would have a variable called `ANALYTICS_COMPANY_ID` commented out. Please set your company ID there, uncomment (by removing the hash "#"), and then re-run the app. The env var is picked up by the app according to the mapping in manifest.yml.
Views
Replies
Total Likes
thanks duypnguyen. I have updated the question with app.js code.
Views
Replies
Total Likes
@prashantonkar - could you please try upgrading all @react-spectrum dependencies to "3.0.1"? It did work for me. We will work on a fix to update the versions in the template
Views
Replies
Total Likes
Views
Replies
Total Likes
If you leave the default settings from the template, meaning "require-adobe-auth" is set to true, the Runtime action expects the bearer token in the authorization header. You could find more details here: https://github.com/AdobeDocs/project-firefly/blob/master/guides/security_overview.md.
The IMS token is generated for the API service you work with (Analytics). The Runtime action only validates that it belongs to the right org and is valid to access the service. Hence in AEM particularly, you would use the IMS config for Analytics (if available), or add it to your AEM instance.
Views
Replies
Total Likes
Views
Replies
Total Likes
Views
Replies
Total Likes
You can read more about authentication for Adobe I/O API services here: https://www.adobe.io/authentication.html.
As mentioned in the earlier comment, the authentication check in a Firefly app is described here: https://github.com/AdobeDocs/project-firefly/blob/master/guides/security_overview.md.
You may want to reach our to AEM Customer Care / Forum about IMS Access Token Provider and how to configure it using the credentials returned by Adobe I/O Console.
I assume you selected JWT token for the Analytics API service. In brief, the access token is generated on the AEM side using the private key you set for it (either generated by AEM or uploaded by you). When it makes request to your Firefly service / app, the token should be attached to the headers, which is then validated by the Firefly app to assure that your request is authenticated to access the integrated service. Once validated, the app will retrieve data from Analytics API, compute your logics and returns the results back to AEM.
Does it answer your question?
Views
Replies
Total Likes
thanks duypnguyen. I am able to get the token by reading the documentation you shared. Also this link helped me too in generating a certificate and accessing it in AEM: https://docs.adobe.com/content/help/en/experience-manager-learn/foundation/authentication/set-up-pub... and by using AccessTokenProvider.
Views
Replies
Total Likes
Views
Likes
Replies