How to import mp3 files or else

Hello,

I want to create an audio polymer template with a server sie java class. My MP3 files are placed in my frontend directory (src/main/webapp/frontend). The question is how to import these files into my application?

Greetings!

Without knowing exactly how you handle the files in the frontend I would say that you could have the files registered as StreamReasources from where the client can get them.
see: [Dynamic Content]
(https://vaadin.com/docs/v10/flow/advanced/tutorial-dynamic-content.html)

I would expect to register the resources to the session and give the url:s to the client to use like

StreamRegistration resource = ui.getSession().getResourceRegistry().registerResource(new StreamResource(name, streamFactory));
URI resourceUri = resource.getResourceUri();

// send the resourceUri.toString() to the client component

Note for register resource

    /**
     * Registers a stream resource in the session and returns registration
     * handler.
     * <p>
     * You can get resource URI to use it in the application (e.g. set an
     * attribute value or property value) via the registration handler. The
     * registration handler should be used to unregister resource when it's not
     * needed anymore. Note that it is the developer's responsibility to
     * unregister resources. Otherwise resources won't be garbage collected
     * until the session expires which causes memory leak.
     * 
     * @param resource
     *            stream resource to register
     * @return registration handler
     */

Thanks for your reply!

This solution don’t solved my problem. I want to use a solution like the ThemeResource from Vaadin 8. But ThemeResource don’t exist anymore.

To get the servlet context path to the file use

String url = "frontend://{path_to_file}";
String resolvedUrl = VaadinServlet.getCurrent().resolveResource(url);

This should be close to the same that ThemeResource in V8 returned.
The resource should be available for a request from the application.

  • Mikael

src/main/webapp/frontend URL normally is handled by the webserver itself (as a static resource).
If you don’t have a custom unusual configuration then src/main/webapp/ is the root folder for static Web resources that may be referenced directly and they are handled by the Web server.
This means that they are not handled by the Vaadin application. It’s the web server which just return
the content of the file without any servlets involving.

So if your web server has URL like http://example.com/ then file src/main/webapp/myfile.ext may be access directly as http://example.com/myfile.ext. In the same way file src/main/webapp/frontend/my.txt may be accessed via the http://example.com/frontend/myfile.ext URL.
Vaadin servlet won’t handle those files anyhow at all. Those are static resource handled by the web server.
So to be able to access those files you just may create a Java URL class and get them as any other HTTP resource from the web.

The question is why you want to access those files inside your application?
If those files are not intended to be accesible as a Web resource then you may just put them as a classpath resource and access them via Class::getResource or Class::getResourceAsStream.
If you want them available in the Web and also inside the application then you may use StreamResource as Mikael mentioned.

There is no such thing as ThemeResource in Flow, that’s true.
You may create a ticket to make functionality to solve your need in a simpler way.

Thanks for your reply!

I don’t want use the resource on server side, but on client side. I want to implement an audio component to play a notification sound on a user action. The MP3 file isn’t played by the audio HTML tag. My tag looks like:

<link rel="import" href="../../bower_components/polymer/polymer.html">

<dom-module id="sound-template">
    <template>
        <audio controls autoplay>
            <source src="[[sourcePath]
]" type="[[type]
]">
        </audio>
    </template>

    <script>
        class SoundTemplate extends Polymer.Element {
            static get is() {
                return 'sound-template';
            }
        }

        customElements.define(SoundTemplate.is, SoundTemplate);
    </script>
</dom-module>

The Java class is looking like:

@Tag("sound-template")
@HtmlImport("src/instruction/sound-template.html")
public class Sound extends PolymerTemplate<Sound.SoundModel>
{
    private static final long serialVersionUID = 3385584228063340684L;

    public void setSource(String sourcePath)
    {
        getModel().setSourcePath("sounds/" + sourcePath);
        getModel().setType("audio/mpeg");
    }

    public interface SoundModel extends TemplateModel
    {
        void setSourcePath(String sourcePath);

        void setType(String type);
    }
}

```

As I understand you need URL of the audio file to be able to send it from the server side to the client side where they are used in the template, right ?

So the question is just about constructing the URL of the resource.

I think you may use the same logic which we are using to access to the template files on the server side.
There is a method VaadinServlet::resolveResource which returns a path to get resource via the ServletContext::getResource method.

Here is the example how we use it in our code:
https://github.com/vaadin/flow/blob/master/flow-server/src/main/java/com/vaadin/flow/component/polymertemplate/DefaultTemplateParser.java#L102
https://github.com/vaadin/flow/blob/master/flow-server/src/main/java/com/vaadin/flow/component/polymertemplate/DefaultTemplateParser.java#L108

The second link referers to the servlet.getResourceAsStream call but it just simply delegates to the ServletContext::getResourceAsStream. Since you don’t need the content itself you may just call ServletContext::getResource which return a URL.

Thanks for your reply!

Yes, I want to load the resource on server side and pass the URI to the client!

I have tried it now with VaadinServlet::resolveResource. The HTML in production looks like this now:

<sound-template id="notificationSound">
	<audio id="audioElement" controls="" autoplay="">
		<source type="audio/mpeg" src="/./frontend/sounds/notification.mp3">
	</audio>
</sound-template>

My Java class looks like this:

public void setSource(String sourcePath)
{
	String path = VaadinServlet.getCurrent().resolveResource("frontend://sounds/" + sourcePath);
	getModel().setSourcePath(path);
	getModel().setType("audio/mpeg");
}

But the audio source is not playing in my browser (Google Chrome).

You are using only resolceResource method. Which just returns path.
You need URL, not a path. As I said to get the correct URL you should use ServletContext::getResource with path as an argument.

The other thing which I don’t really understand: why you don’t want to use relative URL in your template file?

If your component navigation target URL is http://example.com/myview then <source src="frontend/path_to_audio/[[audioName] ]" ... where audioName or sourcePath is a name of your audio file will work just fine.

My sound file was corrupt. :frowning:

But your solution is good and I have edit my code. Now all is working fine! Thank you a lot!

Very good.