Pages

Wednesday, December 24, 2008

Flex : Solution to Error: unable to resolve '/assets/icons/icon.png' for transcoding using Embed tag

It so happens that when we work on IDE like flex builder, every thing seems to be working fine but the same would not work other wise.

Problem:

We use maven as build tool, and my mxml and css has tags like:

[Embed(source='/assets/icons/icon.png')]

We get the error

Error: unable to resolve '/assets/icons/icon.png' for transcoding

You have tried to put assets folder in line with the main application file, in common and any other place you can think of, and still this problem is not resolved.
You have also tried with or with out '/' in front of 'assets' in your Embed tag as given by many people around the Internet.

Solution:

With all the assets that will be used in the Embed tag, create a 'swc' library and put it in the mxmlc class path. And use with out a forward slash in the beginning,as in, assets/icons/icon.png.

Next Problem:

How do you create a swc file?

Solution:

The method I adopted in the beginning to just to get my app up as I had a release next day was, if you own Flexbuilder, then create a Flex Library project, and include all these resources in the library. Use this generated library in the mxmlc build path to build the project.

Next Problem:

I can not always keep adding a resource as and when included into my Flex builder library project to generate the swc. So, I will have to automate this. Before, I build the mxmlc, I have to create the swc, and add it in the build path of mxmlc so that the compilation is successful.

Solution:

This is done using the compc compiler. So, I will have to use this compiler to generate the swc of the resources being embedded in the Flex project, then run the mxmlc.

Next Problem:

Running compc directly from command line, to include files, takes the form:

compc -output assets.swc -include-file <file_alias_1> <real file path 1> .. -include-file <file_alias_n> <real file path  n>

or

We can use the compc task in the maven ant run plugin. But, this compc task, can include only classes, and could not include all the resources.

Solution:

I assume that the folder structure is like below:

flex
|- libs
|- mainapp
     |--src
           |
           |-- index.mxml
           |-- assets
           |     |-- icons
           |    |-- images
           |-- css
           |-- pom.xml

The packages that Flex app uses can be any where, either in mainapp/src or out side it, but its configured in the class path of the mxmlc task in pom.xml.

Step 1: Add the following dependencies with in the maven-antrun-plugin.

<dependencies> 
<dependency>
<groupId>ant-contrib</groupId>
<artifactId>ant-contrib</artifactId>
<version>1.0b2</version>
</dependency>
<dependency>
<groupId>ant</groupId>
<artifactId>ant-jakarta-regexp</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>ant</groupId>
<artifactId>ant-nodeps</artifactId>
<version>1.6.5</version>
</dependency>
</dependencies>


Step 2: Define ant-contrib task as below:
<taskdef 
resource="net/sf/antcontrib/antlib.xml" classpathref="maven.plugin.classpath">
</taskdef>

Step 3: Before invoking the mxmlc task, add the below ant script. If you are not using maven, then directly use the below ant script in the ant build.xml, making sure the dependent jars are present in the ant/lib directory.
    <fileset id="assets.flex" dir="src" includes="**/*.jpg,**/*.png,**/*.css,**/*.swf,**/*.TTF,**/*.jpeg,**/*.xml" /> 
<pathconvert pathsep=" " property="assets.flex.output" refid="assets.flex" dirsep="/">
<map from="${basedir}/src/" to=""/>
</pathconvert>
<echo message="...Resources being considered..."/>
<var name="filelist" value=""/>
<var name="prefixfilelist" value="-include-file"/>
<for list="${assets.flex.output}" delimiter=" " param="asset">
<sequential>
<echo>Asset: @{asset}</echo>
<propertyregex property="prop"
input="@{asset}"
regexp="(.*)mainapp/src/(.*)"
select="\2"
casesensitive="false" />
<var name="filelist_tmp" value="${filelist}"/>
<var name="filelist" unset="true"/>
<var name="filelist" value="${filelist_tmp} ${prefixfilelist} ${prop} @{asset}"/>
<var name="prop" unset="true"/>
</sequential>
</for>
<echo message="-output assets.swc ${filelist}"/>
<exec executable="${FLEX_HOME}/bin/compc.exe" failonerror="true">
<arg line="-output ../libs/assets.swc ${filelist}"/>
</exec>

Its just a simple program that generates the required argument for compc compiler and invokes it, any developer should be able to read and understand this script. Hence, I will leave out the explanations part of it.


Step 4: Proceed with the mxmlc task with libs in the class path, sample is given below:
<mxmlc  file="src/index.mxml" 
output="../target/App.swf"
link-report="../target/report.xml"
warnings="false"
services="${CONFIG}/services-config.xml"
context-root = "/App"
>
<load-config filename="${FLEX_HOME}/frameworks/flex-config.xml"/>
<source-path path-element="${FLEX_HOME}/frameworks"/>
<compiler.library-path dir="${FLEX_HOME}/frameworks" append="true">
<include name="libs" />
</compiler.library-path>
<compiler.library-path dir="../." append="true">
<include name="libs" />
</compiler.library-path>
<compiler.source-path path-element="../mainapp/src"/>
</mxmlc>

This will make sure all your assets is present in the mxmlc build path, and the Embed transcode error does not occur.
I will put the entire ant run plugin in the pom file here for reference:    
<build> 
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<dependencies>
<dependency>
<groupId>ant-contrib</groupId>
<artifactId>ant-contrib</artifactId>
<version>1.0b2</version>
</dependency>
<dependency>
<groupId>ant</groupId>
<artifactId>ant-jakarta-regexp</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>ant</groupId>
<artifactId>ant-nodeps</artifactId>
<version>1.6.5</version>
</dependency>
</dependencies>
<executions>
<execution>
<phase>compile</phase>
<configuration>
<tasks>
<taskdef
resource="net/sf/antcontrib/antlib.xml" classpathref="maven.plugin.classpath">
</taskdef>
<taskdef resource="flexTasks.tasks" />
<fileset id="assets.flex" dir="src" includes="**/*.jpg,**/*.png,**/*.css,**/*.swf,**/*.TTF,**/*.jpeg,**/*.xml" />
<pathconvert pathsep=" " property="assets.flex.output" refid="assets.flex" dirsep="/">
<map from="${basedir}/src/" to=""/>
</pathconvert>
<echo message="...Resources being considered..."/>
<var name="filelist" value=""/>
<var name="prefixfilelist" value="-include-file"/>
<for list="${assets.flex.output}" delimiter=" " param="asset">
<sequential>
<echo>Asset: @{asset}</echo>
<propertyregex property="prop"
input="@{asset}"
regexp="(.*)mainapp/src/(.*)"
select="\2"
casesensitive="false" />
<var name="filelist_tmp" value="${filelist}"/>
<var name="filelist" unset="true"/>
<var name="filelist" value="${filelist_tmp} ${prefixfilelist} ${prop} @{asset}"/>
<var name="prop" unset="true"/>
</sequential>
</for>
<echo message="-output assets.swc ${filelist}"/>
<exec executable="${FLEX_HOME}/bin/compc.exe" failonerror="true">
<arg line="-output ../libs/assets.swc ${filelist}"/>
</exec>
<mxmlc file="src/index.mxml"
output="../target/App.swf"
link-report="../target/report.xml"
warnings="false"
services="${CONFIG}/services-config.xml"
context-root = "/App"
>
<load-config filename="${FLEX_HOME}/frameworks/flex-config.xml"/>
<source-path path-element="${FLEX_HOME}/frameworks"/>
<compiler.library-path dir="${FLEX_HOME}/frameworks" append="true">
<include name="libs" />
</compiler.library-path>
<compiler.library-path dir="../." append="true">
<include name="libs" />
</compiler.library-path>
<compiler.source-path path-element="../mainapp/src"/>
</mxmlc>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

10 comments:

  1. I came across your post having the same error using the mxmlc command line compiler and got it to work, without using the swc library as you suggested. Note that I have embeds in various places, including CSS stylesheets just like you.

    Here is my batch file if it helps
    SET SDK=E:\Program Files (x86)\Adobe\Flex Builder 3\sdks\3.0.0
    SET PROJ=C:\Projects\Thoropredictor
    C:
    cd %PROJ%\ThoroClient\src

    "%SDK%\bin\mxmlc.exe" -locale en_US -o "%PROJ%\ThoroClient\bin\ThoroClient.swf" -sp %PROJ%\ThoroClient\src -context-root Thoropredictor -services %PROJ%\WEB-INF\Flex\services-config.xml -l "%SDK%\frameworks\locale\en_US" -l "%SDK%\Frameworks\libs" -l %PROJ%\ThoroClient\libs\ -title ThoropredictorClient ThoroClient.mxml > ..\build.log 2>&1

    ReplyDelete
  2. Anonymous8:56 AM

    The ant build you have put doesn't explain anything at all - it didn't work - I am sick and tired of people putting stupid posts that don't work at all

    ReplyDelete
  3. Hi, The code that I have put is being used in a production application. So, it works.

    I am sure there may be some things that you may have overlooked. Let me know what is the problem that you are facing, I will try to help because I know how frustrating this problem is.

    ReplyDelete
  4. Hi, I have a similar problem with images. When I use the same image in different parts of the project, in all cases with the Embed tag, it works fine (the image is not copied to output folder).
    If I don't use the Embed tag (but check the 'copy non-embedded files to output folder) it also work (the image is copied to output folder).
    However, if I use the same image, sometimes using the Embed tag I sometimes not, the image is not copied to output folder and only the references to the file using the Embed tag work.
    Any ideas? Thanks

    ReplyDelete
  5. I think you are using Flex builder option to copy the non-embedded files. I have never used that, we write ant script to build and copy all the required images to the output folder.

    ReplyDelete
  6. Anonymous12:35 PM

    "Its just a simple program that generates the required argument for compc compiler and invokes it, any developer should be able to read and understand this script. Hence, I will leave out the explanations part of it."

    I think you should have left out that sentence.

    ReplyDelete
  7. Anonymous1:39 AM

    When I copy and paste your Step3 code in my build.xml and execute it gives me the following errro

    command line: Error: configuration variable 'include-file' value contains unknown token 'prop'

    How to solve it ?

    ReplyDelete
  8. sometimes you need to use ";" (semicolon) in all variable description, at the start of the class, if you dont write code using this end-line delimiter

    ReplyDelete
  9. I found the solution for this problem:

    The problem is with the underlying JDK.

    http://mytechieblog.blogspot.com/2011/06/error-unable-to-transcode-assetsxyzpng.html

    Cheers
    Aneesh

    ReplyDelete
  10. Anonymous1:52 PM

    4 years later and i was having the same problem with ant 1.8.2 on flex builder...

    But this post solution worked like a charm =)

    @Anonymous1:39 AM
    The error means that the compiler is reciving "${prop}" as a literal value, in the argument. You can see that appearing in the echo message as well:

    "-output ../libs/assets.swc -include-file ${prop} ..."

    This happens all the time when the propertyregex cant find the regular expression ur asking for. Modify "regexp" and "select" parameters to get the file names acording to the dir estructure of ur app. So keep an eye on the echo message.

    The autor of this post is assuming you already have ant-contrib, and that you're able to manipulate ant codes.

    ReplyDelete