2017년 7월 23일 일요일

Unable to find component "TaifunTools" while loading project


it has been reported an issue with 2 extensions in the same project, see also this thread in the Thunkable forum
and I can reproduce this issue also on the App Inventor server like this

1. Create a new project
2. import the TaifunTools extension and another extension, for example the TaifunMath extension
3. Drag both extensions to the working area
4. save the project and close App Inventor
5. Open App Inventor again and the error message appears, the project is not able to load anymore, also it is not possible to export the aia file anymore

Attached the aia file (was exported before closing App Inventor) and the 2 extensions
Both extensions have been compiled recently using the current App Inventor sources.
@MIT: please investigate. Thank you in advance. The project number for the test project is #5792277635792896


--
I think the issue is with your extension. If you combine other extensions of yours, nothing will happen. 

--
thank you Moliata for trying to help

the question is, what is the issue exactly? and what needs to be done to avoid this... and this question most probably only the MIT App Inventor team can answer...

btw. the same problem happens with TaifunTools together with TaifunSQlite
it does not happen for TaifunTools together with TaifunWifi
all these extensions have been compiled recently using the current App Inventor sources

up to now most of my extensions still have been compiled in May 2017 or earlier using the older App Inventor sources


--
I looked at the project. The issue is that the extensions in question are in the same package (com.puravidaapps). The problem occurs due to the following sequence of events:

1. You upload the first extension, the server unpacks the aix, and then sends back the components.json file. This is used to populate the palette with the first extension.
2. You upload the second extension, the server unpacks it and, given that the files are in the same package name, this overwrites the components.json from the first extension. The server and then sends back the components.json. The palette is populated with the second component.
3. You create the two instances.
4. After reloading, only the newer components.json file is sent from the server, so the first component is missing and yields the error.

The server expects that if the package name is the same, that the intersection of the classes will not be disjoint, but in this case it is and violating that assumption is the cause of the error. Short term, we can add a mechanism so that when there is already an extension using the package name but not a superset of the extensions already present it returns an error. Longer term, you should migrate each extension into its own package name so that there isn't a collision and/or release a single extension bundle that groups them together if they are going to share the package name.

--
we already talked about package names last year in November here https://groups.google.com/d/msg/app-inventor-dev/vNxCIp4WaZ8/z7WDw6YtCQAJ
this was your suggestion
 Looking at the contents of your AIX files, it appears you are placing all of your extensions in the same package, which makes the ant extensions script include all of them in any AIX you build. The current best practice is to have a package per extension that contains all classes required for the extension so you may want to split up your classes accordingly. You could also strip out the unneeded classes in files/AndroidRuntime.jar on a per-extension basis to ensure backwards compatibility by not changing the package name. However, it's probably best to perform the refactoring now to save future headaches.
to use new package names means, after importing a new version of an extension into a project, the extension is identified as new extension and not as update of the old extension anymore
so is my understanding correct, now with the recent change in the App Inventor sources, I am forced to use separate package names?

--
as test I now took the screenshot extension and modified the package name from com.puravidaapps to com.puravidaapps.screenshot and built the extension

to my surprise, importing the new version results in replacing the existing old version of the extension in the project (the upgrade window does not show up!), and after looking into the aia file using 7zip, I now can find 2 folders inside
- com.puravidaapps.TaifunScreenshot (having the files of the old version) and
- com.puravidaapps.screenshot (having the files of the new version)

it looks like the upgrade process from an old extension (built using the old App Inventor sources) to a new version (built using the new App Inventor sources) has not been considered completely? 

attached please find
- aia file including the old extension (Version 1b)
- aix file (new version of the extension)
- aia file after importing the new version of the extension (Version 1c)


--
It depends on your goals. You can either:

1. Use two separate package names (which was my first suggestion in that post), and in that case users will have change their blocks over, or
2. Package a single aix with all of the extensions in the same bundle. When they load the new extension, the server should replace all of the existing extensions with the same package name. However, since this is a single package, you can't distribute pieces separately.

Note that this should only affect new imports of the extensions. Projects with the older versions of the extensions built with the old framework should continue to operate normally. In either cases 1 or 2 new projects with the new extensions will operate normally. The only issue becomes when your users want to upgrade an existing extension. (2) will likely make that path easier than (1).

Technically there is a third option that while I don't recommend it would maintain the existing semantics. Inside each AIX you can rename the com.puravidaapps directory back to an extension-specific directory (e.g., com.puravidaapps.TaifunMath). This will maintain that the files in each extension won't override complementary extensions with the same package name and upgrade accordingly. However, this makes building your extensions slightly more involved because you have to manually rename the internals of the extension file.

--
The extension upgrade mechanism considers only considers when the fully qualified class name doesn't change. For example, there's no guarantee that com.puravidaapps.screenshot.TaifunScreenshot is an upgrade to com.puravidaapps.TaifunScreenshot, or vice versa, or that com.example.FoobarScreenshot is an upgrade to both. For App Inventor components, we can handle these things by providing upgrade code in JavaScript to handle changes to property names, methods, even classes. But since we don't have a mechanism for extension developers to execute code within the app engine context there isn't a sophisticated way to handle extension upgrades. We are discussing adding some form of JavaScript execution for extensions to handle visible extensions, in which case it will open the way for more complex upgrade strategies for extensions.

--
my goal is to keep the existing extensions backward compatible

so if I choose to use separate package names for existing extensions, then I additionally have to change the class names to avoid extension upgrade issues (see my last post)... but changing the class name results in a completely new extension and therefore loss of backward compatibility. Also I would have to update all my documentation...
I will look into the 3rd option. Thank you.

--

댓글 없음:

댓글 쓰기